Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(accordion): add Accordion component
- Loading branch information
1 parent
dcf16db
commit c0f8f79
Showing
4 changed files
with
285 additions
and
11 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,104 @@ | ||
import React from 'react' | ||
import { Story, Meta } from '@storybook/react' | ||
|
||
import { Accordion, Text, AccordionPanel } from '../../components' | ||
import { Heading } from '../heading' | ||
|
||
export default { | ||
title: 'Components/Accordion', | ||
component: Accordion | ||
} as Meta | ||
|
||
export const Sizes = () => ( | ||
<> | ||
<Heading level='h2' size='xl'> | ||
Small Sized Heading | ||
</Heading> | ||
<Accordion size='sm'> | ||
<AccordionPanel header='One'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
<AccordionPanel header='Two'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
<AccordionPanel header='Three'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
</Accordion> | ||
|
||
<Heading level='h2' size='xl'> | ||
Medium Sized Accordion | ||
</Heading> | ||
<Accordion size='md'> | ||
<AccordionPanel header='One'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
<AccordionPanel header='Two'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
<AccordionPanel header='Three'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
</Accordion> | ||
|
||
<Heading level='h2' size='xl'> | ||
Large Sized Accordion | ||
</Heading> | ||
<Accordion size='lg'> | ||
<AccordionPanel header='One'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
<AccordionPanel header='Two'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
<AccordionPanel header='Three'> | ||
<div> | ||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet | ||
perspiciatis praesentium nemo nobis sed, assumenda vitae voluptatum | ||
rerum, libero, quisquam nostrum aspernatur labore saepe totam iusto | ||
harum? Quidem, mollitia aspernatur. | ||
</div> | ||
</AccordionPanel> | ||
</Accordion> | ||
</> | ||
) |
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 |
---|---|---|
@@ -1,23 +1,172 @@ | ||
import React, { FC } from 'react' | ||
import React, { FC, HTMLAttributes, createContext, useContext } from 'react' | ||
import styled from '@emotion/styled' | ||
import { Disclosure } from '@headlessui/react' | ||
import { ChevronDown } from 'react-feather' | ||
|
||
import { accordionTheme } from '../theme/components/accordion.theme' | ||
import { Flex } from '../../components' | ||
|
||
const { Button, Panel } = Disclosure | ||
|
||
const Accordion: FC<any> = (props) => { | ||
return <Disclosure {...props} /> | ||
const AccordionContext = createContext<AccordionBaseProps | null>(null) | ||
|
||
const { Provider } = AccordionContext | ||
|
||
const Accordion: FC<AccordionProps> = ({ | ||
children, | ||
className, | ||
size, | ||
width, | ||
fullWidth, | ||
showIcon, | ||
iconPosition, | ||
...props | ||
}) => { | ||
const _className = className | ||
? `avocado-accordion ${className}` | ||
: `avocado-accordion` | ||
|
||
const accordionValues = { | ||
size, | ||
width, | ||
fullWidth, | ||
showIcon, | ||
iconPosition | ||
} | ||
|
||
return ( | ||
<Provider value={accordionValues}> | ||
<StyledAccordion | ||
className={_className} | ||
width={width} | ||
fullWidth={fullWidth} | ||
{...props} | ||
> | ||
{children} | ||
</StyledAccordion> | ||
</Provider> | ||
) | ||
} | ||
|
||
const AccordionButton: FC<any> = Button | ||
// interface AccordionButtonProps {} | ||
const AccordionButton: FC = Button | ||
|
||
const AccordionPanel: FC<AccordionPanelProps> = ({ | ||
children, | ||
className, | ||
header, | ||
...props | ||
}) => { | ||
const context = useContext(AccordionContext) | ||
const { iconPosition, showIcon, size } = context as AccordionBaseProps | ||
|
||
const _className = className | ||
? `avocado-accordion_panel ${className}` | ||
: `avocado-accordion_panel` | ||
|
||
const AccordionPanel: FC<any> = (props) => { | ||
return ( | ||
<span> | ||
<Button>{props.heading}</Button> | ||
<Panel>{props.children}</Panel> | ||
</span> | ||
<Disclosure> | ||
<StyledDisclosure | ||
className={_className} | ||
{...props} | ||
size={size} | ||
iconPosition={iconPosition} | ||
showIcon={showIcon} | ||
> | ||
<Button className='avocado-accordion_panel__button'> | ||
<Flex alignItems='center' justifyContent='space-between' gap={0}> | ||
{header} | ||
<ChevronDown className='avocado-accordion_panel__icon' /> | ||
</Flex> | ||
</Button> | ||
<Panel className='avocado-accordion_panel__content'>{children}</Panel> | ||
</StyledDisclosure> | ||
</Disclosure> | ||
) | ||
} | ||
// interface AccordionPanelProps {} | ||
|
||
interface AccordionPanelProps | ||
extends HTMLAttributes<HTMLElement>, | ||
Omit<AccordionBaseProps, 'width' | 'fullWidth'> { | ||
/** | ||
* header - component/text to show on the Accordion Button | ||
*/ | ||
header: string | JSX.Element | ||
} | ||
|
||
const StyledDisclosure = styled.div<AccordionBaseProps>` | ||
display: block; | ||
width: 100%; | ||
border-bottom: 1px solid ${accordionTheme.border}; | ||
.avocado-accordion_panel__button { | ||
cursor: pointer; | ||
width: 100%; | ||
text-align: left; | ||
background: inherit; | ||
border: none; | ||
padding: ${({ size }) => size && `${accordionTheme.sizes[size].margin} 0`}; | ||
user-select: none; | ||
font-size: ${({ size }) => size && accordionTheme.sizes[size].fontSize}; | ||
} | ||
.avocado-accordion_panel__content { | ||
background: ${accordionTheme.panelBackground}; | ||
font-size: ${({ size }) => size && accordionTheme.sizes[size].fontSize}; | ||
margin: 0; | ||
padding: 0.85em; | ||
} | ||
.avocado-accordion_panel__icon { | ||
height: 1em; | ||
} | ||
` | ||
|
||
const StyledAccordion = styled.div<AccordionProps>` | ||
width: ${({ width, fullWidth }) => (fullWidth ? '100%' : width)}; | ||
font-size: ${({ size }) => size && accordionTheme.sizes[size].fontSize}; | ||
margin-bottom: 1.5em; | ||
button { | ||
font-size: inherit; | ||
} | ||
` | ||
|
||
type AccordionSize = 'sm' | 'md' | 'lg' | ||
type AccordionBaseProps = { | ||
/** | ||
* size - size of the Accordion component | ||
*/ | ||
size?: AccordionSize | ||
|
||
/** | ||
* width - width of the Accordion component in px | ||
*/ | ||
width?: string | ||
|
||
/** | ||
* fullWidth - when set to true, Accordion stretches to fill horizontal space | ||
*/ | ||
fullWidth?: boolean | ||
|
||
/** | ||
* showIcon - should Accordion show chevron icon | ||
*/ | ||
showIcon?: boolean | ||
|
||
/** | ||
* iconPosition - position of Accordion header icon | ||
*/ | ||
iconPosition?: 'left' | 'right' | ||
} | ||
interface AccordionProps | ||
extends HTMLAttributes<HTMLElement>, | ||
AccordionBaseProps {} | ||
|
||
Accordion.defaultProps = { | ||
size: 'md', | ||
width: '20em', | ||
iconPosition: 'right', | ||
fullWidth: false, | ||
showIcon: true | ||
} | ||
|
||
export { Accordion, AccordionButton, AccordionPanel } |
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,20 @@ | ||
import colors from '../colors' | ||
|
||
export const accordionTheme = { | ||
border: colors.gray[4], | ||
panelBackground: colors.gray[3], | ||
sizes: { | ||
sm: { | ||
fontSize: `0.875em`, | ||
margin: `0.5em` | ||
}, | ||
md: { | ||
fontSize: `1em`, | ||
margin: `0.5em` | ||
}, | ||
lg: { | ||
fontSize: `1em`, | ||
margin: `0.625em` | ||
} | ||
} | ||
} |
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