Skip to content

Commit 448a43c

Browse files
authored
Add support for arrays of active event keys to Accordion (#1286)
* Add support for arrays of active event keys to Accordion * Add misc CSS things Nat wants * Fix css logic * Fix CSS to avoid doubling the top border
1 parent d3b2725 commit 448a43c

File tree

5 files changed

+122
-5
lines changed

5 files changed

+122
-5
lines changed

src/Accordion/Accordion.stories.tsx

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,48 @@ Default.args = {
6464
title: 'Accordion Toggle',
6565
};
6666

67+
export function AlwaysOpen(args) {
68+
return (
69+
<Accordion alwaysOpen>
70+
<AccordionItem eventKey="0">
71+
<AccordionToggle
72+
eventKey="0"
73+
leadingIcon={faCreditCard}
74+
{...args}
75+
/>
76+
<AccordionCollapse eventKey="0">
77+
<ul>
78+
<li>Item 1</li>
79+
<li>Item 2</li>
80+
<li>Item 3</li>
81+
</ul>
82+
</AccordionCollapse>
83+
</AccordionItem>
84+
<AccordionItem eventKey="1">
85+
<AccordionToggle
86+
eventKey="1"
87+
leadingIcon={faCreditCard}
88+
{...args}
89+
/>
90+
<AccordionCollapse eventKey="1">
91+
<ul>
92+
<li>Item 1</li>
93+
<li>Item 2</li>
94+
<li>Item 3</li>
95+
</ul>
96+
</AccordionCollapse>
97+
</AccordionItem>
98+
</Accordion>
99+
);
100+
}
101+
102+
AlwaysOpen.args = {
103+
chevronLeft: false,
104+
disabled: false,
105+
helperText: 'helper text',
106+
title: 'Accordion Toggle - always open',
107+
};
108+
67109
export function DefaultOpen(args) {
68110
return (
69111
<Accordion defaultActiveKey="1">
@@ -307,6 +349,50 @@ Borderless.args = {
307349
title: 'Accordion Toggle',
308350
};
309351

352+
export function BorderlessBorderBottomFlushToggles(args) {
353+
return (
354+
<Accordion flush>
355+
<AccordionItem borderless eventKey="0">
356+
<AccordionToggle
357+
borderBottom
358+
eventKey="0"
359+
flush
360+
{...args}
361+
/>
362+
<AccordionCollapse eventKey="0">
363+
<ul>
364+
<li>Item 1</li>
365+
<li>Item 2</li>
366+
<li>Item 3</li>
367+
</ul>
368+
</AccordionCollapse>
369+
</AccordionItem>
370+
<AccordionItem borderless eventKey="1">
371+
<AccordionToggle
372+
borderBottom
373+
eventKey="1"
374+
flush
375+
{...args}
376+
/>
377+
<AccordionCollapse eventKey="1">
378+
<ul>
379+
<li>Item 1</li>
380+
<li>Item 2</li>
381+
<li>Item 3</li>
382+
</ul>
383+
</AccordionCollapse>
384+
</AccordionItem>
385+
</Accordion>
386+
);
387+
}
388+
389+
BorderlessBorderBottomFlushToggles.args = {
390+
chevronLeft: false,
391+
disabled: false,
392+
helperText: 'helper text',
393+
title: 'Accordion Toggle',
394+
};
395+
310396
export function InCard(args) {
311397
return (
312398
<>

src/Accordion/AccordionCollapse.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@
1616
padding-top: 0px !important;
1717
}
1818
}
19+
/* If the parent AccordionToggle has a border-bottom applied, remove the top one here */
20+
.borderBottom {
21+
.AccordionCollapse {
22+
border-top: none;
23+
}
24+
}

src/Accordion/AccordionToggle.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
grid-template-areas: 'content chevron-right';
1111
padding: 16px 24px;
1212

13+
&.borderBottom {
14+
border-bottom: 1px solid var(--ux-gray-400);
15+
}
16+
17+
&.flush {
18+
padding: 16px 4px;
19+
}
20+
1321
&--right {
1422
grid-area: chevron-right;
1523

src/Accordion/AccordionToggle.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import AccordionContext from 'react-bootstrap/AccordionContext';
1010
import './AccordionToggle.scss';
1111
import { faChevronUp } from '@fortawesome/pro-solid-svg-icons';
1212

13+
import { isEventKeyActive } from './utils';
14+
1315
type AccordionToggleProps = {
16+
borderBottom?: boolean;
1417
/**
1518
Set Chevron icon to open/close quarter turn from lateral
1619
*/
@@ -30,6 +33,7 @@ type AccordionToggleProps = {
3033
*/
3134
disabled?: boolean;
3235
eventKey: string;
36+
flush?: boolean;
3337
helperText?: string;
3438
leadingIcon?: object;
3539
title?: string;
@@ -38,13 +42,15 @@ type AccordionToggleProps = {
3842
};
3943

4044
function AccordionToggle({
45+
borderBottom,
4146
children,
4247
chevronLateral,
4348
chevronLeft,
4449
chevronRight,
4550
collapsedText,
4651
disabled,
4752
eventKey,
53+
flush,
4854
helperText,
4955
leadingIcon,
5056
title,
@@ -54,10 +60,12 @@ function AccordionToggle({
5460
}: AccordionToggleProps) {
5561
const { activeEventKey } = React.useContext(AccordionContext);
5662

63+
const eventKeyIsActive = isEventKeyActive(eventKey, activeEventKey);
64+
5765
const [isCollapsed, setIsCollapsed] = useState(true);
5866

5967
const decoratedOnClick = useAccordionButton(eventKey, () => {
60-
if (eventKey !== activeEventKey) {
68+
if (!eventKeyIsActive) {
6169
setIsCollapsed(false);
6270
}
6371
setIsCollapsed((prev) => !prev);
@@ -68,14 +76,14 @@ function AccordionToggle({
6876
};
6977

7078
useEffect(() => {
71-
if (activeEventKey && eventKey !== activeEventKey) {
79+
if (!eventKeyIsActive) {
7280
handleCloseInactiveToggle();
7381
}
7482

75-
if (activeEventKey && eventKey === activeEventKey) {
83+
if (eventKeyIsActive) {
7684
setIsCollapsed(((prev) => !prev));
7785
}
78-
}, [activeEventKey, eventKey]);
86+
}, [eventKeyIsActive]);
7987

8088
return (
8189
<button
@@ -92,7 +100,7 @@ function AccordionToggle({
92100
type="button"
93101
onClick={decoratedOnClick}
94102
>
95-
<div className="AccordionToggle__container">
103+
<div className={classNames('AccordionToggle__container', { flush }, { borderBottom })}>
96104
<div className="AccordionToggle__container--content">
97105
{chevronLeft && (
98106
<span className="AccordionToggle__chevron-left">

src/Accordion/utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { AccordionEventKey } from 'react-bootstrap/esm/AccordionContext';
2+
3+
export function isEventKeyActive(eventKey: string | null | undefined,
4+
activeEventKey: AccordionEventKey) {
5+
if (!eventKey) return false;
6+
7+
return (Array.isArray(activeEventKey) && activeEventKey.includes(eventKey)) ||
8+
eventKey === activeEventKey;
9+
}

0 commit comments

Comments
 (0)