@brijbyte/agentic-ui 0.0.1 → 0.0.2

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.
Files changed (135) hide show
  1. package/README.md +183 -111
  2. package/dist/accordion/accordion.css +6 -10
  3. package/dist/accordion/accordion.module.js.map +1 -1
  4. package/dist/alert-dialog/alert-dialog.css +84 -0
  5. package/dist/alert-dialog/alert-dialog.d.ts +44 -0
  6. package/dist/alert-dialog/alert-dialog.d.ts.map +1 -0
  7. package/dist/alert-dialog/alert-dialog.js +46 -0
  8. package/dist/alert-dialog/alert-dialog.js.map +1 -0
  9. package/dist/alert-dialog/alert-dialog.module.css.d.ts +2 -0
  10. package/dist/alert-dialog/alert-dialog.module.js +14 -0
  11. package/dist/alert-dialog/alert-dialog.module.js.map +1 -0
  12. package/dist/alert-dialog/index.d.ts +3 -0
  13. package/dist/alert-dialog/index.js +4 -0
  14. package/dist/alert-dialog/parts.d.ts +28 -0
  15. package/dist/alert-dialog/parts.d.ts.map +1 -0
  16. package/dist/alert-dialog/parts.js +62 -0
  17. package/dist/alert-dialog/parts.js.map +1 -0
  18. package/dist/badge/badge.css +3 -7
  19. package/dist/badge/badge.module.js.map +1 -1
  20. package/dist/button/button.css +14 -14
  21. package/dist/button/button.module.js.map +1 -1
  22. package/dist/card/card.css +5 -9
  23. package/dist/card/card.module.js.map +1 -1
  24. package/dist/checkbox/checkbox.css +3 -7
  25. package/dist/checkbox/checkbox.module.js.map +1 -1
  26. package/dist/collapsible/collapsible.css +7 -11
  27. package/dist/collapsible/collapsible.module.js.map +1 -1
  28. package/dist/context-menu/context-menu.css +151 -0
  29. package/dist/context-menu/context-menu.d.ts +36 -0
  30. package/dist/context-menu/context-menu.d.ts.map +1 -0
  31. package/dist/context-menu/context-menu.js +54 -0
  32. package/dist/context-menu/context-menu.js.map +1 -0
  33. package/dist/context-menu/context-menu.module.css.d.ts +2 -0
  34. package/dist/context-menu/context-menu.module.js +18 -0
  35. package/dist/context-menu/context-menu.module.js.map +1 -0
  36. package/dist/context-menu/index.d.ts +3 -0
  37. package/dist/context-menu/index.js +4 -0
  38. package/dist/context-menu/parts.d.ts +38 -0
  39. package/dist/context-menu/parts.d.ts.map +1 -0
  40. package/dist/context-menu/parts.js +91 -0
  41. package/dist/context-menu/parts.js.map +1 -0
  42. package/dist/dialog/dialog.css +27 -22
  43. package/dist/dialog/dialog.d.ts +8 -0
  44. package/dist/dialog/dialog.d.ts.map +1 -1
  45. package/dist/dialog/dialog.js +7 -4
  46. package/dist/dialog/dialog.js.map +1 -1
  47. package/dist/dialog/dialog.module.js +2 -0
  48. package/dist/dialog/dialog.module.js.map +1 -1
  49. package/dist/drawer/drawer.css +9 -13
  50. package/dist/drawer/drawer.module.js.map +1 -1
  51. package/dist/index.css +1630 -1353
  52. package/dist/index.d.ts +24 -18
  53. package/dist/index.js +10 -1
  54. package/dist/input/input.css +5 -9
  55. package/dist/input/input.module.js.map +1 -1
  56. package/dist/layer-order.css +22 -0
  57. package/dist/menu/menu.css +13 -17
  58. package/dist/menu/menu.module.js.map +1 -1
  59. package/dist/number-field/number-field.css +12 -16
  60. package/dist/number-field/number-field.module.js.map +1 -1
  61. package/dist/progress/progress.css +1 -5
  62. package/dist/progress/progress.module.js.map +1 -1
  63. package/dist/reset.css +6 -6
  64. package/dist/select/select.css +14 -16
  65. package/dist/select/select.d.ts +5 -2
  66. package/dist/select/select.d.ts.map +1 -1
  67. package/dist/select/select.js +11 -2
  68. package/dist/select/select.js.map +1 -1
  69. package/dist/select/select.module.js.map +1 -1
  70. package/dist/separator/separator.css +1 -5
  71. package/dist/separator/separator.module.js.map +1 -1
  72. package/dist/slider/index.d.ts +3 -0
  73. package/dist/slider/index.js +4 -0
  74. package/dist/slider/parts.d.ts +38 -0
  75. package/dist/slider/parts.d.ts.map +1 -0
  76. package/dist/slider/parts.js +69 -0
  77. package/dist/slider/parts.js.map +1 -0
  78. package/dist/slider/slider.css +97 -0
  79. package/dist/slider/slider.d.ts +38 -0
  80. package/dist/slider/slider.d.ts.map +1 -0
  81. package/dist/slider/slider.js +41 -0
  82. package/dist/slider/slider.js.map +1 -0
  83. package/dist/slider/slider.module.css.d.ts +2 -0
  84. package/dist/slider/slider.module.js +15 -0
  85. package/dist/slider/slider.module.js.map +1 -0
  86. package/dist/styles/reset.css +6 -6
  87. package/dist/styles/tokens.css +73 -71
  88. package/dist/switch/switch.css +2 -6
  89. package/dist/switch/switch.module.js.map +1 -1
  90. package/dist/tabs/tabs.css +5 -9
  91. package/dist/tabs/tabs.module.js.map +1 -1
  92. package/dist/tailwind-theme.css +23 -23
  93. package/dist/toast/toast.css +11 -15
  94. package/dist/toast/toast.module.js.map +1 -1
  95. package/dist/tokens.css +79 -75
  96. package/dist/tooltip/tooltip.css +7 -11
  97. package/dist/tooltip/tooltip.module.js.map +1 -1
  98. package/package.json +17 -1
  99. package/src/accordion/accordion.module.css +6 -20
  100. package/src/alert-dialog/alert-dialog.module.css +91 -0
  101. package/src/alert-dialog/alert-dialog.tsx +69 -0
  102. package/src/alert-dialog/index.ts +7 -0
  103. package/src/alert-dialog/parts.tsx +73 -0
  104. package/src/badge/badge.module.css +3 -13
  105. package/src/button/button.module.css +15 -51
  106. package/src/card/card.module.css +5 -16
  107. package/src/checkbox/checkbox.module.css +3 -14
  108. package/src/collapsible/collapsible.module.css +7 -20
  109. package/src/context-menu/context-menu.module.css +168 -0
  110. package/src/context-menu/context-menu.tsx +75 -0
  111. package/src/context-menu/index.ts +21 -0
  112. package/src/context-menu/parts.tsx +99 -0
  113. package/src/dialog/dialog.module.css +26 -33
  114. package/src/dialog/dialog.tsx +14 -1
  115. package/src/drawer/drawer.module.css +9 -58
  116. package/src/index.ts +48 -0
  117. package/src/input/input.module.css +5 -21
  118. package/src/menu/menu.module.css +13 -43
  119. package/src/number-field/number-field.module.css +12 -28
  120. package/src/progress/progress.module.css +1 -10
  121. package/src/select/select.module.css +14 -35
  122. package/src/select/select.tsx +14 -5
  123. package/src/separator/separator.module.css +1 -5
  124. package/src/slider/index.ts +14 -0
  125. package/src/slider/parts.tsx +90 -0
  126. package/src/slider/slider.module.css +110 -0
  127. package/src/slider/slider.tsx +68 -0
  128. package/src/styles/layer-order.css +22 -0
  129. package/src/styles/reset.css +6 -6
  130. package/src/styles/tailwind-theme.css +23 -23
  131. package/src/styles/tokens.css +79 -75
  132. package/src/switch/switch.module.css +2 -12
  133. package/src/tabs/tabs.module.css +5 -18
  134. package/src/toast/toast.module.css +11 -51
  135. package/src/tooltip/tooltip.module.css +7 -18
