torch-glare 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/lib/components/Drawer.tsx +368 -84
- package/apps/lib/components/{SectionCard.tsx → SectionBlock.tsx} +4 -4
- package/docs/components/alert-dialog.md +160 -0
- package/docs/components/date-picker.md +78 -0
- package/docs/components/dialog.md +189 -0
- package/docs/components/input-field.md +36 -0
- package/docs/components/section-block.md +275 -0
- package/docs/components/select.md +24 -0
- package/docs/components/simple-select.md +34 -0
- package/docs/components/table.md +75 -0
- package/docs/components/textarea.md +40 -0
- package/docs/components/toggle.md +59 -0
- package/docs/how-to/form-and-list-recipes.md +379 -0
- package/package.json +1 -1
|
@@ -1,118 +1,402 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { Drawer as DrawerPrimitive } from "vaul"
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Drawer as DrawerPrimitive } from "vaul";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
6
|
|
|
6
|
-
import { cn } from "../utils/cn"
|
|
7
|
+
import { cn } from "../utils/cn";
|
|
7
8
|
|
|
8
9
|
const Drawer = ({
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
shouldScaleBackground = true,
|
|
11
|
+
...props
|
|
11
12
|
}: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
)
|
|
17
|
-
Drawer.displayName = "Drawer"
|
|
13
|
+
<DrawerPrimitive.Root
|
|
14
|
+
shouldScaleBackground={shouldScaleBackground}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
Drawer.displayName = "Drawer";
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
+
const DrawerNested = (
|
|
21
|
+
props: React.ComponentProps<typeof DrawerPrimitive.NestedRoot>,
|
|
22
|
+
) => <DrawerPrimitive.NestedRoot {...props} />;
|
|
23
|
+
DrawerNested.displayName = "DrawerNested";
|
|
20
24
|
|
|
21
|
-
const
|
|
25
|
+
const DrawerTrigger = DrawerPrimitive.Trigger;
|
|
22
26
|
|
|
23
|
-
const
|
|
27
|
+
const DrawerPortal = DrawerPrimitive.Portal;
|
|
28
|
+
|
|
29
|
+
const DrawerClose = DrawerPrimitive.Close;
|
|
24
30
|
|
|
25
31
|
const DrawerOverlay = React.forwardRef<
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
React.ElementRef<typeof DrawerPrimitive.Overlay>,
|
|
33
|
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
|
|
28
34
|
>(({ className, ...props }, ref) => (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
))
|
|
35
|
-
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
|
|
35
|
+
<DrawerPrimitive.Overlay
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={cn("fixed inset-0 z-50 ", className)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
));
|
|
41
|
+
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
|
|
42
|
+
|
|
43
|
+
interface DrawerContentProps extends React.ComponentPropsWithoutRef<
|
|
44
|
+
typeof DrawerPrimitive.Content
|
|
45
|
+
> {
|
|
46
|
+
showHandle?: boolean;
|
|
47
|
+
notch?: React.ReactNode;
|
|
48
|
+
notchSide?: "left" | "right";
|
|
49
|
+
/**
|
|
50
|
+
* Show the dark "tray" frame (and panel border + inset shadow) around the
|
|
51
|
+
* drawer panel. Defaults to `true`. Set to `false` for bottom-anchored
|
|
52
|
+
* drawers (slide up from below) where a surrounding frame would just look
|
|
53
|
+
* like a stray border at the top.
|
|
54
|
+
*/
|
|
55
|
+
framed?: boolean;
|
|
56
|
+
wrapperClassName?: string;
|
|
57
|
+
trayClassName?: string;
|
|
58
|
+
}
|
|
36
59
|
|
|
37
60
|
const DrawerContent = React.forwardRef<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
>(
|
|
61
|
+
React.ElementRef<typeof DrawerPrimitive.Content>,
|
|
62
|
+
DrawerContentProps
|
|
63
|
+
>(
|
|
64
|
+
(
|
|
65
|
+
{
|
|
66
|
+
className,
|
|
67
|
+
children,
|
|
68
|
+
showHandle = true,
|
|
69
|
+
notch,
|
|
70
|
+
notchSide = "left",
|
|
71
|
+
framed: framedProp,
|
|
72
|
+
wrapperClassName,
|
|
73
|
+
trayClassName,
|
|
74
|
+
...props
|
|
75
|
+
},
|
|
76
|
+
ref,
|
|
77
|
+
) => {
|
|
78
|
+
const framed = framedProp ?? true;
|
|
79
|
+
return (
|
|
41
80
|
<DrawerPortal>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
81
|
+
<DrawerOverlay />
|
|
82
|
+
<DrawerPrimitive.Content
|
|
83
|
+
ref={ref}
|
|
84
|
+
className={cn(
|
|
85
|
+
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col items-stretch m-1",
|
|
86
|
+
wrapperClassName,
|
|
87
|
+
)}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
{notch && (
|
|
91
|
+
<div className={notchSide === "right" ? "self-end" : "self-start"}>
|
|
92
|
+
{React.isValidElement(notch)
|
|
93
|
+
? React.cloneElement(
|
|
94
|
+
notch as React.ReactElement<{ side?: "left" | "right" }>,
|
|
95
|
+
{ side: notchSide },
|
|
96
|
+
)
|
|
97
|
+
: notch}
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
<div
|
|
101
|
+
className={cn(
|
|
102
|
+
"flex flex-1 flex-col min-h-0",
|
|
103
|
+
framed
|
|
104
|
+
? "p-1.5 bg-black-400 shadow-[0_0_4px_rgba(0,0,0,0.2),0_0_30px_rgba(0,0,0,0.4)]"
|
|
105
|
+
: "p-0",
|
|
106
|
+
framed && notch
|
|
107
|
+
? notchSide === "right"
|
|
108
|
+
? "rounded-tr-none rounded-tl-[22px] rounded-b-[22px]"
|
|
109
|
+
: "rounded-tl-none rounded-tr-[22px] rounded-b-[22px]"
|
|
110
|
+
: framed
|
|
111
|
+
? "rounded-t-[22px]"
|
|
112
|
+
: "",
|
|
113
|
+
trayClassName,
|
|
114
|
+
)}
|
|
115
|
+
>
|
|
116
|
+
<div
|
|
45
117
|
className={cn(
|
|
46
|
-
|
|
47
|
-
|
|
118
|
+
"flex flex-1 flex-col gap-2 rounded-t-[16px] p-1.5 bg-[#F0F0F0] min-h-0",
|
|
119
|
+
framed && "border border-[#D4D4D4] shadow-[inset_0_-4px_16px_rgba(0,0,0,0.1)]",
|
|
120
|
+
className,
|
|
121
|
+
)}
|
|
122
|
+
>
|
|
123
|
+
{showHandle && !notch && (
|
|
124
|
+
<div className="mx-auto h-2 w-[100px] rounded-full bg-[#D4D4D4]" />
|
|
48
125
|
)}
|
|
49
|
-
{...props}
|
|
50
|
-
>
|
|
51
|
-
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
|
|
52
126
|
{children}
|
|
53
|
-
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</DrawerPrimitive.Content>
|
|
54
130
|
</DrawerPortal>
|
|
55
|
-
)
|
|
56
|
-
|
|
131
|
+
);
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
DrawerContent.displayName = "DrawerContent";
|
|
57
135
|
|
|
58
136
|
const DrawerHeader = ({
|
|
59
|
-
|
|
60
|
-
|
|
137
|
+
className,
|
|
138
|
+
...props
|
|
61
139
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
140
|
+
<div
|
|
141
|
+
className={cn(
|
|
142
|
+
"flex flex-row justify-between items-stretch gap-2 px-1 pt-1",
|
|
143
|
+
className,
|
|
144
|
+
)}
|
|
145
|
+
{...props}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
DrawerHeader.displayName = "DrawerHeader";
|
|
149
|
+
|
|
150
|
+
const drawerHeaderPane = cva(
|
|
151
|
+
"flex items-center gap-2 rounded-[14px] border p-2 bg-[#131415] border-[#2C2D2E] shadow-[0_0_32px_2px_rgba(0,0,0,0.05)]",
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const DrawerHeaderTitle = ({
|
|
155
|
+
className,
|
|
156
|
+
...props
|
|
157
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
158
|
+
<div className={cn(drawerHeaderPane(), className)} {...props} />
|
|
159
|
+
);
|
|
160
|
+
DrawerHeaderTitle.displayName = "DrawerHeaderTitle";
|
|
161
|
+
|
|
162
|
+
const DrawerHeaderActions = ({
|
|
163
|
+
className,
|
|
164
|
+
...props
|
|
165
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
166
|
+
<div
|
|
167
|
+
className={cn(drawerHeaderPane(), "justify-end", className)}
|
|
168
|
+
{...props}
|
|
169
|
+
/>
|
|
170
|
+
);
|
|
171
|
+
DrawerHeaderActions.displayName = "DrawerHeaderActions";
|
|
172
|
+
|
|
173
|
+
const drawerBadge = cva(
|
|
174
|
+
"inline-flex items-center justify-center rounded-[8px] px-1 py-0.5 typography-display-medium-medium uppercase",
|
|
175
|
+
{
|
|
176
|
+
variants: {
|
|
177
|
+
color: {
|
|
178
|
+
Blue: "bg-[rgba(0,117,255,0.5)] text-[#CCE3FF]",
|
|
179
|
+
Green: "bg-[rgba(34,197,94,0.5)] text-[#D1FAE5]",
|
|
180
|
+
Red: "bg-[rgba(239,68,68,0.5)] text-[#FEE2E2]",
|
|
181
|
+
Yellow: "bg-[rgba(234,179,8,0.5)] text-[#FEF3C7]",
|
|
182
|
+
Purple: "bg-[rgba(139,92,246,0.5)] text-[#EDE9FE]",
|
|
183
|
+
Gray: "bg-[rgba(255,255,255,0.15)] text-[#E5E5E5]",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
defaultVariants: { color: "Blue" },
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
interface DrawerBadgeProps
|
|
191
|
+
extends
|
|
192
|
+
Omit<React.HTMLAttributes<HTMLSpanElement>, "color">,
|
|
193
|
+
VariantProps<typeof drawerBadge> {}
|
|
194
|
+
|
|
195
|
+
const DrawerBadge = React.forwardRef<HTMLSpanElement, DrawerBadgeProps>(
|
|
196
|
+
({ className, color, ...props }, ref) => (
|
|
197
|
+
<span
|
|
198
|
+
ref={ref}
|
|
199
|
+
className={cn(drawerBadge({ color }), className)}
|
|
200
|
+
{...props}
|
|
65
201
|
/>
|
|
66
|
-
)
|
|
67
|
-
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
DrawerBadge.displayName = "DrawerBadge";
|
|
68
205
|
|
|
69
206
|
const DrawerFooter = ({
|
|
70
|
-
|
|
71
|
-
|
|
207
|
+
className,
|
|
208
|
+
...props
|
|
72
209
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
)
|
|
78
|
-
DrawerFooter.displayName = "DrawerFooter"
|
|
210
|
+
<div
|
|
211
|
+
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
|
212
|
+
{...props}
|
|
213
|
+
/>
|
|
214
|
+
);
|
|
215
|
+
DrawerFooter.displayName = "DrawerFooter";
|
|
79
216
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
217
|
+
interface DrawerNotchProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
218
|
+
side?: "left" | "right";
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const DrawerNotch = ({
|
|
222
|
+
className,
|
|
223
|
+
children,
|
|
224
|
+
side = "left",
|
|
225
|
+
...props
|
|
226
|
+
}: DrawerNotchProps) => {
|
|
227
|
+
// Wedge bridges the notch's bottom-edge corner into the tray's top edge.
|
|
228
|
+
// For a left-attached notch (the default), the wedge sits at the notch's
|
|
229
|
+
// bottom-right; for a right-attached notch, mirror it to the bottom-left.
|
|
230
|
+
const wedge = (
|
|
231
|
+
<svg
|
|
232
|
+
aria-hidden
|
|
233
|
+
width="12"
|
|
234
|
+
height="12"
|
|
235
|
+
viewBox="0 0 12 12"
|
|
236
|
+
className="block shrink-0 self-end"
|
|
237
|
+
>
|
|
238
|
+
<path
|
|
239
|
+
d={
|
|
240
|
+
side === "right"
|
|
241
|
+
? "M 12 0 L 12 12 L 0 12 A 12 12 0 0 0 12 0 Z"
|
|
242
|
+
: "M 0 0 L 0 12 L 12 12 A 12 12 0 0 1 0 0 Z"
|
|
243
|
+
}
|
|
244
|
+
fill="#434446"
|
|
245
|
+
/>
|
|
246
|
+
</svg>
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<div className="relative flex flex-row items-end">
|
|
251
|
+
{side === "right" && wedge}
|
|
252
|
+
<div
|
|
86
253
|
className={cn(
|
|
87
|
-
|
|
88
|
-
|
|
254
|
+
"flex items-center gap-1 rounded-t-[18px] bg-black-400 px-1.5 pt-1.5 pb-1.5",
|
|
255
|
+
side === "right" ? "flex-row-reverse" : "flex-row",
|
|
256
|
+
className,
|
|
89
257
|
)}
|
|
90
258
|
{...props}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
259
|
+
>
|
|
260
|
+
{children}
|
|
261
|
+
</div>
|
|
262
|
+
{side === "left" && wedge}
|
|
263
|
+
</div>
|
|
264
|
+
);
|
|
265
|
+
};
|
|
266
|
+
DrawerNotch.displayName = "DrawerNotch";
|
|
267
|
+
|
|
268
|
+
const DrawerNotchClose = React.forwardRef<
|
|
269
|
+
HTMLButtonElement,
|
|
270
|
+
React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
271
|
+
>(({ className, children, ...props }, ref) => (
|
|
272
|
+
<button
|
|
273
|
+
ref={ref}
|
|
274
|
+
type="button"
|
|
275
|
+
aria-label="Close"
|
|
276
|
+
className={cn(
|
|
277
|
+
"inline-flex h-[22px] w-[22px] items-center justify-center rounded-[13px] bg-white/15 text-content-presentation-global-primary transition-colors hover:bg-white/25",
|
|
278
|
+
className,
|
|
279
|
+
)}
|
|
280
|
+
{...props}
|
|
281
|
+
>
|
|
282
|
+
{children ?? <i className="ri-close-fill text-[14px]" />}
|
|
283
|
+
</button>
|
|
284
|
+
));
|
|
285
|
+
DrawerNotchClose.displayName = "DrawerNotchClose";
|
|
286
|
+
|
|
287
|
+
const drawerNotchPill = cva(
|
|
288
|
+
"inline-flex items-center gap-1 rounded-[16px] px-1.5 py-0.5 typography-body-small-medium text-white transition-colors",
|
|
289
|
+
{
|
|
290
|
+
variants: {
|
|
291
|
+
color: {
|
|
292
|
+
Yellow: "bg-white/15 hover:bg-white/25",
|
|
293
|
+
Blue: "bg-[#005ECC] hover:bg-[#0070E0]",
|
|
294
|
+
Gray: "bg-white/10 hover:bg-white/20",
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
defaultVariants: { color: "Yellow" },
|
|
298
|
+
},
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
interface DrawerNotchPillProps
|
|
302
|
+
extends
|
|
303
|
+
Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "color">,
|
|
304
|
+
VariantProps<typeof drawerNotchPill> {}
|
|
305
|
+
|
|
306
|
+
const DrawerNotchPill = React.forwardRef<
|
|
307
|
+
HTMLButtonElement,
|
|
308
|
+
DrawerNotchPillProps
|
|
309
|
+
>(({ className, color, children, ...props }, ref) => (
|
|
310
|
+
<button
|
|
311
|
+
ref={ref}
|
|
312
|
+
type="button"
|
|
313
|
+
className={cn(drawerNotchPill({ color }), className)}
|
|
314
|
+
{...props}
|
|
315
|
+
>
|
|
316
|
+
{children}
|
|
317
|
+
</button>
|
|
318
|
+
));
|
|
319
|
+
DrawerNotchPill.displayName = "DrawerNotchPill";
|
|
320
|
+
|
|
321
|
+
const DrawerNotchDivider = ({
|
|
322
|
+
className,
|
|
323
|
+
...props
|
|
324
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
325
|
+
<div
|
|
326
|
+
aria-hidden
|
|
327
|
+
className={cn("h-[18px] w-px bg-white/20", className)}
|
|
328
|
+
{...props}
|
|
329
|
+
/>
|
|
330
|
+
);
|
|
331
|
+
DrawerNotchDivider.displayName = "DrawerNotchDivider";
|
|
332
|
+
|
|
333
|
+
interface DrawerNotchAppProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
334
|
+
icon?: React.ReactNode;
|
|
335
|
+
name: React.ReactNode;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const DrawerNotchApp = ({
|
|
339
|
+
className,
|
|
340
|
+
icon,
|
|
341
|
+
name,
|
|
342
|
+
...props
|
|
343
|
+
}: DrawerNotchAppProps) => (
|
|
344
|
+
<div className={cn("flex items-center gap-2.5 px-1", className)} {...props}>
|
|
345
|
+
{icon && (
|
|
346
|
+
<div className="flex h-[22px] w-[22px] items-center justify-center overflow-hidden rounded-[5.6px] bg-black shadow-[0_0_4.66px_rgba(0,0,0,0.3),0_0.75px_0.75px_rgba(0,0,0,0.2)]">
|
|
347
|
+
{icon}
|
|
348
|
+
</div>
|
|
349
|
+
)}
|
|
350
|
+
<span className="text-white text-[14px] leading-[1.475]">{name}</span>
|
|
351
|
+
</div>
|
|
352
|
+
);
|
|
353
|
+
DrawerNotchApp.displayName = "DrawerNotchApp";
|
|
354
|
+
|
|
355
|
+
const DrawerTitle = React.forwardRef<
|
|
356
|
+
React.ElementRef<typeof DrawerPrimitive.Title>,
|
|
357
|
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
|
|
358
|
+
>(({ className, ...props }, ref) => (
|
|
359
|
+
<DrawerPrimitive.Title
|
|
360
|
+
ref={ref}
|
|
361
|
+
className={cn(
|
|
362
|
+
"typography-display-medium-medium uppercase text-white leading-none",
|
|
363
|
+
className,
|
|
364
|
+
)}
|
|
365
|
+
{...props}
|
|
366
|
+
/>
|
|
367
|
+
));
|
|
368
|
+
DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
|
|
94
369
|
|
|
95
370
|
const DrawerDescription = React.forwardRef<
|
|
96
|
-
|
|
97
|
-
|
|
371
|
+
React.ElementRef<typeof DrawerPrimitive.Description>,
|
|
372
|
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
|
|
98
373
|
>(({ className, ...props }, ref) => (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
))
|
|
105
|
-
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
|
|
374
|
+
<DrawerPrimitive.Description
|
|
375
|
+
ref={ref}
|
|
376
|
+
className={cn("typography-body-small-regular text-[#9FA0A1]", className)}
|
|
377
|
+
{...props}
|
|
378
|
+
/>
|
|
379
|
+
));
|
|
380
|
+
DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
|
|
106
381
|
|
|
107
382
|
export {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
383
|
+
Drawer,
|
|
384
|
+
DrawerNested,
|
|
385
|
+
DrawerPortal,
|
|
386
|
+
DrawerOverlay,
|
|
387
|
+
DrawerTrigger,
|
|
388
|
+
DrawerClose,
|
|
389
|
+
DrawerContent,
|
|
390
|
+
DrawerHeader,
|
|
391
|
+
DrawerHeaderTitle,
|
|
392
|
+
DrawerHeaderActions,
|
|
393
|
+
DrawerBadge,
|
|
394
|
+
DrawerFooter,
|
|
395
|
+
DrawerTitle,
|
|
396
|
+
DrawerDescription,
|
|
397
|
+
DrawerNotch,
|
|
398
|
+
DrawerNotchClose,
|
|
399
|
+
DrawerNotchPill,
|
|
400
|
+
DrawerNotchDivider,
|
|
401
|
+
DrawerNotchApp,
|
|
402
|
+
};
|
|
@@ -14,7 +14,7 @@ const titleBadge = cva(
|
|
|
14
14
|
Orange: "bg-red-orange-900",
|
|
15
15
|
Purple: "bg-violet-900",
|
|
16
16
|
Pink: "bg-medium-violet-red-900",
|
|
17
|
-
Gray: "bg-background-presentation-
|
|
17
|
+
Gray: "bg-background-presentation-badge-gray",
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
defaultVariants: { color: "Blue" },
|
|
@@ -23,7 +23,7 @@ const titleBadge = cva(
|
|
|
23
23
|
|
|
24
24
|
export type SectionColor = NonNullable<VariantProps<typeof titleBadge>["color"]>;
|
|
25
25
|
|
|
26
|
-
export interface
|
|
26
|
+
export interface SectionBlockProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
27
27
|
color?: SectionColor;
|
|
28
28
|
title?: ReactNode;
|
|
29
29
|
containerClassName?: string;
|
|
@@ -31,7 +31,7 @@ export interface SectionCardProps extends Omit<HTMLAttributes<HTMLDivElement>, "
|
|
|
31
31
|
bodyClassName?: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export const
|
|
34
|
+
export const SectionBlock = forwardRef<HTMLDivElement, SectionBlockProps>(
|
|
35
35
|
(
|
|
36
36
|
{
|
|
37
37
|
children,
|
|
@@ -68,4 +68,4 @@ export const SectionCard = forwardRef<HTMLDivElement, SectionCardProps>(
|
|
|
68
68
|
},
|
|
69
69
|
);
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
SectionBlock.displayName = "SectionBlock";
|
|
@@ -456,6 +456,166 @@ function PermissionAlert() {
|
|
|
456
456
|
| `variant` | `ButtonVariant` | `'RedSecStyle'` | Button variant |
|
|
457
457
|
| `buttonType` | `'button' \| 'icon'` | `'icon'` | Button type |
|
|
458
458
|
|
|
459
|
+
## Known Limitations & Frontend Patterns
|
|
460
|
+
|
|
461
|
+
### Every AlertDialog subcomponent ships without panel/typography defaults — and worse than `Dialog`
|
|
462
|
+
|
|
463
|
+
`AlertDialogContent` ships with `p-[12px]` (too tight), `AlertDialogHeader` with `flex justify-between` (instead of `flex-col` for stacked title+description), `AlertDialogFooter` with `flex-col-reverse sm:flex-row` (vertical-on-mobile), and `AlertDialogDescription` with the bizarre `bg-background-presentation-form-base border ... rounded-[8px] p-[24px_48px_48px_48px]` — a 48 px-padded bordered box wrapped around what should be a one-line subtitle.
|
|
464
|
+
|
|
465
|
+
**Production-tested override** — patch `AlertDialog.tsx` once after `npx torch-glare add AlertDialog`. Same surface-token corrections as `Dialog`: use `bg-background-presentation-body-primary` and `text-content-presentation-global-*`, never `*-system-*` and never `form-base`.
|
|
466
|
+
|
|
467
|
+
```tsx
|
|
468
|
+
"use client";
|
|
469
|
+
|
|
470
|
+
import * as React from "react";
|
|
471
|
+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
|
472
|
+
import { cn } from "@/utils/cn";
|
|
473
|
+
|
|
474
|
+
const AlertDialog = AlertDialogPrimitive.Root;
|
|
475
|
+
const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
476
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
477
|
+
|
|
478
|
+
const AlertDialogOverlay = React.forwardRef<
|
|
479
|
+
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
|
480
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
|
481
|
+
>(({ className, ...props }, ref) => (
|
|
482
|
+
<AlertDialogPrimitive.Overlay
|
|
483
|
+
ref={ref}
|
|
484
|
+
className={cn(
|
|
485
|
+
"fixed inset-0 z-50 bg-black/60",
|
|
486
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
487
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
488
|
+
className,
|
|
489
|
+
)}
|
|
490
|
+
{...props}
|
|
491
|
+
/>
|
|
492
|
+
));
|
|
493
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
494
|
+
|
|
495
|
+
const AlertDialogContent = React.forwardRef<
|
|
496
|
+
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
|
497
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
|
|
498
|
+
>(({ className, ...props }, ref) => (
|
|
499
|
+
<AlertDialogPortal>
|
|
500
|
+
<AlertDialogOverlay />
|
|
501
|
+
<AlertDialogPrimitive.Content
|
|
502
|
+
ref={ref}
|
|
503
|
+
className={cn(
|
|
504
|
+
"fixed left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]",
|
|
505
|
+
"flex flex-col items-stretch justify-start",
|
|
506
|
+
"w-[92vw] sm:max-w-md",
|
|
507
|
+
"bg-background-presentation-body-primary",
|
|
508
|
+
"border border-border-presentation-global-primary",
|
|
509
|
+
"rounded-xl shadow-lg",
|
|
510
|
+
"p-0 gap-0 overflow-hidden",
|
|
511
|
+
"duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
512
|
+
className,
|
|
513
|
+
)}
|
|
514
|
+
{...props}
|
|
515
|
+
/>
|
|
516
|
+
</AlertDialogPortal>
|
|
517
|
+
));
|
|
518
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
519
|
+
|
|
520
|
+
const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
521
|
+
<div
|
|
522
|
+
className={cn("flex flex-col space-y-1.5 text-left px-6 pt-5 pb-2", className)}
|
|
523
|
+
{...props}
|
|
524
|
+
/>
|
|
525
|
+
);
|
|
526
|
+
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
527
|
+
|
|
528
|
+
const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
529
|
+
<div
|
|
530
|
+
className={cn("flex flex-row justify-end gap-2 px-6 py-4", className)}
|
|
531
|
+
{...props}
|
|
532
|
+
/>
|
|
533
|
+
);
|
|
534
|
+
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
535
|
+
|
|
536
|
+
const AlertDialogTitle = React.forwardRef<
|
|
537
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
538
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
|
539
|
+
>(({ className, ...props }, ref) => (
|
|
540
|
+
<AlertDialogPrimitive.Title
|
|
541
|
+
ref={ref}
|
|
542
|
+
className={cn(
|
|
543
|
+
"typography-headers-small-semibold text-content-presentation-global-primary",
|
|
544
|
+
className,
|
|
545
|
+
)}
|
|
546
|
+
{...props}
|
|
547
|
+
/>
|
|
548
|
+
));
|
|
549
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
550
|
+
|
|
551
|
+
const AlertDialogDescription = React.forwardRef<
|
|
552
|
+
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
|
553
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
|
554
|
+
>(({ className, ...props }, ref) => (
|
|
555
|
+
<AlertDialogPrimitive.Description
|
|
556
|
+
ref={ref}
|
|
557
|
+
className={cn(
|
|
558
|
+
"typography-body-small-regular text-content-presentation-global-secondary px-6 pb-2",
|
|
559
|
+
className,
|
|
560
|
+
)}
|
|
561
|
+
{...props}
|
|
562
|
+
/>
|
|
563
|
+
));
|
|
564
|
+
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
565
|
+
|
|
566
|
+
const AlertDialogAction = AlertDialogPrimitive.Action;
|
|
567
|
+
const AlertDialogCancel = AlertDialogPrimitive.Cancel;
|
|
568
|
+
|
|
569
|
+
export {
|
|
570
|
+
AlertDialog,
|
|
571
|
+
AlertDialogTrigger,
|
|
572
|
+
AlertDialogPortal,
|
|
573
|
+
AlertDialogOverlay,
|
|
574
|
+
AlertDialogContent,
|
|
575
|
+
AlertDialogHeader,
|
|
576
|
+
AlertDialogFooter,
|
|
577
|
+
AlertDialogTitle,
|
|
578
|
+
AlertDialogDescription,
|
|
579
|
+
AlertDialogAction,
|
|
580
|
+
AlertDialogCancel,
|
|
581
|
+
};
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Critical default decisions:
|
|
585
|
+
|
|
586
|
+
- **Drop the bordered box on `AlertDialogDescription`.** The shipped default wraps the description in a 48 px-padded bordered box, which produces a visually heavy nested panel. Description is a one-line subtitle — same typography pattern as `DialogDescription`.
|
|
587
|
+
- **`AlertDialogHeader` → `flex flex-col` (NOT `flex justify-between`)** so title and description stack with proper rhythm.
|
|
588
|
+
- **`AlertDialogFooter` → `flex-row justify-end`** on all viewports, no `flex-col-reverse sm:flex-row` weirdness.
|
|
589
|
+
- **`AlertDialogDescription` carries `px-6 pb-2`** since alert dialogs typically don't have a separate body section between header and footer.
|
|
590
|
+
- Surface and text tokens are **identical to `Dialog`** — `bg-background-presentation-body-primary` + `text-content-presentation-global-primary` + `text-content-presentation-global-secondary`. Never `*-system-*`. Never `form-base`. Never `action-secondary`.
|
|
591
|
+
|
|
592
|
+
### Standard usage after the override
|
|
593
|
+
|
|
594
|
+
Once the patches above are in place, every consumer renders correctly with bare components:
|
|
595
|
+
|
|
596
|
+
```tsx
|
|
597
|
+
<AlertDialog open={open} onOpenChange={setOpen}>
|
|
598
|
+
<AlertDialogContent>
|
|
599
|
+
<AlertDialogHeader>
|
|
600
|
+
<AlertDialogTitle>Delete this template?</AlertDialogTitle>
|
|
601
|
+
<AlertDialogDescription>
|
|
602
|
+
This action cannot be undone. The template will be permanently removed.
|
|
603
|
+
</AlertDialogDescription>
|
|
604
|
+
</AlertDialogHeader>
|
|
605
|
+
<AlertDialogFooter>
|
|
606
|
+
<AlertDialogCancel asChild>
|
|
607
|
+
<Button type="button" variant="BorderStyle" size="M">Cancel</Button>
|
|
608
|
+
</AlertDialogCancel>
|
|
609
|
+
<AlertDialogAction asChild>
|
|
610
|
+
<Button type="button" variant="RedColStyle" size="M" onClick={handleDelete}>
|
|
611
|
+
Delete
|
|
612
|
+
</Button>
|
|
613
|
+
</AlertDialogAction>
|
|
614
|
+
</AlertDialogFooter>
|
|
615
|
+
</AlertDialogContent>
|
|
616
|
+
</AlertDialog>
|
|
617
|
+
```
|
|
618
|
+
|
|
459
619
|
## Variants
|
|
460
620
|
|
|
461
621
|
### Default Variant
|