This repository has been archived by the owner on Oct 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: create accordion component and story
- Loading branch information
1 parent
72b9b94
commit da73fec
Showing
7 changed files
with
471 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import React from 'react'; | ||
import { Accordion } from './Accordion'; | ||
import { Layout } from '../../storybook'; | ||
import styled from 'styled-components'; | ||
import { Gear } from '../../icons'; | ||
import { rem } from 'polished'; | ||
import { core } from '../../tokens'; | ||
|
||
export default { | ||
title: 'components/Accordion/examples', | ||
component: Accordion, | ||
argTypes: { | ||
allowMultiple: { control: { disable: true } }, | ||
defaultIndex: { control: { disable: true } }, | ||
format: { control: { disable: true } }, | ||
}, | ||
}; | ||
|
||
export function AccordionWithSubcopy({ args }) { | ||
return ( | ||
<Layout.StoryVertical center> | ||
<Accordion {...args}> | ||
<Accordion.Item | ||
title="Accordion item title" | ||
subcopy="Subcopy text" | ||
> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Layout.StoryVertical> | ||
); | ||
} | ||
|
||
AccordionWithSubcopy.storyName = 'Accordion - subcopy'; | ||
|
||
export function AccordionWithIcon({ args }) { | ||
return ( | ||
<Layout.StoryVertical center> | ||
<Accordion {...args}> | ||
<Accordion.Item | ||
title="Accordion item with icon" | ||
icon={<GearIcon />} | ||
> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Layout.StoryVertical> | ||
); | ||
} | ||
|
||
const GearIcon = styled(Gear)` | ||
width: ${rem(22)}; | ||
margin-right: ${rem(10)}; | ||
path { | ||
fill: ${core.color.text.primary}; | ||
} | ||
`; | ||
|
||
AccordionWithIcon.storyName = 'Accordion - icon'; | ||
|
||
export function DisabledAccordion({ args }) { | ||
return ( | ||
<Layout.StoryVertical center> | ||
<Accordion {...args}> | ||
<Accordion.Item | ||
title="Disabled accordion item" | ||
disabled={true} | ||
> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Layout.StoryVertical> | ||
); | ||
} | ||
|
||
DisabledAccordion.storyName = 'Accordion - disabled'; | ||
|
||
export function AccordionWithError({ args }) { | ||
return ( | ||
<Layout.StoryVertical center> | ||
<Accordion {...args}> | ||
<Accordion.Item | ||
title="Accordion item with error" | ||
hasError={true} | ||
> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Layout.StoryVertical> | ||
); | ||
} | ||
|
||
AccordionWithError.storyName = 'Accordion - error'; | ||
|
||
export function AccordionWithAllowMultipleFalse({ args }) { | ||
return ( | ||
<Layout.StoryVertical center> | ||
<Accordion {...args} allowMultiple={false} defaultIndex={0}> | ||
<Accordion.Item title="Accordion item 1"> | ||
Accordion content | ||
</Accordion.Item> | ||
<Accordion.Item title="Accordion item 2"> | ||
Accordion content | ||
</Accordion.Item> | ||
<Accordion.Item title="Accordion item 3"> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Layout.StoryVertical> | ||
); | ||
} | ||
|
||
AccordionWithAllowMultipleFalse.storyName = | ||
'Accordion - allowMultiple is false'; | ||
|
||
export function AccordionAllowMultiple({ args }) { | ||
return ( | ||
<Layout.StoryVertical center> | ||
<Accordion {...args}> | ||
<Accordion.Item title="Accordion item 1"> | ||
Accordion content | ||
</Accordion.Item> | ||
<Accordion.Item title="Accordion item 2"> | ||
Accordion content | ||
</Accordion.Item> | ||
<Accordion.Item title="Accordion item 3"> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Layout.StoryVertical> | ||
); | ||
} | ||
|
||
AccordionAllowMultiple.storyName = | ||
'Accordion - allowMultiple is true (default)'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import React, { useState } from 'react'; | ||
|
||
import { | ||
Content, | ||
ChevronUp, | ||
CircleWarningIcon, | ||
Header, | ||
StyledChevronDown, | ||
Subcopy, | ||
Title, | ||
TitleContainer, | ||
TriggerContainer, | ||
Wrapper, | ||
} from './Accordion.style'; | ||
import { MinorComponent } from '../../utils'; | ||
import { AccordionItemProps } from './Accordion.types'; | ||
|
||
export interface Minors { | ||
Item: MinorComponent<any>; | ||
} | ||
|
||
export function Item({ | ||
children, | ||
title, | ||
format, | ||
index, | ||
allowMultiple, | ||
defaultActive, | ||
setActiveIndex, | ||
itemActive, | ||
subcopy = '', | ||
icon, | ||
hasError = false, | ||
disabled = false, | ||
}: AccordionItemProps) { | ||
const [active, setActive] = useState<boolean>(defaultActive); | ||
const isActive = allowMultiple | ||
? active && !disabled | ||
: itemActive && !disabled; | ||
|
||
return ( | ||
<Wrapper | ||
active={isActive} | ||
disabled={disabled} | ||
format={format} | ||
key={index} | ||
> | ||
<TriggerContainer | ||
onClick={() => { | ||
if (allowMultiple) { | ||
setActive(!active); | ||
} else { | ||
setActiveIndex({ index }); | ||
} | ||
}} | ||
tabIndex={0} | ||
format={format} | ||
active={isActive} | ||
> | ||
<Header> | ||
{hasError && <CircleWarningIcon />} | ||
{!hasError && icon && icon} | ||
<TitleContainer> | ||
<Title>{title}</Title> | ||
{subcopy && <Subcopy>{subcopy}</Subcopy>} | ||
</TitleContainer> | ||
</Header> | ||
{isActive ? ( | ||
<ChevronUp width="24" /> | ||
) : ( | ||
<StyledChevronDown width="24" /> | ||
)} | ||
</TriggerContainer> | ||
{isActive && <Content active={isActive}>{children}</Content>} | ||
</Wrapper> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from 'react'; | ||
import styled, { css } from 'styled-components'; | ||
import { rem } from 'polished'; | ||
|
||
import { Accordion } from './Accordion'; | ||
|
||
export default { | ||
title: 'components/Accordion/props', | ||
component: Accordion, | ||
argTypes: { | ||
allowMultiple: { control: { disable: true } }, | ||
defaultIndex: { control: { disable: true } }, | ||
format: { control: { disable: true } }, | ||
}, | ||
}; | ||
|
||
const formats = ['basic', 'secondary']; | ||
|
||
export function Formats({ args }) { | ||
return ( | ||
<Container> | ||
{formats.map((format, i) => ( | ||
<Accordion key={i} format={format} {...args}> | ||
<Accordion.Item title={`Accordion format: ${format}`}> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
))} | ||
</Container> | ||
); | ||
} | ||
|
||
const Container = styled.div` | ||
width: 50%; | ||
display: flex; | ||
flex-direction: column; | ||
gap: ${rem(8)}; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
import { Story } from '@storybook/react'; | ||
|
||
import { Accordion } from './Accordion'; | ||
import { Props } from './Accordion.types'; | ||
import styled from 'styled-components'; | ||
import { Gear } from '../../icons'; | ||
import { rem } from 'polished'; | ||
|
||
export default { | ||
title: 'components/Accordion', | ||
component: Accordion, | ||
}; | ||
|
||
const Template: Story<Props> = (args) => { | ||
return ( | ||
<Container> | ||
<Accordion {...args}> | ||
<Accordion.Item title="Accordion item 1"> | ||
Accordion content | ||
</Accordion.Item> | ||
<Accordion.Item title="Accordion item 2"> | ||
Accordion content | ||
</Accordion.Item> | ||
</Accordion> | ||
</Container> | ||
); | ||
}; | ||
|
||
const Container = styled.div` | ||
width: 50%; | ||
`; | ||
|
||
export const Controls = Template.bind({}); | ||
Controls.storyName = 'Accordion'; |
Oops, something went wrong.