diff --git a/packages/unity-bootstrap-theme/src/js/collapse.js b/packages/unity-bootstrap-theme/src/js/collapse.js
new file mode 100644
index 0000000000..f13aa19984
--- /dev/null
+++ b/packages/unity-bootstrap-theme/src/js/collapse.js
@@ -0,0 +1,23 @@
+import { adjustShrinkingElementIfAboveViewport } from "@shared";
+
+import { EventHandler } from "./bootstrap-helper";
+
+function initCollapse() {
+ function accordionClick({target}) {
+ const targetHref = target.getAttribute("href");
+ if (target.getAttribute("data-bs-toggle") !== "collapse" || !targetHref || !targetHref.includes("#")) {
+ return; // Exit the function - not a collapse link
+ }
+
+ /**
+ * Find the first accordion that is currently collapsing or expanding
+ * Function will determine if scroll adjustment is needed
+ */
+ adjustShrinkingElementIfAboveViewport(document.querySelector(".collapsing"));
+ }
+ EventHandler.on(document, "click.uds.collapse", accordionClick);
+}
+
+EventHandler.on(window, "load.uds.collapse", initCollapse);
+
+export { initCollapse };
diff --git a/packages/unity-bootstrap-theme/src/js/unity-bootstrap.js b/packages/unity-bootstrap-theme/src/js/unity-bootstrap.js
index b3783e3931..a74bdc8747 100644
--- a/packages/unity-bootstrap-theme/src/js/unity-bootstrap.js
+++ b/packages/unity-bootstrap-theme/src/js/unity-bootstrap.js
@@ -5,6 +5,7 @@ import { initCalendar } from "./calendar.js";
import { initCardBodies } from "./card-bodies.js";
import { initRankingCard } from "./card-ranking.js";
import { initChart } from "./charts-and-graphs.js";
+import { initCollapse } from "./collapse.js";
import { initDataLayer } from "./data-layer.js";
import { initGlobalHeader } from "./global-header.js";
import { initHeroesVideo } from "./heroes-video.js";
@@ -19,6 +20,7 @@ const unityBootstrap = {
initAnchorMenu,
initBlockquoteAnimation,
initCalendar,
+ initCollapse,
initChart,
initDataLayer,
initFixedTable,
diff --git a/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss b/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss
index d165381a1c..165321cce5 100644
--- a/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss
+++ b/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss
@@ -691,6 +691,13 @@ Cards - Table of Contents
7. Accordion
--------------------------------------------------------------------*/
.accordion {
+ &:focus {
+ outline: none!important;
+ box-shadow: 0 0 0 1px $uds-color-base-gray-7 !important;
+ border: 1px solid $uds-color-base-gray-7 !important;
+ margin: 4px;
+ width: -webkit-fill-available;
+ }
.accordion-item {
border-bottom: 1px solid $uds-color-base-gray-3;
border-top: 1px solid $uds-color-base-gray-3;
diff --git a/packages/unity-bootstrap-theme/stories/atoms/accordion/accordion.examples.stories.js b/packages/unity-bootstrap-theme/stories/atoms/accordion/accordion.examples.stories.js
index 78db067aba..c246c9b023 100644
--- a/packages/unity-bootstrap-theme/stories/atoms/accordion/accordion.examples.stories.js
+++ b/packages/unity-bootstrap-theme/stories/atoms/accordion/accordion.examples.stories.js
@@ -8,484 +8,11 @@ export default {
parameters: { controls: { disable: true } },
};
-export const FoldableCardDefaultOpen = () =>
+export const Default = () =>
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
- ad minim veniam, quis nostrud
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor
-
- This uses the
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
- Aenean commodo ligula eget dolor. Aenean massa. Cum sociis
- natoque penatibus et magnis dis parturient montes, nascetur
- ridiculus mus. Donec quam felis, ultricies nec, pellentesque
- eu, pretium quis, sem.
-
- This uses the
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
- Aenean commodo ligula eget dolor. Aenean massa. Cum sociis
- natoque penatibus et magnis dis parturient montes, nascetur
- ridiculus mus. Donec quam felis, ultricies nec, pellentesque
- eu, pretium quis, sem.
-
-
-
- This is a quaternary headline
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
- Quatrenary Headline
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
- Quatrenary Headline
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
- Quatrenary Headline
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
-
- This is a level five headline. There's a fancy word for that too.
-
-
-
-
- .desktop-disable-lg
class.
-
-
-
- .desktop-disable-xl
class.
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud -
-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud -
-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor -
-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod - tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim - veniam, quis nostrud -
-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod - tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim - veniam, quis nostrud -
-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod - tempor -
-{getLoremSentences(12, i++)}
+{getLoremSentences(22, i++)}
+{getLoremSentences(10, i++)}
+{getLoremSentences(35, i++)}
+{getLoremSentences(22, i++)}
+{getLoremSentences(12, i++)}
+{getLoremSentences(42, i++)}
+{getLoremSentences(19, i++)}
+{getLoremSentences(12, i++)}
+{getLoremSentences(10, i++)}
+{getLoremSentences(35, i++)}
+{getLoremSentences(22, i++)}
+{getLoremSentences(12, i++)}
+{getLoremSentences(42, i++)}
+{getLoremSentences(19, i++)}
+{getLoremSentences(12, i++)}
+{getLoremSentences(10, i++)}
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
", + }, + }, + { + content: { + header: "Accordion Card 2, Large Content", + body: `${getLoremSentences(35, i++)}
+${getLoremSentences(22, i++)}
+${getLoremSentences(12, i++)}
+${getLoremSentences(42, i++)}
+${getLoremSentences(19, i++)}
+${getLoremSentences(12, i++)}
+${getLoremSentences(10, i++)}
+${getLoremSentences(35, i++)}
+${getLoremSentences(22, i++)}
+${getLoremSentences(12, i++)}
+${getLoremSentences(42, i++)}
+${getLoremSentences(19, i++)}
+${getLoremSentences(12, i++)}
+${getLoremSentences(10, i++)}
+ `, + }, + }, + { + content: { + header: "Accordion Card 3", + body: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+${getLoremSentences(35, i++)}
+${getLoremSentences(22, i++)}
`, + }, + }, + ], + openedCard: 2, + }, +}; export const ColorCombinations = Template.bind({}); ColorCombinations.args = { cards: [ diff --git a/packages/unity-react-core/src/components/Accordion/AccordionCard/AccordionCard.jsx b/packages/unity-react-core/src/components/Accordion/AccordionCard/AccordionCard.jsx index 7953aca0ce..118ab6118b 100644 --- a/packages/unity-react-core/src/components/Accordion/AccordionCard/AccordionCard.jsx +++ b/packages/unity-react-core/src/components/Accordion/AccordionCard/AccordionCard.jsx @@ -1,7 +1,7 @@ // @ts-check import classNames from "classnames"; import PropTypes from "prop-types"; -import React from "react"; +import React, { forwardRef } from "react"; import { sanitizeDangerousMarkup } from "../../../../../../shared"; import { accordionCardPropTypes } from "../../../core/models/shared-prop-types"; @@ -11,77 +11,104 @@ import { GaEventWrapper } from "../../GaEventWrapper/GaEventWrapper"; * @typedef {import('../../../core/types/shared-types').AccordionCardItemProps} AccordionCardItemProps */ +/** + * @typedef {import('../../../core/types/shared-types').AccordionCard} AccordionCard + */ + /** * @param {AccordionCardItemProps} props * @returns {JSX.Element} * @ignore */ -export const AccordionCard = ({ id, item, openCard, onClick, gaData }) => { - const isOpen = id === openCard; - /** - * event to open accordion is happening on the closed accordion - * so the action seem backwards but: - * open will send an event with action "close" - * close will send an event with action "open" - * */ +export const AccordionCard = forwardRef( + ( + /** @type {AccordionCardItemProps} */ { + id, + parentId, + /** @type {AccordionCard} */ item, + openCard, + onClick, + gaData, + }, + ref + ) => { + const isOpen = id === openCard; + /** + * event to open accordion is happening on the closed accordion + * so the action seem backwards but: + * open will send an event with action "close" + * close will send an event with action "open" + * */ - const gaAction = !isOpen ? "close" : "open"; - return ( -