diff --git a/packages/fuselage/src/components/Accordion/Accordion.spec.tsx b/packages/fuselage/src/components/Accordion/Accordion.spec.tsx index dd89c59947..6906ff8101 100644 --- a/packages/fuselage/src/components/Accordion/Accordion.spec.tsx +++ b/packages/fuselage/src/components/Accordion/Accordion.spec.tsx @@ -4,17 +4,25 @@ import { axe } from 'jest-axe'; import { render } from '../../testing'; import * as stories from './Accordion.stories'; -const { Default } = composeStories(stories); +const testCases = Object.values(composeStories(stories)).map((Story) => [ + Story.storyName || 'Story', + Story, +]); -describe('[Accordion Component]', () => { - it('renders without crashing', () => { - render(); - }); +test.each(testCases)( + `renders %s without crashing`, + async (_storyname, Story) => { + const tree = render(); + expect(tree.baseElement).toMatchSnapshot(); + } +); - it('should have no a11y violations', async () => { - const { container } = render(); +test.each(testCases)( + '%s should have no a11y violations', + async (_storyname, Story) => { + const { container } = render(); const results = await axe(container); expect(results).toHaveNoViolations(); - }); -}); + } +); diff --git a/packages/fuselage/src/components/Accordion/Accordion.stories.tsx b/packages/fuselage/src/components/Accordion/Accordion.stories.tsx index a9593ba888..209f9fa92e 100644 --- a/packages/fuselage/src/components/Accordion/Accordion.stories.tsx +++ b/packages/fuselage/src/components/Accordion/Accordion.stories.tsx @@ -2,36 +2,66 @@ import type { StoryFn, Meta } from '@storybook/react'; import type { ComponentType } from 'react'; import Box from '../Box'; -import { Accordion } from './Accordion'; -import { AccordionItem } from './AccordionItem'; +import Accordion from './Accordion'; +import AccordionItem from './AccordionItem'; export default { title: 'Containers/Accordion', component: Accordion, subcomponents: { - 'Accordion.Item': Accordion.Item as ComponentType, - 'AccordionItem': AccordionItem as ComponentType, + AccordionItem: AccordionItem as ComponentType, }, } satisfies Meta; -const Template: StoryFn = () => ( +export const Default: StoryFn = () => ( - + Content #1 - - + + Content #2 - - + + Content #3 - + ); -export const Default: StoryFn = Template.bind({}); +const ItemTemplate: StoryFn = ({ + title = 'Item #2', + ...args +}) => ( + + + + Content #1 + + + + + Content #2 + + + + + Content #3 + + + +); + +export const ExpandedItemByDefault = ItemTemplate.bind({}); +ExpandedItemByDefault.args = { + defaultExpanded: true, +}; + +export const DisabledItem = ItemTemplate.bind({}); +DisabledItem.args = { + disabled: true, +}; diff --git a/packages/fuselage/src/components/Accordion/Accordion.styles.scss b/packages/fuselage/src/components/Accordion/Accordion.styles.scss index 8e591e47ac..962eedaeff 100644 --- a/packages/fuselage/src/components/Accordion/Accordion.styles.scss +++ b/packages/fuselage/src/components/Accordion/Accordion.styles.scss @@ -6,7 +6,6 @@ display: flex; flex-flow: column nowrap; border-block-end-color: colors.stroke(extra-light); - border-block-end-width: lengths.border-width(default); } @@ -64,14 +63,6 @@ @include typography.use-font-scale(h4); } -.rcx-accordion-item__toggle-switch { - display: flex; - align-items: center; - flex: 0 0 auto; - - margin: lengths.margin(none) lengths.margin(24); -} - .rcx-accordion-item__panel { visibility: hidden; diff --git a/packages/fuselage/src/components/Accordion/Accordion.tsx b/packages/fuselage/src/components/Accordion/Accordion.tsx index 57d0a552eb..8de50c0ab8 100644 --- a/packages/fuselage/src/components/Accordion/Accordion.tsx +++ b/packages/fuselage/src/components/Accordion/Accordion.tsx @@ -1,21 +1,22 @@ -import type { ComponentProps, ReactElement, ReactNode } from 'react'; +import type { ReactNode } from 'react'; -import Box from '../Box'; -import { AccordionItem } from './AccordionItem'; +import { cx, cxx } from '../../helpers/composeClassNames'; +import { StylingBox } from '../Box'; +import { StylingProps } from '../Box/stylingProps'; -type AccordionProps = ComponentProps & { - animated?: boolean; +export type AccordionProps = { children: ReactNode; -}; +} & Partial; /** * An `Accordion` allows users to toggle the display of sections of content. */ -export function Accordion(props: AccordionProps): ReactElement { - return ; -} +const Accordion = ({ children, ...props }: AccordionProps) => ( + + + {children} + + +); -/** - * @deprecated use named import instead - */ -Accordion.Item = AccordionItem; +export default Accordion; diff --git a/packages/fuselage/src/components/Accordion/AccordionItem.tsx b/packages/fuselage/src/components/Accordion/AccordionItem.tsx index 94081394b8..1af15408e3 100644 --- a/packages/fuselage/src/components/Accordion/AccordionItem.tsx +++ b/packages/fuselage/src/components/Accordion/AccordionItem.tsx @@ -1,11 +1,11 @@ import { useToggle, useUniqueId } from '@rocket.chat/fuselage-hooks'; -import type { FormEvent, KeyboardEvent, MouseEvent, ReactNode } from 'react'; +import type { KeyboardEvent, MouseEvent, ReactNode } from 'react'; -import Box from '../Box'; +import { cx, cxx } from '../../helpers/composeClassNames'; +import { StylingBox } from '../Box'; import { Chevron } from '../Chevron'; -import { ToggleSwitch } from '../ToggleSwitch'; -type AccordionItemProps = { +export type AccordionItemProps = { children?: ReactNode; className?: string; defaultExpanded?: boolean; @@ -14,33 +14,20 @@ type AccordionItemProps = { tabIndex?: number; title: ReactNode; noncollapsible?: boolean; - onToggle?: (e: MouseEvent | KeyboardEvent) => void; - onToggleEnabled?: (e: FormEvent) => void; }; -export const AccordionItem = function Item({ +const AccordionItem = ({ children, - className, defaultExpanded, - disabled, + disabled = false, expanded: propExpanded, tabIndex = 0, title, noncollapsible = !title, - onToggle, - onToggleEnabled, ...props -}: AccordionItemProps) { +}: AccordionItemProps) => { const [stateExpanded, toggleStateExpanded] = useToggle(defaultExpanded); const expanded = propExpanded || stateExpanded; - const toggleExpanded = (event: MouseEvent | KeyboardEvent) => { - if (onToggle) { - onToggle.call(event.currentTarget, event); - return; - } - - toggleStateExpanded(); - }; const panelExpanded = noncollapsible || expanded; @@ -52,7 +39,7 @@ export const AccordionItem = function Item({ return; } e.currentTarget?.blur(); - toggleExpanded(e); + toggleStateExpanded(); }; const handleKeyDown = (event: KeyboardEvent) => { @@ -60,19 +47,17 @@ export const AccordionItem = function Item({ return; } - if ([13, 32].includes(event.keyCode)) { - event.preventDefault(); + if (![' ', 'Enter'].includes(event.key)) { + return; + } - if (event.repeat) { - return; - } + event.preventDefault(); - toggleExpanded(event); + if (event.repeat) { + return; } - }; - const handleToggleClick = (event: MouseEvent) => { - event.stopPropagation(); + toggleStateExpanded(); }; const collapsibleProps = { @@ -92,42 +77,41 @@ export const AccordionItem = function Item({ const barProps = noncollapsible ? nonCollapsibleProps : collapsibleProps; return ( - - {title && ( - - - {title} - - {!noncollapsible && ( - <> - {(disabled || onToggleEnabled) && ( - - - + + + {title && ( + + - > + id={titleId} + > + {title} + + {!noncollapsible && } + + )} + - )} - - {children} - - + id={panelId} + > + {children} + + + ); }; + +export default AccordionItem; diff --git a/packages/fuselage/src/components/Accordion/__snapshots__/Accordion.spec.tsx.snap b/packages/fuselage/src/components/Accordion/__snapshots__/Accordion.spec.tsx.snap new file mode 100644 index 0000000000..47f51c1482 --- /dev/null +++ b/packages/fuselage/src/components/Accordion/__snapshots__/Accordion.spec.tsx.snap @@ -0,0 +1,375 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders Default without crashing 1`] = ` + + + + + + + Item #1 + + + + + + + + + + Content #1 + + + + + + + Item #2 + + + + + + + + + + Content #2 + + + + + + + Item #3 + + + + + + + + + + Content #3 + + + + + + +`; + +exports[`renders DisabledItem without crashing 1`] = ` + + + + + + + Item #1 + + + + + + + + + + Content #1 + + + + + + + Item #2 + + + + + + + + + + Content #2 + + + + + + + Item #3 + + + + + + + + + + Content #3 + + + + + + +`; + +exports[`renders ExpandedItemByDefault without crashing 1`] = ` + + + + + + + Item #1 + + + + + + + + + + Content #1 + + + + + + + Item #2 + + + + + + + + + + Content #2 + + + + + + + Item #3 + + + + + + + + + + Content #3 + + + + + + +`; diff --git a/packages/fuselage/src/components/Accordion/index.ts b/packages/fuselage/src/components/Accordion/index.ts index cadd5bc406..fb3ec96a24 100644 --- a/packages/fuselage/src/components/Accordion/index.ts +++ b/packages/fuselage/src/components/Accordion/index.ts @@ -1,2 +1,5 @@ -export * from './Accordion'; -export * from './AccordionItem'; +export { default as Accordion, type AccordionProps } from './Accordion'; +export { + default as AccordionItem, + type AccordionItemProps, +} from './AccordionItem';