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.
@@ -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
- shouldScaleBackground = true,
10
- ...props
10
+ shouldScaleBackground = true,
11
+ ...props
11
12
  }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
12
- <DrawerPrimitive.Root
13
- shouldScaleBackground={shouldScaleBackground}
14
- {...props}
15
- />
16
- )
17
- Drawer.displayName = "Drawer"
13
+ <DrawerPrimitive.Root
14
+ shouldScaleBackground={shouldScaleBackground}
15
+ {...props}
16
+ />
17
+ );
18
+ Drawer.displayName = "Drawer";
18
19
 
19
- const DrawerTrigger = DrawerPrimitive.Trigger
20
+ const DrawerNested = (
21
+ props: React.ComponentProps<typeof DrawerPrimitive.NestedRoot>,
22
+ ) => <DrawerPrimitive.NestedRoot {...props} />;
23
+ DrawerNested.displayName = "DrawerNested";
20
24
 
21
- const DrawerPortal = DrawerPrimitive.Portal
25
+ const DrawerTrigger = DrawerPrimitive.Trigger;
22
26
 
23
- const DrawerClose = DrawerPrimitive.Close
27
+ const DrawerPortal = DrawerPrimitive.Portal;
28
+
29
+ const DrawerClose = DrawerPrimitive.Close;
24
30
 
25
31
  const DrawerOverlay = React.forwardRef<
26
- React.ElementRef<typeof DrawerPrimitive.Overlay>,
27
- React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
32
+ React.ElementRef<typeof DrawerPrimitive.Overlay>,
33
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
28
34
  >(({ className, ...props }, ref) => (
29
- <DrawerPrimitive.Overlay
30
- ref={ref}
31
- className={cn("fixed inset-0 z-50 bg-black/80", className)}
32
- {...props}
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
- React.ElementRef<typeof DrawerPrimitive.Content>,
39
- React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
40
- >(({ className, children, ...props }, ref) => (
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
- <DrawerOverlay />
43
- <DrawerPrimitive.Content
44
- ref={ref}
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
- "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] bg-background-system-body-primary m-1 border-border-system-global-primary",
47
- className
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
- </DrawerPrimitive.Content>
127
+ </div>
128
+ </div>
129
+ </DrawerPrimitive.Content>
54
130
  </DrawerPortal>
55
- ))
56
- DrawerContent.displayName = "DrawerContent"
131
+ );
132
+ },
133
+ );
134
+ DrawerContent.displayName = "DrawerContent";
57
135
 
58
136
  const DrawerHeader = ({
59
- className,
60
- ...props
137
+ className,
138
+ ...props
61
139
  }: React.HTMLAttributes<HTMLDivElement>) => (
62
- <div
63
- className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
64
- {...props}
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
- DrawerHeader.displayName = "DrawerHeader"
202
+ ),
203
+ );
204
+ DrawerBadge.displayName = "DrawerBadge";
68
205
 
69
206
  const DrawerFooter = ({
70
- className,
71
- ...props
207
+ className,
208
+ ...props
72
209
  }: React.HTMLAttributes<HTMLDivElement>) => (
73
- <div
74
- className={cn("mt-auto flex flex-col gap-2 p-4", className)}
75
- {...props}
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
- const DrawerTitle = React.forwardRef<
81
- React.ElementRef<typeof DrawerPrimitive.Title>,
82
- React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
83
- >(({ className, ...props }, ref) => (
84
- <DrawerPrimitive.Title
85
- ref={ref}
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
- "text-lg font-semibold leading-none tracking-tight",
88
- className
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
- DrawerTitle.displayName = DrawerPrimitive.Title.displayName
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
- React.ElementRef<typeof DrawerPrimitive.Description>,
97
- React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
371
+ React.ElementRef<typeof DrawerPrimitive.Description>,
372
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
98
373
  >(({ className, ...props }, ref) => (
99
- <DrawerPrimitive.Description
100
- ref={ref}
101
- className={cn("text-sm text-muted-foreground", className)}
102
- {...props}
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
- Drawer,
109
- DrawerPortal,
110
- DrawerOverlay,
111
- DrawerTrigger,
112
- DrawerClose,
113
- DrawerContent,
114
- DrawerHeader,
115
- DrawerFooter,
116
- DrawerTitle,
117
- DrawerDescription,
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-button-primary",
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 SectionCardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
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 SectionCard = forwardRef<HTMLDivElement, SectionCardProps>(
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
- SectionCard.displayName = "SectionCard";
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