Skip to content

Commit b41fe7b

Browse files
committed
mc
Signed-off-by: Simon Bruneaud <simon.bruneaud@ledger.fr>
1 parent 2665ee0 commit b41fe7b

File tree

3 files changed

+99
-162
lines changed

3 files changed

+99
-162
lines changed

libs/ui-react/src/lib/Components/Popover/Popover.stories.tsx

Lines changed: 78 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { Meta, StoryObj } from '@storybook/react-vite';
22
import * as React from 'react';
3+
import { Avatar } from '../Avatar/Avatar';
34
import { Button } from '../Button/Button';
5+
import { Tag } from '../Tag';
46
import {
57
Popover,
68
PopoverTrigger,
@@ -28,19 +30,46 @@ export default meta;
2830

2931
type 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%3D%3D'
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+
3165
export 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+
79128
export 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

156186
export 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-
};

libs/ui-react/src/lib/Components/Popover/Popover.tsx

Lines changed: 16 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { cn, createSafeContext } from '@ledgerhq/lumen-utils-shared';
21
import { Popover as PopoverPrimitive } from '@base-ui/react/popover';
2+
import { cn, createSafeContext } from '@ledgerhq/lumen-utils-shared';
33
import { cva } from 'class-variance-authority';
44
import type {
55
PopoverProps,
@@ -13,10 +13,10 @@ const [PopoverContextProvider, usePopoverContext] =
1313

1414
const popupVariants = cva(
1515
[
16-
'z-menu overflow-hidden rounded-md bg-canvas-sheet p-16',
16+
'overflow-hidden rounded-md bg-canvas-sheet p-16',
1717
'shadow-sm',
18-
'data-[state=open]:animate-fade-in',
19-
'data-[state=closed]:animate-fade-out',
18+
'data-open:animate-fade-in data-open:duration-100!',
19+
'data-closed:animate-fade-out data-closed:duration-100!',
2020
],
2121
{
2222
variants: {
@@ -32,9 +32,9 @@ const popupVariants = cva(
3232
);
3333

3434
const overlayStyles = cn(
35-
'fixed inset-0 z-dialog-overlay bg-canvas-overlay backdrop-blur-sm',
36-
'data-[state=open]:animate-fade-in',
37-
'data-[state=closed]:animate-fade-out',
35+
'fixed inset-0 z-dialog-overlay bg-canvas-overlay',
36+
'data-open:animate-fade-in data-open:duration-100!',
37+
'data-closed:animate-fade-out',
3838
);
3939

4040
/**
@@ -63,13 +63,10 @@ function Popover<Payload = unknown>({
6363
open,
6464
defaultOpen,
6565
onOpenChange,
66-
overlay = true,
66+
overlay = false,
6767
side = 'bottom',
68-
sideOffset = 4,
68+
sideOffset = 8,
6969
align = 'start',
70-
alignOffset = 0,
71-
collisionPadding,
72-
collisionBoundary,
7370
width = 'hug',
7471
handle,
7572
children,
@@ -81,14 +78,11 @@ function Popover<Payload = unknown>({
8178
side,
8279
sideOffset,
8380
align,
84-
alignOffset,
85-
collisionPadding,
86-
collisionBoundary,
8781
width,
8882
}}
8983
>
9084
<PopoverPrimitive.Root
91-
data-slot="popover"
85+
data-slot='popover'
9286
open={open}
9387
defaultOpen={defaultOpen}
9488
onOpenChange={onOpenChange}
@@ -107,15 +101,6 @@ function Popover<Payload = unknown>({
107101
* Use the `render` prop to compose with a custom component.
108102
*
109103
* @see {@link https://ldls.vercel.app/?path=/docs/components-popover-overview--docs Storybook}
110-
*
111-
* @example
112-
* <PopoverTrigger>
113-
* <button>Open popover</button>
114-
* </PopoverTrigger>
115-
*
116-
* @example
117-
* // With render prop for custom trigger
118-
* <PopoverTrigger render={<IconButton icon={SettingsIcon} />} />
119104
*/
120105
const PopoverTrigger = <Payload,>({
121106
handle,
@@ -126,7 +111,7 @@ const PopoverTrigger = <Payload,>({
126111
...props
127112
}: PopoverTriggerProps<Payload>) => (
128113
<PopoverPrimitive.Trigger
129-
data-slot="popover-trigger"
114+
data-slot='popover-trigger'
130115
handle={handle}
131116
payload={payload}
132117
render={render}
@@ -143,29 +128,9 @@ PopoverTrigger.displayName = 'PopoverTrigger';
143128
* optional Backdrop, Positioner, and Popup.
144129
*
145130
* @see {@link https://ldls.vercel.app/?path=/docs/components-popover-overview--docs Storybook}
146-
*
147-
* @example
148-
* <PopoverContent>
149-
* <p>Popover content here</p>
150-
* </PopoverContent>
151-
*
152-
* @example
153-
* // With custom className
154-
* <PopoverContent className="min-w-320">
155-
* <p>Wide content</p>
156-
* </PopoverContent>
157131
*/
158132
function PopoverContent({ className, children }: PopoverContentProps) {
159-
const {
160-
overlay,
161-
side,
162-
sideOffset,
163-
align,
164-
alignOffset,
165-
collisionPadding,
166-
collisionBoundary,
167-
width,
168-
} = usePopoverContext({
133+
const { overlay, side, sideOffset, align, width } = usePopoverContext({
169134
consumerName: 'PopoverContent',
170135
contextRequired: true,
171136
});
@@ -174,21 +139,19 @@ function PopoverContent({ className, children }: PopoverContentProps) {
174139
<PopoverPrimitive.Portal>
175140
{overlay && (
176141
<PopoverPrimitive.Backdrop
177-
data-slot="popover-overlay"
142+
data-slot='popover-overlay'
178143
className={overlayStyles}
179144
/>
180145
)}
181146
<PopoverPrimitive.Positioner
182-
data-slot="popover-positioner"
147+
data-slot='popover-positioner'
148+
className='z-menu'
183149
side={side}
184150
sideOffset={sideOffset}
185151
align={align}
186-
alignOffset={alignOffset}
187-
collisionPadding={collisionPadding}
188-
collisionBoundary={collisionBoundary}
189152
>
190153
<PopoverPrimitive.Popup
191-
data-slot="popover-content"
154+
data-slot='popover-content'
192155
className={cn(popupVariants({ width }), className)}
193156
>
194157
{children}

0 commit comments

Comments
 (0)