diff --git a/README.md b/README.md index 9bb6656a..3c701c7e 100644 --- a/README.md +++ b/README.md @@ -86,10 +86,18 @@ We recommend that you copy them into your own app and modify them to suit your n - accordion + allowMultipleExpanded + Boolean + false + Don't close all the others when expanding an + AccordionItem + + + allowZeroExpanded Boolean - true - Open only one item at a time or not + false + Close an AccordionItem when it's the only + one expanded onChange @@ -133,10 +141,10 @@ We recommend that you copy them into your own app and modify them to suit your n CSS class(es) applied to the component - hideBodyClassName + expandedClassName String null - Class name for hidden body state + Class name for expanded panel state uuid @@ -168,10 +176,10 @@ We recommend that you copy them into your own app and modify them to suit your n CSS class(es) applied to the component - hideBodyClassName + expandedClassName String null - Class name for hidden body state + Class name for expanded panel state @@ -197,10 +205,10 @@ We recommend that you copy them into your own app and modify them to suit your n CSS class(es) applied to the component - hideBodyClassName + expandedClassName String - accordion__panel--hidden - Class name for hidden body state + accordion__panel--expanded + Class name for expanded panel state @@ -222,29 +230,23 @@ We recommend that you copy them into your own app and modify them to suit your n ### What this project is doing accessibility-wise? -This project manages two types of Accordions, with single or multiple items open. +This project manages Accordions with several options available for allowing/not allowing multiple items to be open at once, and allowing/not allowing all items to be closed. -#### Single item +#### Single item open -> Use this with with props `accordion` set to `true` on `Accordion`. +> Use this with with props `allowMultipleExpanded` set to `false` on `Accordion`. -For this type of Accordion, you will get the following `role` set up on your elements: +#### Multiple items open -- Accordion: `tablist` -- AccordionItem: no specific role -- AccordionItemHeading: `tab` -- AccordionItemPanel: `tabpanel` +> Use this with with props `allowMultipleExpanded` set to `true` on `Accordion`. -#### Multiple items +#### One item must remain open -For this type of Accordion, you will get the following `role` set up on your elements: +> Use this with with props `allowZeroExpanded` set to `false` on `Accordion`. -> Use this with with props `accordion` set to `false` on `Accordion`. +#### All items can be closed -- Accordion: no specific role -- AccordionItem: no specific role -- AccordionItemHeading: `button` -- AccordionItemPanel: no specific role +> Use this with with props `allowZeroExpanded` set to `true` on `Accordion`. # Browser support diff --git a/demo/src/index.tsx b/demo/src/index.tsx index f7d0f1cd..4f1daa61 100644 --- a/demo/src/index.tsx +++ b/demo/src/index.tsx @@ -212,10 +212,10 @@ const Example = (): JSX.Element => ( CSS class(es) applied to the component - hideBody ClassName + expandedClassName String - accordion__panel--hidden - Class name for hidden body state + accordion__panel--expanded + Class name for expanded panel state @@ -261,8 +261,8 @@ const Example = (): JSX.Element => ( Boolean false - Open only one item at a time or - not + Don't close all the others when + expanding an AccordionItem @@ -395,11 +395,12 @@ const Example = (): JSX.Element => ( - hideBody ClassName + expandedClassName String - accordion__panel--hidden + accordion__panel--expanded - Class name for hidden body state + Class name for expanded panel + state diff --git a/package.json b/package.json index 4a462bff..53992e58 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,10 @@ }, { "name": "Thibaud Colas" + }, + { + "name": "Cate Palmer", + "url": "https://github.com/catepalmer" } ], "license": "MIT", diff --git a/src/Accordion/Accordion.spec.tsx b/src/Accordion/Accordion.spec.tsx index c8e591ea..5c541c48 100644 --- a/src/Accordion/Accordion.spec.tsx +++ b/src/Accordion/Accordion.spec.tsx @@ -80,18 +80,18 @@ describe('Accordion', () => { }); it('works with multiple pre expanded accordion. Extra expands are just ignored.', () => { - const hideBodyClassName = 'HIDE'; + const expandedClassName = 'EXPANDED'; const wrapper = mount( Fake Child Fake Child @@ -106,7 +106,7 @@ describe('Accordion', () => { ).toEqual(1); expect( wrapper.findWhere((item: ReactWrapper) => - item.hasClass(hideBodyClassName), + item.hasClass(expandedClassName), ).length, ).toEqual(1); }); diff --git a/src/AccordionItem/AccordionItem.spec.tsx b/src/AccordionItem/AccordionItem.spec.tsx index 81d0576f..f89aa702 100644 --- a/src/AccordionItem/AccordionItem.spec.tsx +++ b/src/AccordionItem/AccordionItem.spec.tsx @@ -140,19 +140,19 @@ describe('AccordionItem', () => { expect(wrapper.find('div').prop('className')).toBe('testCSSClass'); }); - it('renders with different hideBodyClassName', () => { + it('renders with different expandedClassName', () => { const wrapper = mount( , ); expect(wrapper.find('div').prop('className')).toEqual( - 'AccordionItem AccordionItem--hidden', + 'AccordionItem AccordionItem--expanded', ); }); diff --git a/src/AccordionItem/AccordionItem.tsx b/src/AccordionItem/AccordionItem.tsx index 59fa3745..a06d2699 100644 --- a/src/AccordionItem/AccordionItem.tsx +++ b/src/AccordionItem/AccordionItem.tsx @@ -8,7 +8,7 @@ import { UUID } from '../ItemContainer/ItemContainer'; type AccordionItemProps = React.HTMLAttributes & { uuid: UUID; - hideBodyClassName?: string; + expandedClassName?: string; expanded?: boolean; accordionStore: AccordionContainer; }; @@ -39,7 +39,7 @@ class AccordionItem extends React.Component { const { uuid, className, - hideBodyClassName, + expandedClassName, accordionStore, expanded, ...rest @@ -57,8 +57,8 @@ class AccordionItem extends React.Component { return (
diff --git a/src/AccordionItem/AccordionItem.wrapper.tsx b/src/AccordionItem/AccordionItem.wrapper.tsx index b7e6dcfe..960882fc 100644 --- a/src/AccordionItem/AccordionItem.wrapper.tsx +++ b/src/AccordionItem/AccordionItem.wrapper.tsx @@ -10,7 +10,7 @@ import { Provider as ItemProvider } from '../ItemContainer/ItemContainer'; import AccordionItem from './AccordionItem'; type AccordionItemWrapperProps = React.HTMLAttributes & { - hideBodyClassName?: string; + expandedClassName?: string; expanded?: boolean; uuid?: string; }; @@ -32,7 +32,7 @@ export default class AccordionItemWrapper extends React.Component< static defaultProps: AccordionItemWrapperProps = { className: 'accordion__item', - hideBodyClassName: '', + expandedClassName: '', expanded: false, uuid: undefined, }; diff --git a/src/AccordionItem/__snapshots__/AccordionItem.spec.tsx.snap b/src/AccordionItem/__snapshots__/AccordionItem.spec.tsx.snap index cf9f9dc3..bb90f0cb 100644 --- a/src/AccordionItem/__snapshots__/AccordionItem.spec.tsx.snap +++ b/src/AccordionItem/__snapshots__/AccordionItem.spec.tsx.snap @@ -22,7 +22,7 @@ exports[`AccordionItem renders correctly with allowMultipleExpanded false 1`] =
@@ -55,7 +55,7 @@ exports[`AccordionItem renders correctly with allowMultipleExpanded true 1`] = `
@@ -88,7 +88,7 @@ exports[`AccordionItem renders correctly with allowZeroExpanded false 1`] = `
@@ -121,7 +121,7 @@ exports[`AccordionItem renders correctly with allowZeroExpanded true 1`] = `
@@ -157,7 +157,7 @@ exports[`AccordionItem renders correctly with other blocks inside 1`] = `
@@ -190,7 +190,7 @@ exports[`AccordionItem renders correctly with other blocks inside 2 1`] = `
diff --git a/src/AccordionItemHeading/AccordionItemHeading.spec.tsx b/src/AccordionItemHeading/AccordionItemHeading.spec.tsx index c0812585..3560bddd 100644 --- a/src/AccordionItemHeading/AccordionItemHeading.spec.tsx +++ b/src/AccordionItemHeading/AccordionItemHeading.spec.tsx @@ -70,20 +70,19 @@ describe('AccordionItemHeading', () => { expect(wrapper.find('div').hasClass(className)).toEqual(true); }); - it('renders with different hideBodyClassName', () => { - const hideBodyClassName = 'hideBodyClassName'; - const wrapper = mountItem( - , - ); - expect(wrapper.find('div').hasClass(hideBodyClassName)).toEqual(true); - }); + it('renders with different expandedClassName when item is expanded', () => { + const expandedClassName = 'expandedClassName'; - it("doesn't present hideBodyClassName when collapsed", () => { - const hideBodyClassName = 'hideBodyClassName'; - const wrapper = mountItem( - , + const wrapper = mount( + + + + + , ); - expect(wrapper.find('div').hasClass(hideBodyClassName)).toEqual(true); + expect(wrapper.find('div').hasClass(expandedClassName)).toEqual(true); }); it('toggles state when clicked', async () => { diff --git a/src/AccordionItemHeading/AccordionItemHeading.tsx b/src/AccordionItemHeading/AccordionItemHeading.tsx index 57a705d9..84e41a9b 100644 --- a/src/AccordionItemHeading/AccordionItemHeading.tsx +++ b/src/AccordionItemHeading/AccordionItemHeading.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { UUID } from '../ItemContainer/ItemContainer'; type AccordionItemHeadingProps = React.HTMLAttributes & { - hideBodyClassName: string; + expandedClassName: string; expanded: boolean; uuid: UUID; disabled: boolean; @@ -32,7 +32,7 @@ export default class AccordionItemHeading extends React.Component< render(): JSX.Element { const { className, - hideBodyClassName, + expandedClassName, setExpanded, expanded, uuid, @@ -42,8 +42,9 @@ export default class AccordionItemHeading extends React.Component< const id = `accordion__heading-${uuid}`; const ariaControls = `accordion__panel-${uuid}`; + const headingClassName = classnames(className, { - [hideBodyClassName]: hideBodyClassName && !expanded, + [expandedClassName]: expandedClassName && expanded, }); return ( diff --git a/src/AccordionItemHeading/AccordionItemHeading.wrapper.tsx b/src/AccordionItemHeading/AccordionItemHeading.wrapper.tsx index 31f481d1..646f2ecb 100644 --- a/src/AccordionItemHeading/AccordionItemHeading.wrapper.tsx +++ b/src/AccordionItemHeading/AccordionItemHeading.wrapper.tsx @@ -12,7 +12,7 @@ import { import { default as AccordionItemHeading } from './AccordionItemHeading'; type AccordionItemHeadingWrapperProps = React.HTMLAttributes & { - hideBodyClassName: string; + expandedClassName: string; }; type AccordionItemHeadingWrapperState = {}; @@ -32,7 +32,7 @@ export default class AccordionItemHeadingWrapper extends React.Component< static defaultProps: AccordionItemHeadingWrapperProps = { className: 'accordion__heading', - hideBodyClassName: '', + expandedClassName: '', }; render(): JSX.Element { diff --git a/src/AccordionItemPanel/AccordionItemPanel.spec.tsx b/src/AccordionItemPanel/AccordionItemPanel.spec.tsx index 52110b05..ccf8b1f4 100644 --- a/src/AccordionItemPanel/AccordionItemPanel.spec.tsx +++ b/src/AccordionItemPanel/AccordionItemPanel.spec.tsx @@ -11,7 +11,7 @@ describe('AccordionItemPanel', () => { function mountItem(children: React.ReactNode): ReactWrapper { const item: Item = { uuid: 0, - expanded: false, + expanded: true, }; return mount( @@ -36,12 +36,12 @@ describe('AccordionItemPanel', () => { expect(wrapper.find('div').hasClass(className)).toEqual(true); }); - it('renders correctly with different hideBodyClassName', () => { - const hideBodyClassName = 'hideBodyClassName'; + it('renders correctly with different expandedClassName when item is expanded', () => { + const expandedClassName = 'expandedClassName'; const wrapper = mountItem( - , + , ); - expect(wrapper.find('div').hasClass(hideBodyClassName)).toEqual(true); + expect(wrapper.find('div').hasClass(expandedClassName)).toEqual(true); }); it('respects arbitrary user-defined props', () => { diff --git a/src/AccordionItemPanel/AccordionItemPanel.tsx b/src/AccordionItemPanel/AccordionItemPanel.tsx index 1ca6d2fd..b0aa7101 100644 --- a/src/AccordionItemPanel/AccordionItemPanel.tsx +++ b/src/AccordionItemPanel/AccordionItemPanel.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { UUID } from '../ItemContainer/ItemContainer'; type AccordionItemPanelProps = React.HTMLAttributes & { - hideBodyClassName: string; + expandedClassName: string; uuid: UUID; expanded: boolean; allowMultipleExpanded: boolean; @@ -12,7 +12,7 @@ type AccordionItemPanelProps = React.HTMLAttributes & { const AccordionItemPanel = (props: AccordionItemPanelProps): JSX.Element => { const { className, - hideBodyClassName, + expandedClassName, uuid, expanded, allowMultipleExpanded, @@ -26,7 +26,7 @@ const AccordionItemPanel = (props: AccordionItemPanelProps): JSX.Element => {
& { - hideBodyClassName: string; + expandedClassName: string; }; type AccordionItemPanelWrapperState = {}; @@ -35,7 +35,7 @@ export default class AccordionItemPanelWrapper extends React.Component< static defaultProps: AccordionItemPanelWrapperProps = { className: 'accordion__panel', - hideBodyClassName: 'accordion__panel--hidden', + expandedClassName: 'accordion__panel--expanded', }; render(): JSX.Element { diff --git a/src/AccordionItemPanel/__snapshots__/AccordionItemPanel.spec.tsx.snap b/src/AccordionItemPanel/__snapshots__/AccordionItemPanel.spec.tsx.snap index 7166e2aa..80eec0f9 100644 --- a/src/AccordionItemPanel/__snapshots__/AccordionItemPanel.spec.tsx.snap +++ b/src/AccordionItemPanel/__snapshots__/AccordionItemPanel.spec.tsx.snap @@ -4,7 +4,7 @@ exports[`AccordionItemPanel renders correctly with min params 1`] = `
diff --git a/src/css/fancy-example.css b/src/css/fancy-example.css index 570c9955..6cf872d6 100644 --- a/src/css/fancy-example.css +++ b/src/css/fancy-example.css @@ -40,13 +40,13 @@ .accordion__panel { padding: 20px; - display: block; + display: none; + opacity: 0; animation: fadein 0.35s ease-in; } -.accordion__panel--hidden { - display: none; - opacity: 0; +.accordion__panel--expanded { + display: block; animation: fadein 0.35s ease-in; } diff --git a/src/css/minimal-example.css b/src/css/minimal-example.css index f88d4f91..3acfd543 100644 --- a/src/css/minimal-example.css +++ b/src/css/minimal-example.css @@ -1,7 +1,7 @@ .accordion__panel { - display: block; -} - -.accordion__panel--hidden { display: none; } + +.accordion__panel--expanded { + display: block; +} \ No newline at end of file