Skip to content

Commit 8ed7768

Browse files
authored
feat(Accordion): Add Accordion Component (#364)
* using dialog element * fix ModalLegacy story meta * add glass button & neutral color * feat(Join): Add Join Component * feat(Accordion): Add Accordion Component
1 parent 3cf91f9 commit 8ed7768

3 files changed

Lines changed: 261 additions & 0 deletions

File tree

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
import React from 'react'
2+
import { StoryFn as Story, Meta } from '@storybook/react'
3+
4+
import Accordion, { AccordionProps } from '.'
5+
import Join from '../Join'
6+
7+
export default {
8+
title: 'Data Display/Accordion',
9+
component: Accordion,
10+
} as Meta
11+
12+
export const Default: Story<AccordionProps> = (args) => {
13+
return (
14+
<div className="flex flex-wrap gap-2">
15+
<Accordion {...args} defaultChecked>
16+
<Accordion.Title className="text-xl font-medium">
17+
Click to open this one and close others
18+
</Accordion.Title>
19+
<Accordion.Content>
20+
<p>hello</p>
21+
</Accordion.Content>
22+
</Accordion>
23+
<Accordion {...args}>
24+
<Accordion.Title className="text-xl font-medium">
25+
Click to open this one and close others
26+
</Accordion.Title>
27+
<Accordion.Content>
28+
<p>hello</p>
29+
</Accordion.Content>
30+
</Accordion>
31+
<Accordion {...args}>
32+
<Accordion.Title className="text-xl font-medium">
33+
Click to open this one and close others
34+
</Accordion.Title>
35+
<Accordion.Content>
36+
<p>hello</p>
37+
</Accordion.Content>
38+
</Accordion>
39+
</div>
40+
)
41+
}
42+
Default.args = {
43+
className: 'bg-base-200',
44+
}
45+
46+
export const WithArrow: Story<AccordionProps> = (args) => {
47+
return (
48+
<div className="flex flex-wrap gap-2">
49+
<Accordion {...args} defaultChecked>
50+
<Accordion.Title className="text-xl font-medium">
51+
Click to open this one and close others
52+
</Accordion.Title>
53+
<Accordion.Content>
54+
<p>hello</p>
55+
</Accordion.Content>
56+
</Accordion>
57+
<Accordion {...args}>
58+
<Accordion.Title className="text-xl font-medium">
59+
Click to open this one and close others
60+
</Accordion.Title>
61+
<Accordion.Content>
62+
<p>hello</p>
63+
</Accordion.Content>
64+
</Accordion>
65+
<Accordion {...args}>
66+
<Accordion.Title className="text-xl font-medium">
67+
Click to open this one and close others
68+
</Accordion.Title>
69+
<Accordion.Content>
70+
<p>hello</p>
71+
</Accordion.Content>
72+
</Accordion>
73+
</div>
74+
)
75+
}
76+
WithArrow.args = {
77+
className: 'bg-base-200',
78+
icon: 'arrow',
79+
}
80+
81+
export const WithPlusMinus: Story<AccordionProps> = (args) => {
82+
return (
83+
<div className="flex flex-wrap gap-2">
84+
<Accordion {...args} defaultChecked>
85+
<Accordion.Title className="text-xl font-medium">
86+
Click to open this one and close others
87+
</Accordion.Title>
88+
<Accordion.Content>
89+
<p>hello</p>
90+
</Accordion.Content>
91+
</Accordion>
92+
<Accordion {...args}>
93+
<Accordion.Title className="text-xl font-medium">
94+
Click to open this one and close others
95+
</Accordion.Title>
96+
<Accordion.Content>
97+
<p>hello</p>
98+
</Accordion.Content>
99+
</Accordion>
100+
<Accordion {...args}>
101+
<Accordion.Title className="text-xl font-medium">
102+
Click to open this one and close others
103+
</Accordion.Title>
104+
<Accordion.Content>
105+
<p>hello</p>
106+
</Accordion.Content>
107+
</Accordion>
108+
</div>
109+
)
110+
}
111+
WithPlusMinus.args = {
112+
className: 'bg-base-200',
113+
icon: 'plus',
114+
}
115+
116+
export const AndJoinTogether: Story<AccordionProps> = (args) => {
117+
return (
118+
<Join className="w-full" vertical={true}>
119+
<Accordion {...args} defaultChecked>
120+
<Accordion.Title className="text-xl font-medium">
121+
Click to open this one and close others
122+
</Accordion.Title>
123+
<Accordion.Content>
124+
<p>hello</p>
125+
</Accordion.Content>
126+
</Accordion>
127+
<Accordion {...args}>
128+
<Accordion.Title className="text-xl font-medium">
129+
Click to open this one and close others
130+
</Accordion.Title>
131+
<Accordion.Content>
132+
<p>hello</p>
133+
</Accordion.Content>
134+
</Accordion>
135+
<Accordion {...args}>
136+
<Accordion.Title className="text-xl font-medium">
137+
Click to open this one and close others
138+
</Accordion.Title>
139+
<Accordion.Content>
140+
<p>hello</p>
141+
</Accordion.Content>
142+
</Accordion>
143+
</Join>
144+
)
145+
}
146+
AndJoinTogether.args = {
147+
className: 'border border-base-300 join-item',
148+
icon: 'arrow',
149+
}
150+
151+
export const Multiple: Story<AccordionProps> = (args) => {
152+
return (
153+
<>
154+
<div className="flex flex-wrap gap-2">
155+
<Accordion {...args} defaultChecked name="groupA">
156+
<Accordion.Title className="text-xl font-medium">
157+
Group A
158+
</Accordion.Title>
159+
<Accordion.Content>
160+
<p>hello</p>
161+
</Accordion.Content>
162+
</Accordion>
163+
<Accordion {...args} name="groupA">
164+
<Accordion.Title className="text-xl font-medium">
165+
Group A
166+
</Accordion.Title>
167+
<Accordion.Content>
168+
<p>hello</p>
169+
</Accordion.Content>
170+
</Accordion>
171+
<Accordion {...args} name="groupA">
172+
<Accordion.Title className="text-xl font-medium">
173+
Group A
174+
</Accordion.Title>
175+
<Accordion.Content>
176+
<p>hello</p>
177+
</Accordion.Content>
178+
</Accordion>
179+
</div>
180+
<div className="flex flex-wrap gap-2">
181+
<Accordion {...args} defaultChecked name="groupB">
182+
<Accordion.Title className="text-xl font-medium">
183+
Group B
184+
</Accordion.Title>
185+
<Accordion.Content>
186+
<p>hello</p>
187+
</Accordion.Content>
188+
</Accordion>
189+
<Accordion {...args} name="groupB">
190+
<Accordion.Title className="text-xl font-medium">
191+
Group B
192+
</Accordion.Title>
193+
<Accordion.Content>
194+
<p>hello</p>
195+
</Accordion.Content>
196+
</Accordion>
197+
<Accordion {...args} name="groupB">
198+
<Accordion.Title className="text-xl font-medium">
199+
Group B
200+
</Accordion.Title>
201+
<Accordion.Content>
202+
<p>hello</p>
203+
</Accordion.Content>
204+
</Accordion>
205+
</div>
206+
</>
207+
)
208+
}
209+
Multiple.args = {
210+
className: 'bg-base-200',
211+
}

src/Accordion/Accordion.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React, { forwardRef, ReactNode } from 'react'
2+
import clsx from 'clsx'
3+
import { twMerge } from 'tailwind-merge'
4+
5+
import { IComponentBaseProps } from '../types'
6+
7+
import CollapseTitle from '../Collapse/CollapseTitle'
8+
import CollapseContent from '../Collapse/CollapseContent'
9+
10+
export type AccordionProps = Omit<
11+
React.HTMLAttributes<HTMLInputElement>,
12+
'type'
13+
> &
14+
IComponentBaseProps & {
15+
name?: string
16+
icon?: 'arrow' | 'plus'
17+
}
18+
19+
const Accordion = forwardRef<HTMLInputElement, AccordionProps>(
20+
(
21+
{ name = 'accordion', icon, dataTheme, className, children, ...props },
22+
ref
23+
): JSX.Element => {
24+
const classes = twMerge(
25+
'collapse',
26+
clsx({
27+
'collapse-arrow': icon === 'arrow',
28+
'collapse-plus': icon === 'plus',
29+
}),
30+
className
31+
)
32+
33+
return (
34+
<div data-theme={dataTheme} className={classes}>
35+
<input {...props} ref={ref} type="radio" name={name} />
36+
{children}
37+
</div>
38+
)
39+
}
40+
)
41+
42+
Accordion.displayName = 'Accordion'
43+
44+
export default Object.assign(Accordion, {
45+
Title: CollapseTitle,
46+
Content: CollapseContent,
47+
})

src/Accordion/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Accordion, { AccordionProps as TAccordionProps } from './Accordion'
2+
export type AccordionProps = TAccordionProps
3+
export default Accordion

0 commit comments

Comments
 (0)