Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPHJOD-258: Expander #19

Merged
merged 1 commit into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions lib/components/Expander/Expander.stories.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof Expander>;

export default meta;

type Story = StoryObj<typeof meta>;

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: <div>Children here</div>,
},
};
51 changes: 51 additions & 0 deletions lib/components/Expander/Expander.test.tsx
Original file line number Diff line number Diff line change
@@ -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(
<Expander label="Label" description="Description">
content
</Expander>,
);
expect(container.firstChild).toMatchSnapshot();
});
});

describe('Expander', () => {
test('renders label and description correctly', () => {
const label = 'Test Label';
const description = 'Test Description';
render(<Expander label={label} description={description} />);

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(<Expander label={label} description={description} />);

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();
});
});
39 changes: 39 additions & 0 deletions lib/components/Expander/Expander.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Disclosure as="div" className="rounded-[20px] border-[3px] border-[#767676] p-4">
{({ open }) => (
<>
<Disclosure.Button className="flex w-full flex-col">
<div className="mb-3 flex w-full flex-row justify-between">
<span id={labelId} className="text-[20px] font-bold text-[#333333]">
{label}
</span>
<CaretDownIcon className={open ? 'rotate-180' : undefined} />
</div>
<span className="mb-4 text-start text-[12px] font-bold text-[#767676]">{description}</span>
</Disclosure.Button>
<Disclosure.Panel role="region" aria-labelledby={labelId}>
{children}
</Disclosure.Panel>
</>
)}
</Disclosure>
);
};

const CaretDownIcon = ({ className }: { className?: string }) => (
<svg width="17" height="11" viewBox="0 0 17 11" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
<path d="M1.08521 1.56995L8.19521 8.56995L15.3052 1.56995" stroke="#767676" strokeWidth="3" />
</svg>
);
45 changes: 45 additions & 0 deletions lib/components/Expander/__snapshots__/Expander.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Snapshot testing > Base button 1`] = `
<div
class="rounded-[20px] border-[3px] border-[#767676] p-4"
data-headlessui-state=""
>
<button
aria-expanded="false"
class="flex w-full flex-col"
data-headlessui-state=""
id="headlessui-disclosure-button-:r1:"
type="button"
>
<div
class="mb-3 flex w-full flex-row justify-between"
>
<span
class="text-[20px] font-bold text-[#333333]"
id=":r0:"
>
Label
</span>
<svg
fill="none"
height="11"
viewBox="0 0 17 11"
width="17"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.08521 1.56995L8.19521 8.56995L15.3052 1.56995"
stroke="#767676"
stroke-width="3"
/>
</svg>
</div>
<span
class="mb-4 text-start text-[12px] font-bold text-[#767676]"
>
Description
</span>
</button>
</div>
`;
1 change: 1 addition & 0 deletions lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down