@@ -0,0 +1,168 @@
1
+ @layer components {
2
+ .positioner {
3
+ outline: none;
4
+ z-index: var(--z-dropdown);
5
+ }
6
+
7
+ .popup {
8
+ box-sizing: border-box;
9
+ padding: var(--space-1) 0;
10
+ border-radius: var(--radius-lg);
11
+ background-color: var(--color-overlay);
12
+ border: var(--border-width-base) solid var(--color-line);
13
+ box-shadow: var(--shadow-popover);
14
+ color: var(--color-primary);
15
+ font-family: var(--font-sans);
16
+ font-size: var(--font-size-md);
17
+ min-width: 220px;
18
+ transform-origin: var(--transform-origin);
19
+ outline: none;
20
+ transition:
21
+ opacity 150ms var(--easing-ease-out),
22
+ transform 150ms var(--easing-ease-out);
23
+ }
24
+
25
+ @supports (backdrop-filter: blur(20px)) {
26
+ .popup {
27
+ backdrop-filter: blur(20px) saturate(1.8);
28
+ -webkit-backdrop-filter: blur(20px) saturate(1.8);
29
+ }
30
+ }
31
+
32
+ .popup[data-starting-style] {
33
+ opacity: 0;
34
+ transform: scale(0.97);
35
+ }
36
+
37
+ .popup[data-ending-style] {
38
+ opacity: 0;
39
+ transform: scale(0.99);
40
+ transition:
41
+ opacity 75ms var(--easing-ease-in),
42
+ transform 75ms var(--easing-ease-in);
43
+ }
44
+
45
+ /* ─── Trigger area ───────────────────────────────────────────── */
46
+
47
+ .trigger {
48
+ display: block;
49
+ outline: none;
50
+ user-select: none;
51
+ -webkit-user-select: none;
52
+ cursor: default;
53
+ }
54
+
55
+ /* ─── Item ───────────────────────────────────────────────────── */
56
+
57
+ .item {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: var(--space-2);
61
+ /* Full-width — no inset margin */
62
+ padding: var(--space-1) var(--space-4);
63
+ font-family: var(--font-sans);
64
+ font-size: var(--font-size-md);
65
+ color: var(--color-primary);
66
+ cursor: default;
67
+ outline: none;
68
+ user-select: none;
69
+ position: relative;
70
+ transition: none;
71
+ }
72
+
73
+ .item[data-highlighted] {
74
+ background-color: var(--color-accent);
75
+ color: var(--color-on-accent);
76
+ }
77
+
78
+ .item[data-disabled] {
79
+ opacity: 0.36;
80
+ cursor: not-allowed;
81
+ }
82
+
83
+ /* ─── Item internals ─────────────────────────────────────────── */
84
+
85
+ .item-icon {
86
+ width: 16px;
87
+ height: 16px;
88
+ flex-shrink: 0;
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: center;
92
+ color: inherit;
93
+ }
94
+
95
+ .item-label {
96
+ flex: 1;
97
+ }
98
+
99
+ .item-shortcut {
100
+ margin-left: var(--space-8);
101
+ font-size: var(--font-size-sm);
102
+ color: var(--color-tertiary);
103
+ flex-shrink: 0;
104
+ }
105
+
106
+ .item[data-highlighted] .item-shortcut {
107
+ color: color-mix(in srgb, var(--color-on-accent) 60%, transparent);
108
+ }
109
+
110
+ .submenu-icon {
111
+ margin-left: auto;
112
+ color: var(--color-tertiary);
113
+ flex-shrink: 0;
114
+ }
115
+
116
+ .item[data-highlighted] .submenu-icon,
117
+ .submenu-trigger[data-highlighted] .submenu-icon {
118
+ color: color-mix(in srgb, var(--color-on-accent) 70%, transparent);
119
+ }
120
+
121
+ /* ─── Submenu trigger ────────────────────────────────────────── */
122
+
123
+ .submenu-trigger {
124
+ display: flex;
125
+ align-items: center;
126
+ gap: var(--space-2);
127
+ padding: var(--space-1) var(--space-4);
128
+ font-family: var(--font-sans);
129
+ font-size: var(--font-size-md);
130
+ color: var(--color-primary);
131
+ cursor: default;
132
+ outline: none;
133
+ user-select: none;
134
+ transition: none;
135
+ }
136
+
137
+ .submenu-trigger[data-highlighted],
138
+ .submenu-trigger[data-popup-open] {
139
+ background-color: var(--color-accent);
140
+ color: var(--color-on-accent);
141
+ }
142
+
143
+ .submenu-trigger[data-disabled] {
144
+ opacity: 0.36;
145
+ cursor: not-allowed;
146
+ }
147
+
148
+ /* ─── Group label ────────────────────────────────────────────── */
149
+
150
+ .group-label {
151
+ padding: var(--space-1) var(--space-4) var(--space-0-5);
152
+ font-family: var(--font-sans);
153
+ font-size: var(--font-size-xs);
154
+ font-weight: var(--font-weight-semibold);
155
+ color: var(--color-tertiary);
156
+ text-transform: uppercase;
157
+ letter-spacing: var(--letter-spacing-wide);
158
+ cursor: default;
159
+ user-select: none;
160
+ }
161
+
162
+ /* ─── Separator ──────────────────────────────────────────────── */
163
+ .separator {
164
+ margin: var(--space-1) var(--space-4);
165
+ height: var(--border-width-base);
166
+ background-color: var(--color-line-subtle);
167
+ }
168
+ }
@@ -0,0 +1,75 @@
1
+ import type { ReactNode, ReactElement } from "react";
2
+ import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
3
+ import styles from "./context-menu.module.css";
4
+
5
+ export interface ContextMenuItemDef {
6
+ type?: "item";
7
+ label: ReactNode;
8
+ icon?: ReactNode;
9
+ shortcut?: string;
10
+ onSelect?: () => void;
11
+ disabled?: boolean;
12
+ }
13
+
14
+ export interface ContextMenuSeparatorDef {
15
+ type: "separator";
16
+ }
17
+
18
+ export interface ContextMenuGroupDef {
19
+ type: "group";
20
+ label?: ReactNode;
21
+ items: ContextMenuItemDef[];
22
+ }
23
+
24
+ export type ContextMenuEntry = ContextMenuItemDef | ContextMenuSeparatorDef | ContextMenuGroupDef;
25
+
26
+ export interface ContextMenuProps {
27
+ /** The element that can be right-clicked / long-pressed to open the menu. */
28
+ children: ReactElement;
29
+ items: ContextMenuEntry[];
30
+ className?: string;
31
+ }
32
+
33
+ function RenderItem({ item, i }: { item: ContextMenuItemDef; i: number }) {
34
+ return (
35
+ <BaseContextMenu.Item key={i} className={styles.item} disabled={item.disabled} onClick={item.onSelect}>
36
+ {item.icon && <span className={styles["item-icon"]}>{item.icon}</span>}
37
+ <span className={styles["item-label"]}>{item.label}</span>
38
+ {item.shortcut && <span className={styles["item-shortcut"]}>{item.shortcut}</span>}
39
+ </BaseContextMenu.Item>
40
+ );
41
+ }
42
+
43
+ export function ContextMenu({ children, items, className }: ContextMenuProps) {
44
+ return (
45
+ <BaseContextMenu.Root>
46
+ <BaseContextMenu.Trigger className={`${styles.trigger} ${className ?? ""}`} render={children} />
47
+ <BaseContextMenu.Portal>
48
+ <BaseContextMenu.Positioner className={styles.positioner}>
49
+ <BaseContextMenu.Popup className={styles.popup}>
50
+ {items.map((entry, i) => {
51
+ if (entry.type === "separator") {
52
+ return <BaseContextMenu.Separator key={i} className={styles.separator} />;
53
+ }
54
+ if (entry.type === "group") {
55
+ return (
56
+ <BaseContextMenu.Group key={i}>
57
+ {entry.label && (
58
+ <BaseContextMenu.GroupLabel className={styles["group-label"]}>{entry.label}</BaseContextMenu.GroupLabel>
59
+ )}
60
+ {entry.items.map((item, j) => (
61
+ <RenderItem key={j} item={item} i={j} />
62
+ ))}
63
+ </BaseContextMenu.Group>
64
+ );
65
+ }
66
+ return <RenderItem key={i} item={entry} i={i} />;
67
+ })}
68
+ </BaseContextMenu.Popup>
69
+ </BaseContextMenu.Positioner>
70
+ </BaseContextMenu.Portal>
71
+ </BaseContextMenu.Root>
72
+ );
73
+ }
74
+
75
+ export { styles as ContextMenuStyles };
@@ -0,0 +1,21 @@
1
+ export { ContextMenu } from "./context-menu";
2
+ export type { ContextMenuProps, ContextMenuEntry, ContextMenuItemDef, ContextMenuSeparatorDef, ContextMenuGroupDef } from "./context-menu";
3
+
4
+ export {
5
+ ContextMenuPopup,
6
+ ContextMenuItem,
7
+ ContextMenuSeparator,
8
+ ContextMenuGroup,
9
+ ContextMenuGroupLabel,
10
+ ContextMenuSubmenuTrigger,
11
+ } from "./parts";
12
+ export type {
13
+ ContextMenuPopupProps,
14
+ ContextMenuItemProps,
15
+ ContextMenuSeparatorProps,
16
+ ContextMenuGroupProps,
17
+ ContextMenuGroupLabelProps,
18
+ ContextMenuSubmenuTriggerProps,
19
+ } from "./parts";
20
+
21
+ export { ContextMenuStyles } from "./context-menu";
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Styled primitives for ContextMenu.
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { ContextMenu as BaseContextMenu } from '@base-ui/react/context-menu';
7
+ * import { ContextMenuPopup, ContextMenuItem, ContextMenuSeparator } from '@brijbyte/agentic-ui/context-menu';
8
+ *
9
+ * <BaseContextMenu.Root>
10
+ * <BaseContextMenu.Trigger render={<div>Right click me</div>} />
11
+ * <BaseContextMenu.Portal>
12
+ * <BaseContextMenu.Positioner>
13
+ * <ContextMenuPopup>
14
+ * <ContextMenuItem>Cut</ContextMenuItem>
15
+ * <ContextMenuItem>Copy</ContextMenuItem>
16
+ * <ContextMenuSeparator />
17
+ * <ContextMenuItem>Paste</ContextMenuItem>
18
+ * </ContextMenuPopup>
19
+ * </BaseContextMenu.Positioner>
20
+ * </BaseContextMenu.Portal>
21
+ * </BaseContextMenu.Root>
22
+ * ```
23
+ */
24
+ import { forwardRef } from "react";
25
+ import type { ComponentRef, ComponentPropsWithoutRef } from "react";
26
+ import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
27
+ import styles from "./context-menu.module.css";
28
+
29
+ type BasePopupProps = ComponentPropsWithoutRef<typeof BaseContextMenu.Popup>;
30
+ type BaseItemProps = ComponentPropsWithoutRef<typeof BaseContextMenu.Item>;
31
+ type BaseSeparatorProps = ComponentPropsWithoutRef<typeof BaseContextMenu.Separator>;
32
+ type BaseGroupProps = ComponentPropsWithoutRef<typeof BaseContextMenu.Group>;
33
+ type BaseGroupLabelProps = ComponentPropsWithoutRef<typeof BaseContextMenu.GroupLabel>;
34
+ type BaseSubmenuTriggerProps = ComponentPropsWithoutRef<typeof BaseContextMenu.SubmenuTrigger>;
35
+
36
+ export interface ContextMenuPopupProps extends Omit<BasePopupProps, "className"> {
37
+ className?: string;
38
+ }
39
+ export interface ContextMenuItemProps extends Omit<BaseItemProps, "className"> {
40
+ className?: string;
41
+ }
42
+ export interface ContextMenuSeparatorProps extends Omit<BaseSeparatorProps, "className"> {
43
+ className?: string;
44
+ }
45
+ export interface ContextMenuGroupProps extends Omit<BaseGroupProps, "className"> {
46
+ className?: string;
47
+ }
48
+ export interface ContextMenuGroupLabelProps extends Omit<BaseGroupLabelProps, "className"> {
49
+ className?: string;
50
+ }
51
+ export interface ContextMenuSubmenuTriggerProps extends Omit<BaseSubmenuTriggerProps, "className"> {
52
+ className?: string;
53
+ }
54
+
55
+ export const ContextMenuPopup = forwardRef<ComponentRef<typeof BaseContextMenu.Popup>, ContextMenuPopupProps>(function ContextMenuPopup(
56
+ { className, ...props },
57
+ ref,
58
+ ) {
59
+ return <BaseContextMenu.Popup ref={ref} className={`${styles.popup} ${className ?? ""}`} {...props} />;
60
+ });
61
+
62
+ export const ContextMenuItem = forwardRef<ComponentRef<typeof BaseContextMenu.Item>, ContextMenuItemProps>(function ContextMenuItem(
63
+ { className, ...props },
64
+ ref,
65
+ ) {
66
+ return <BaseContextMenu.Item ref={ref} className={`${styles.item} ${className ?? ""}`} {...props} />;
67
+ });
68
+
69
+ export const ContextMenuSeparator = forwardRef<ComponentRef<typeof BaseContextMenu.Separator>, ContextMenuSeparatorProps>(
70
+ function ContextMenuSeparator({ className, ...props }, ref) {
71
+ return <BaseContextMenu.Separator ref={ref} className={`${styles.separator} ${className ?? ""}`} {...props} />;
72
+ },
73
+ );
74
+
75
+ export const ContextMenuGroup = forwardRef<ComponentRef<typeof BaseContextMenu.Group>, ContextMenuGroupProps>(function ContextMenuGroup(
76
+ { className, ...props },
77
+ ref,
78
+ ) {
79
+ return <BaseContextMenu.Group ref={ref} className={className} {...props} />;
80
+ });
81
+
82
+ export const ContextMenuGroupLabel = forwardRef<ComponentRef<typeof BaseContextMenu.GroupLabel>, ContextMenuGroupLabelProps>(
83
+ function ContextMenuGroupLabel({ className, ...props }, ref) {
84
+ return <BaseContextMenu.GroupLabel ref={ref} className={`${styles["group-label"]} ${className ?? ""}`} {...props} />;
85
+ },
86
+ );
87
+
88
+ export const ContextMenuSubmenuTrigger = forwardRef<ComponentRef<typeof BaseContextMenu.SubmenuTrigger>, ContextMenuSubmenuTriggerProps>(
89
+ function ContextMenuSubmenuTrigger({ className, children, ...props }, ref) {
90
+ return (
91
+ <BaseContextMenu.SubmenuTrigger ref={ref} className={`${styles["submenu-trigger"]} ${className ?? ""}`} {...props}>
92
+ <span style={{ flex: 1 }}>{children}</span>
93
+ <svg width="10" height="10" viewBox="0 0 10 10" fill="none" className={styles["submenu-icon"]}>
94
+ <path d="M3.5 9L7.5 5L3.5 1" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
95
+ </svg>
96
+ </BaseContextMenu.SubmenuTrigger>
97
+ );
98
+ },
99
+ );
@@ -1,5 +1,3 @@
1
- @layer theme, base, components, utilities;
2
-
3
1
  @layer components {
4
2
  .backdrop {
5
3
  position: fixed;
@@ -8,41 +6,36 @@
8
6
  z-index: var(--z-overlay);
9
7
  transition: opacity var(--duration-slow) var(--easing-standard);
10
8
  }
11
-
12
9
  .backdrop[data-starting-style],
13
10
  .backdrop[data-ending-style] {
14
11
  opacity: 0;
15
12
  }
16
-
17
13
  .popup {
18
14
  position: fixed;
19
15
  top: 50%;
20
16
  left: 50%;
21
17
  transform: translate(-50%, -50%);
22
18
  z-index: var(--z-modal);
23
- background-color: var(--color-bg-elevated);
24
- border: var(--border-width-base) solid var(--color-border-base);
19
+ background-color: var(--color-elevated);
20
+ border: var(--border-width-base) solid var(--color-line);
25
21
  border-radius: var(--radius-2xl);
26
22
  box-shadow: var(--shadow-xl);
27
- padding: var(--space-6);
28
- width: min(480px, calc(100vw - var(--space-8)));
23
+ padding: var(--space-5) var(--space-6) var(--space-5);
24
+ width: min(440px, calc(100vw - var(--space-8)));
29
25
  max-height: min(640px, calc(100vh - var(--space-8)));
30
26
  display: flex;
31
27
  flex-direction: column;
32
- gap: var(--space-4);
28
+ gap: var(--space-3);
33
29
  outline: none;
34
30
  overflow: hidden;
35
-
36
31
  transition:
37
32
  opacity 200ms var(--easing-ease-out),
38
33
  transform 200ms var(--easing-spring);
39
34
  }
40
-
41
35
  .popup[data-starting-style] {
42
36
  opacity: 0;
43
37
  transform: translate(-50%, -48%) scale(0.96);
44
38
  }
45
-
46
39
  .popup[data-ending-style] {
47
40
  opacity: 0;
48
41
  transform: translate(-50%, -50%) scale(0.98);
@@ -50,30 +43,26 @@
50
43
  opacity 150ms var(--easing-ease-in),
51
44
  transform 150ms var(--easing-ease-in);
52
45
  }
53
-
54
46
  .header {
55
47
  display: flex;
56
48
  flex-direction: column;
57
- gap: var(--space-1);
49
+ gap: var(--space-2);
50
+ text-align: center;
58
51
  }
59
-
60
52
  .title {
61
- font-family: var(--font-mono);
53
+ font-family: var(--font-sans);
62
54
  font-size: var(--font-size-lg);
63
- font-weight: var(--font-weight-semibold);
64
- color: var(--color-text-primary);
55
+ font-weight: var(--font-weight-bold);
56
+ color: var(--color-primary);
65
57
  line-height: var(--line-height-tight);
66
58
  letter-spacing: var(--letter-spacing-tight);
67
- padding-right: var(--space-6);
68
59
  }
69
-
70
60
  .description {
71
- font-family: var(--font-mono);
72
- font-size: var(--font-size-sm);
73
- color: var(--color-text-secondary);
61
+ font-family: var(--font-sans);
62
+ font-size: var(--font-size-md);
63
+ color: var(--color-secondary);
74
64
  line-height: var(--line-height-relaxed);
75
65
  }
76
-
77
66
  .close {
78
67
  position: absolute;
79
68
  top: var(--space-4);
@@ -83,7 +72,7 @@
83
72
  border-radius: var(--radius-sm);
84
73
  border: none;
85
74
  background: transparent;
86
- color: var(--color-text-tertiary);
75
+ color: var(--color-tertiary);
87
76
  cursor: pointer;
88
77
  display: flex;
89
78
  align-items: center;
@@ -93,31 +82,35 @@
93
82
  background-color var(--duration-fast) var(--easing-standard),
94
83
  color var(--duration-fast) var(--easing-standard);
95
84
  }
96
-
97
85
  .close:hover {
98
- background-color: var(--color-surface-hover);
99
- color: var(--color-text-primary);
86
+ background-color: var(--color-hover);
87
+ color: var(--color-primary);
100
88
  }
101
-
102
89
  .close:focus-visible {
103
90
  box-shadow: var(--shadow-focus);
104
91
  }
105
-
106
92
  .body {
107
93
  flex: 1;
108
94
  overflow-y: auto;
109
95
  font-family: var(--font-mono);
110
96
  font-size: var(--font-size-sm);
111
- color: var(--color-text-secondary);
97
+ color: var(--color-secondary);
112
98
  line-height: var(--line-height-relaxed);
113
99
  }
114
-
115
100
  .footer {
116
101
  display: flex;
117
102
  align-items: center;
118
103
  justify-content: flex-end;
119
104
  gap: var(--space-2);
120
105
  padding-top: var(--space-2);
121
- border-top: var(--border-width-base) solid var(--color-border-subtle);
106
+ }
107
+ /* When a footerStart slot is present, space-between pushes it left */
108
+ .footer-split {
109
+ justify-content: space-between;
110
+ }
111
+ .footer-end {
112
+ display: flex;
113
+ align-items: center;
114
+ gap: var(--space-2);
122
115
  }
123
116
  }
@@ -11,7 +11,14 @@ export interface DialogProps {
11
11
  title?: ReactNode;
12
12
  description?: ReactNode;
13
13
  children?: ReactNode;
14
+ /** Buttons aligned to the right (cancel, confirm). */
14
15
  footer?: ReactNode;
16
+ /**
17
+ * Content anchored to the left of the footer — intended for a destructive
18
+ * action (e.g. Delete). When present the footer switches to space-between
19
+ * layout, matching the macOS dialog pattern.
20
+ */
21
+ footerStart?: ReactNode;
15
22
  className?: string;
16
23
  dismissible?: boolean;
17
24
  }
@@ -30,6 +37,7 @@ export function Dialog({
30
37
  description,
31
38
  children,
32
39
  footer,
40
+ footerStart,
33
41
  className,
34
42
  dismissible = true,
35
43
  onOpenChange,
@@ -50,7 +58,12 @@ export function Dialog({
50
58
  </BaseDialog.Close>
51
59
  )}
52
60
  {children && <div className={styles.body}>{children}</div>}
53
- {footer && <div className={styles.footer}>{footer}</div>}
61
+ {(footer || footerStart) && (
62
+ <div className={`${styles.footer} ${footerStart ? styles["footer-split"] : ""}`}>
63
+ {footerStart && <div>{footerStart}</div>}
64
+ {footer && <div className={styles["footer-end"]}>{footer}</div>}
65
+ </div>
66
+ )}
54
67
  </BaseDialog.Popup>
55
68
  </BaseDialog.Viewport>
56
69
  </BaseDialog.Portal>