diff --git a/lib/components/Expander/Expander.stories.tsx b/lib/components/Expander/Expander.stories.tsx new file mode 100644 index 0000000..929a639 --- /dev/null +++ b/lib/components/Expander/Expander.stories.tsx @@ -0,0 +1,31 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Expander } from './Expander'; + +const meta = { + title: 'Primitives/Expander', + component: Expander, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +const parameters = { + design: { + type: 'figma', + url: 'https://www.figma.com/file/6M2LrpSCcB0thlFDaQAI2J/cx_jod_client?node-id=542%3A7857', + }, +}; + +export const Default: Story = { + parameters: { + ...parameters, + }, + args: { + label: 'Label', + description: 'Description', + children:
Children here
, + }, +}; diff --git a/lib/components/Expander/Expander.test.tsx b/lib/components/Expander/Expander.test.tsx new file mode 100644 index 0000000..8686a82 --- /dev/null +++ b/lib/components/Expander/Expander.test.tsx @@ -0,0 +1,51 @@ +import { render, screen, cleanup } from '@testing-library/react'; +import { afterEach, describe, expect, test } from 'vitest'; +import '@testing-library/jest-dom/vitest'; +import userEvent from '@testing-library/user-event'; + +import { Expander } from './Expander'; + +afterEach(() => { + cleanup(); +}); + +describe('Snapshot testing', () => { + test('Base button', () => { + const { container } = render( + + content + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); +}); + +describe('Expander', () => { + test('renders label and description correctly', () => { + const label = 'Test Label'; + const description = 'Test Description'; + render(); + + const labelElement = screen.getByText(label); + const descriptionElement = screen.getByText(description); + + expect(labelElement).toBeInTheDocument(); + expect(descriptionElement).toBeInTheDocument(); + }); + + test('expands and collapses on button click', async () => { + const user = userEvent.setup(); + const label = 'Test Label'; + const description = 'Test Description'; + render(); + + const button = screen.getByRole('button'); + expect(screen.queryByRole('region')).toBeNull(); + + await user.click(button); + expect(screen.getByRole('region')).not.toBeNull(); + await user.click(button); + + expect(screen.queryByRole('region')).toBeNull(); + }); +}); diff --git a/lib/components/Expander/Expander.tsx b/lib/components/Expander/Expander.tsx new file mode 100644 index 0000000..9b2f24d --- /dev/null +++ b/lib/components/Expander/Expander.tsx @@ -0,0 +1,39 @@ +import { useId } from 'react'; +import { Disclosure } from '@headlessui/react'; + +export interface ExpanderProps { + label: string; + description: string; + children?: React.ReactNode; +} + +export const Expander = ({ label, description, children }: ExpanderProps) => { + const labelId = useId(); + + return ( + + {({ open }) => ( + <> + +
+ + {label} + + +
+ {description} +
+ + {children} + + + )} +
+ ); +}; + +const CaretDownIcon = ({ className }: { className?: string }) => ( + + + +); diff --git a/lib/components/Expander/__snapshots__/Expander.test.tsx.snap b/lib/components/Expander/__snapshots__/Expander.test.tsx.snap new file mode 100644 index 0000000..a78601e --- /dev/null +++ b/lib/components/Expander/__snapshots__/Expander.test.tsx.snap @@ -0,0 +1,45 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Snapshot testing > Base button 1`] = ` +
+ +
+`; diff --git a/lib/main.ts b/lib/main.ts index 19b3842..e1a4644 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -3,6 +3,7 @@ import './index.css'; export { Button } from './components/Button/Button'; export { HeroCard } from './components/HeroCard/HeroCard'; export { DropdownMenu } from './components/DropdownMenu/DropdownMenu'; +export { Expander } from './components/Expander/Expander'; export { NavigationBar } from './components/NavigationBar/NavigationBar'; export { RadioButton } from './components/RadioButton/RadioButton'; export { RadioButtonGroup } from './components/RadioButton/RadioButtonGroup';