11import type { Meta , StoryObj } from '@storybook/react-vite' ;
22import * as React from 'react' ;
3+ import { Avatar } from '../Avatar/Avatar' ;
34import { Button } from '../Button/Button' ;
5+ import { Tag } from '../Tag' ;
46import {
57 Popover ,
68 PopoverTrigger ,
@@ -28,19 +30,46 @@ export default meta;
2830
2931type Story = StoryObj < typeof Popover > ;
3032
33+ const DefaultContent = ( ) => {
34+ return (
35+ < div className = 'flex flex-col gap-24' >
36+ < div className = 'flex items-center gap-12' >
37+ < Avatar
38+ size = 'lg'
39+ src = 'https://plus.unsplash.com/premium_photo-1689551670902-19b441a6afde?q=80& w = 774 & auto = format & fit = crop & ixlib = rb - 4.1 .0 & ixid = M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA % 3 D % 3 D '
40+ />
41+ < div >
42+ < div className = 'heading-4-semi-bold text-base' > John Doe</ div >
43+ < Tag label = 'Status: Active' appearance = 'success' />
44+ </ div >
45+ </ div >
46+
47+ < div >
48+ < p className = 'heading-4-semi-bold text-base' > Notifications</ p >
49+ < p className = 'body-2 text-muted' >
50+ You have 10 notifications in your account
51+ </ p >
52+ </ div >
53+ < div className = 'flex gap-12' >
54+ < Button size = 'sm' appearance = 'gray' >
55+ View all
56+ </ Button >
57+ < Button size = 'sm' appearance = 'gray' >
58+ Settings
59+ </ Button >
60+ </ div >
61+ </ div >
62+ ) ;
63+ } ;
64+
3165export const Base : Story = {
3266 render : ( args : PopoverProps ) => (
3367 < Popover { ...args } >
3468 < PopoverTrigger >
35- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
36- Open Popover
37- </ button >
69+ < Button appearance = 'gray' > Open Popover</ Button >
3870 </ PopoverTrigger >
3971 < PopoverContent >
40- < div className = 'flex flex-col gap-8' >
41- < p className = 'heading-4-semi-bold text-base' > Notifications</ p >
42- < p className = 'body-2 text-muted' > You are all caught up. Good job!</ p >
43- </ div >
72+ < DefaultContent />
4473 </ PopoverContent >
4574 </ Popover >
4675 ) ,
@@ -51,63 +80,69 @@ export const WidthShowcase: Story = {
5180 < div className = 'flex items-center gap-16' >
5281 < Popover width = 'hug' >
5382 < PopoverTrigger >
54- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
55- Hug (default)
56- </ button >
83+ < Button appearance = 'gray' > Hug (default)</ Button >
5784 </ PopoverTrigger >
5885 < PopoverContent >
59- < p className = 'body-2 text-base' > Short content </ p >
86+ < p className = 'body-2 text-base' > Hug width </ p >
6087 </ PopoverContent >
6188 </ Popover >
6289
6390 < Popover width = 'fixed' >
6491 < PopoverTrigger >
65- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
66- Fixed (400px)
67- </ button >
92+ < Button appearance = 'gray' > Fixed (400px)</ Button >
6893 </ PopoverTrigger >
6994 < PopoverContent >
70- < p className = 'body-2 text-base' >
71- This panel is always 400px wide regardless of content.
72- </ p >
95+ < p className = 'body-2 text-base' > Fixed width</ p >
7396 </ PopoverContent >
7497 </ Popover >
7598 </ div >
7699 ) ,
77100} ;
78101
102+ export const PositionShowcase : Story = {
103+ render : ( ) => {
104+ const side = [ 'top' , 'bottom' , 'left' , 'right' ] as const ;
105+ const align = [ 'start' , 'center' , 'end' ] as const ;
106+
107+ return (
108+ < div className = 'flex flex-col items-center gap-16' >
109+ { align . map ( ( align ) => (
110+ < div key = { align } className = 'flex items-center gap-16' >
111+ { side . map ( ( side ) => (
112+ < Popover key = { side } side = { side } overlay = { false } align = { align } >
113+ < PopoverTrigger >
114+ < Button appearance = 'gray' > { `${ side } -${ align } ` } </ Button >
115+ </ PopoverTrigger >
116+ < PopoverContent >
117+ < DefaultContent />
118+ </ PopoverContent >
119+ </ Popover >
120+ ) ) }
121+ </ div >
122+ ) ) }
123+ </ div >
124+ ) ;
125+ } ,
126+ } ;
127+
79128export const WithOverlay : Story = {
80129 render : ( ) => (
81130 < div className = 'flex items-center gap-16' >
82- < Popover overlay >
131+ < Popover overlay width = 'fixed' >
83132 < PopoverTrigger >
84- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
85- With Overlay (default)
86- </ button >
133+ < Button appearance = 'gray' > With Overlay (default)</ Button >
87134 </ PopoverTrigger >
88135 < PopoverContent >
89- < div className = 'flex flex-col gap-8' >
90- < p className = 'heading-4-semi-bold text-base' > Modal Popover</ p >
91- < p className = 'body-2 text-muted' >
92- A backdrop overlay is shown and outside interaction is blocked.
93- </ p >
94- </ div >
136+ < DefaultContent />
95137 </ PopoverContent >
96138 </ Popover >
97139
98- < Popover overlay = { false } >
140+ < Popover overlay = { false } width = 'fixed' >
99141 < PopoverTrigger >
100- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
101- Without Overlay
102- </ button >
142+ < Button appearance = 'gray' > Without Overlay</ Button >
103143 </ PopoverTrigger >
104144 < PopoverContent >
105- < div className = 'flex flex-col gap-8' >
106- < p className = 'heading-4-semi-bold text-base' > Non-modal Popover</ p >
107- < p className = 'body-2 text-muted' >
108- No overlay. You can interact with elements behind this popover.
109- </ p >
110- </ div >
145+ < DefaultContent />
111146 </ PopoverContent >
112147 </ Popover >
113148 </ div >
@@ -125,16 +160,11 @@ export const Controlled: Story = {
125160 onOpenChange = { ( isOpen : boolean ) => setOpen ( isOpen ) }
126161 >
127162 < PopoverTrigger >
128- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
129- { open ? 'Close' : 'Open' } Popover
130- </ button >
163+ < Button appearance = 'gray' > { open ? 'Close' : 'Open' } Popover</ Button >
131164 </ PopoverTrigger >
132165 < PopoverContent >
133- < div className = 'flex flex-col gap-8' >
134- < p className = 'heading-4-semi-bold text-base' > Controlled</ p >
135- < p className = 'body-2 text-muted' >
136- Open state is managed externally.
137- </ p >
166+ < div className = 'flex flex-col gap-16' >
167+ < DefaultContent />
138168 < Button
139169 size = 'sm'
140170 appearance = 'gray'
@@ -154,15 +184,10 @@ export const Controlled: Story = {
154184} ;
155185
156186export const WithRenderProp : Story = {
157- name : 'With Render Prop (Custom Trigger)' ,
158187 render : ( ) => (
159188 < Popover >
160189 < PopoverTrigger
161- render = {
162- < Button size = 'md' appearance = 'gray' >
163- Custom Trigger
164- </ Button >
165- }
190+ render = { < Button appearance = 'gray' > Custom Trigger</ Button > }
166191 />
167192 < PopoverContent >
168193 < div className = 'flex flex-col gap-8' >
@@ -183,15 +208,11 @@ export const DetachedTrigger: Story = {
183208 return (
184209 < div className = 'flex items-center gap-16' >
185210 < PopoverTrigger handle = { handle } payload = { { label : 'Button A' } } >
186- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
187- Trigger A
188- </ button >
211+ < Button appearance = 'gray' > Trigger A</ Button >
189212 </ PopoverTrigger >
190213
191214 < PopoverTrigger handle = { handle } payload = { { label : 'Button B' } } >
192- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
193- Trigger B
194- </ button >
215+ < Button appearance = 'gray' > Trigger B</ Button >
195216 </ PopoverTrigger >
196217
197218 < Popover handle = { handle } >
@@ -212,22 +233,3 @@ export const DetachedTrigger: Story = {
212233 ) ;
213234 } ,
214235} ;
215-
216- export const PositionShowcase : Story = {
217- render : ( ) => (
218- < div className = 'flex items-center gap-16' >
219- { ( [ 'top' , 'bottom' , 'left' , 'right' ] as const ) . map ( ( side ) => (
220- < Popover key = { side } side = { side } overlay = { false } >
221- < PopoverTrigger >
222- < button className = 'body-2-semi-bold rounded-sm bg-muted px-16 py-8' >
223- { side }
224- </ button >
225- </ PopoverTrigger >
226- < PopoverContent >
227- < p className = 'body-2 text-base' > Side: { side } </ p >
228- </ PopoverContent >
229- </ Popover >
230- ) ) }
231- </ div >
232- ) ,
233- } ;
0 commit comments