Skip to content

Commit

Permalink
refactor: accordion component
Browse files Browse the repository at this point in the history
  • Loading branch information
timoheddes committed Aug 31, 2023
1 parent 7986906 commit 325edf9
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 226 deletions.
54 changes: 38 additions & 16 deletions packages/libs/react-ui/src/components/Accordion/Accordion.css.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { sprinkles } from '@theme/sprinkles.css';
import { style, styleVariants } from '@vanilla-extract/css';
import { vars } from '@theme/vars.css';
import { style } from '@vanilla-extract/css';

export const accordionSectionClass = style([
sprinkles({
display: 'block',
flexGrow: 1,
marginBottom: '$6',
}),
{
Expand All @@ -13,32 +16,49 @@ export const accordionSectionClass = style([
},
},
]);
export const accordionTitleClass = style([
sprinkles({
display: 'flex',

export const accordionSectionHeadingClass = style([
{
alignItems: 'center',
justifyContent: 'space-between',
background: 'none',
border: 'none',
borderBottom: `1px solid ${vars.colors.$gray20}`,
cursor: 'pointer',
display: 'flex',
padding: 0,
textAlign: 'left',
transition: 'color 0.2s ease 0s',
width: '100%',
selectors: {
'&.isOpen': {
border: 'none',
},
},
},
]);

export const accordionTitleClass = style([
sprinkles({
color: '$neutral5',
display: 'block',
fontSize: '$base',
fontWeight: '$medium',
paddingBottom: '$2',
width: '100%',
}),
{
transition: 'color 0.2s ease 0s',
borderBottom: '1px solid',
},
]);
export const accordionTitleVariants = styleVariants({
closed: [sprinkles({ color: '$negativeContrast' })],
opened: [sprinkles({ color: '$foreground' })],
});

export const toggleButtonClass = style([
sprinkles({
border: 'none',
background: 'none',
color: 'inherit',
border: 'none',
color: '$neutral5',
cursor: 'pointer',
paddingBottom: '$2',
}),
]);

export const toggleIconClass = style([
{
transition: 'transform 0.2s ease 0s',
transform: 'rotate(45deg)',
Expand All @@ -49,9 +69,11 @@ export const toggleButtonClass = style([
},
},
]);

export const accordionContentWrapperClass = style([
sprinkles({
paddingTop: '$2',
color: '$neutral5',
paddingTop: 0,
paddingBottom: '$2',
}),
]);
128 changes: 93 additions & 35 deletions packages/libs/react-ui/src/components/Accordion/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,117 @@
import { Accordion, IAccordionProps } from './Accordion';
import type { IAccordionProps, IAccordionSectionProps } from './';
import { Accordion } from './';

import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';

const meta: Meta<{} & IAccordionProps> = {
const generateSection = (i: number): IAccordionSectionProps => ({
title: `Section title ${i}`,
children: (
<p>
This is the content for section {i}. The type of this content is not
restricted: any valid HTML content is allowed.
</p>
),
onOpen: () => console.log(`open section ${i}`),
onClose: () => console.log(`close section ${i}`),
});
const generateSections = (n: number): IAccordionSectionProps[] =>
Array.from({ length: n }, (d, i) => generateSection(i + 1));

const sampleSections: IAccordionSectionProps[] = generateSections(5);

type StoryProps = {
sectionCount: number;
linked: boolean;
useCustomSections: boolean;
customSections: IAccordionSectionProps[];
} & IAccordionProps;

const meta: Meta<StoryProps> = {
title: 'Components/Accordion',
parameters: {
controls: {
hideNoControlsWarning: true,
sort: 'requiredFirst',
},
docs: {
description: {
component:
'The Accordion component allows the user to show and hide sections of content on a page.<br />These sections can be expanded and collapsed by clicking the section headers.<br /><br /><strong>initialOpenSection</strong><br />This optional prop can be used on the Root element to set the initially opened section<br /><em>It defaults to `undefined` and has only been explcitly set to - 1 in the story code for demonstration purposes.</em><br /><br /><em>Note: this variant of the Accordion component is meant to be used to display content. For Navigation purposes, please check the other variant within the Navigation subgroup.</em>',
},
},
},
argTypes: {
linked: {
type: 'boolean',
defaultValue: true,
control: { type: 'boolean' },
description:
'Each section will close the other sections if they are linked',
control: {
type: 'boolean',
'When linked, only one section can be open at a time. If a section is opened, the previously opened section will be closed.',
table: {
defaultValue: { summary: 'false' },
type: { summary: 'boolean' },
},
},
sectionCount: {
control: { type: 'range', min: 1, max: sampleSections.length, step: 1 },
description: 'Adjust sample section items count',
if: { arg: 'useCustomContent', neq: true },
table: {
defaultValue: { summary: 3 },
type: { summary: 'number' },
},
},
useCustomSections: {
control: { type: 'boolean' },
description: 'Define your own sections instead of the sample ones?',
table: {
defaultValue: { summary: 'false' },
type: { summary: 'boolean' },
},
},
sections: {
customSections: {
defaultValue: [],
description: 'Accordion children',
description: 'Custom sections',
control: {
type: 'array',
},
if: { arg: 'useCustomSections', eq: true },
},
},
};

export default meta;
type Story = StoryObj<{} & IAccordionProps>;
type IStory = StoryObj<StoryProps>;

export const Dynamic: Story = {
export const Dynamic: IStory = {
name: 'Accordion',
args: {
linked: true,
sections: [
{
title: <span>First Section</span>,
children: <p>This is the content for the first section</p>,
onOpen: () => console.log('open first item'),
onClose: () => console.log('close first item'),
},
{
title: <span>Second Section</span>,
children: <p>This is the content for the second section</p>,
onOpen: () => console.log('open second item'),
onClose: () => console.log('close second item'),
},
{
title: <span>Third Section</span>,
children: <p>This is the content for the third section</p>,
onOpen: () => console.log('open third item'),
onClose: () => console.log('close third item'),
},
],
linked: false,
sectionCount: 3,
customSections: sampleSections,
},
render: ({ linked, sections }) => {
return <Accordion linked={Boolean(linked)} sections={sections} />;
render: ({ linked, sectionCount, useCustomSections, customSections }) => {
const sections = useCustomSections ? customSections : sampleSections;
return (
<Accordion.Root linked={linked} initialOpenSection={-1}>
{sections
.slice(0, sectionCount)
.map(
(
{ title, children, onOpen, onClose }: IAccordionSectionProps,
index,
) => (
<Accordion.Section
onOpen={onOpen}
onClose={onClose}
title={title}
key={index}
>
{children}
</Accordion.Section>
),
)}
</Accordion.Root>
);
},
};

export default meta;
98 changes: 0 additions & 98 deletions packages/libs/react-ui/src/components/Accordion/Accordion.test.tsx

This file was deleted.

Loading

0 comments on commit 325edf9

Please sign in to comment.