raft-ui 0.0.6 → 0.0.8

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 (138) hide show
  1. package/CHANGELOG.md +7 -5
  2. package/dist/index.d.mts +618 -2
  3. package/dist/index.mjs +1205 -12
  4. package/{src → dist}/styles.css +0 -2
  5. package/{src/lib/styled-props.ts → dist/tv-UUMwNowu.d.mts} +6 -1
  6. package/dist/use-theme-Y_h1DKll.mjs +34 -0
  7. package/dist/wip.d.mts +15 -133
  8. package/dist/wip.mjs +23 -296
  9. package/package.json +4 -4
  10. package/dist/button-CJqMhTPQ.mjs +0 -621
  11. package/dist/index-CpGciYPW.d.mts +0 -267
  12. package/src/components/alert-dialog/alert-dialog.tsx +0 -215
  13. package/src/components/alert-dialog/index.ts +0 -30
  14. package/src/components/avatar/avatar.tsx +0 -375
  15. package/src/components/avatar/index.ts +0 -17
  16. package/src/components/badge/badge.tsx +0 -393
  17. package/src/components/badge/index.ts +0 -2
  18. package/src/components/banner/banner.tsx +0 -269
  19. package/src/components/banner/index.ts +0 -8
  20. package/src/components/bottom-sheet/bottom-sheet.tsx +0 -152
  21. package/src/components/bottom-sheet/index.ts +0 -22
  22. package/src/components/button/button.tsx +0 -499
  23. package/src/components/button/index.ts +0 -2
  24. package/src/components/checkbox/checkbox-indicator.tsx +0 -128
  25. package/src/components/checkbox/checkbox.tsx +0 -350
  26. package/src/components/checkbox/index.ts +0 -2
  27. package/src/components/combobox/combobox.tsx +0 -603
  28. package/src/components/combobox/index.ts +0 -52
  29. package/src/components/context-menu/context-menu.tsx +0 -380
  30. package/src/components/context-menu/index.ts +0 -34
  31. package/src/components/conversation-preview-card/conversation-preview-card.tsx +0 -336
  32. package/src/components/conversation-preview-card/index.ts +0 -32
  33. package/src/components/description-list/description-list.tsx +0 -116
  34. package/src/components/description-list/index.ts +0 -14
  35. package/src/components/dialog/dialog.tsx +0 -152
  36. package/src/components/dialog/index.ts +0 -26
  37. package/src/components/dropdown-menu/dropdown-menu.tsx +0 -405
  38. package/src/components/dropdown-menu/index.ts +0 -38
  39. package/src/components/empty-state/empty-state.tsx +0 -177
  40. package/src/components/empty-state/index.ts +0 -16
  41. package/src/components/field/field.tsx +0 -125
  42. package/src/components/field/index.ts +0 -18
  43. package/src/components/inline-code/index.ts +0 -2
  44. package/src/components/inline-code/inline-code.tsx +0 -35
  45. package/src/components/input/index.ts +0 -2
  46. package/src/components/input/input.tsx +0 -76
  47. package/src/components/input-group/index.ts +0 -7
  48. package/src/components/input-group/input-group.tsx +0 -215
  49. package/src/components/kbd/index.ts +0 -2
  50. package/src/components/kbd/kbd.tsx +0 -43
  51. package/src/components/label/index.ts +0 -2
  52. package/src/components/label/label.tsx +0 -99
  53. package/src/components/lightbox/index.ts +0 -24
  54. package/src/components/lightbox/lightbox.tsx +0 -245
  55. package/src/components/list-item/index.ts +0 -20
  56. package/src/components/list-item/list-item.tsx +0 -263
  57. package/src/components/media-list-item/index.ts +0 -20
  58. package/src/components/media-list-item/media-list-item.tsx +0 -169
  59. package/src/components/notification-center/index.ts +0 -39
  60. package/src/components/notification-center/notification-center.tsx +0 -558
  61. package/src/components/panel-header/index.ts +0 -22
  62. package/src/components/panel-header/panel-header.tsx +0 -199
  63. package/src/components/popover/index.ts +0 -30
  64. package/src/components/popover/popover.tsx +0 -248
  65. package/src/components/preview-shell/index.ts +0 -2
  66. package/src/components/preview-shell/preview-shell.tsx +0 -51
  67. package/src/components/quoted-message-card/index.ts +0 -36
  68. package/src/components/quoted-message-card/quoted-message-card.tsx +0 -391
  69. package/src/components/radio-group/index.ts +0 -2
  70. package/src/components/radio-group/radio-group.tsx +0 -119
  71. package/src/components/section-header/index.ts +0 -16
  72. package/src/components/section-header/section-header.tsx +0 -117
  73. package/src/components/section-label/index.ts +0 -2
  74. package/src/components/section-label/section-label.tsx +0 -38
  75. package/src/components/segmented-control/index.ts +0 -12
  76. package/src/components/segmented-control/segmented-control.tsx +0 -129
  77. package/src/components/select/index.ts +0 -40
  78. package/src/components/select/select.tsx +0 -382
  79. package/src/components/separator/index.ts +0 -2
  80. package/src/components/separator/separator.tsx +0 -40
  81. package/src/components/spinner/index.ts +0 -2
  82. package/src/components/spinner/spinner.tsx +0 -228
  83. package/src/components/status/index.ts +0 -2
  84. package/src/components/status/status.tsx +0 -152
  85. package/src/components/tabs/index.ts +0 -24
  86. package/src/components/tabs/tabs.tsx +0 -451
  87. package/src/components/text/index.ts +0 -2
  88. package/src/components/text/text.tsx +0 -131
  89. package/src/components/textarea/index.ts +0 -2
  90. package/src/components/textarea/textarea.tsx +0 -136
  91. package/src/components/toggle-group/index.ts +0 -7
  92. package/src/components/toggle-group/toggle-group.tsx +0 -111
  93. package/src/components/tooltip/index.ts +0 -8
  94. package/src/components/tooltip/tooltip.tsx +0 -212
  95. package/src/index.ts +0 -429
  96. package/src/legacy/AttentionDot.tsx +0 -28
  97. package/src/legacy/AvatarListRow.tsx +0 -87
  98. package/src/legacy/AvatarSlot.tsx +0 -157
  99. package/src/legacy/Badge.tsx +0 -95
  100. package/src/legacy/Banner.tsx +0 -74
  101. package/src/legacy/BottomSheet.tsx +0 -76
  102. package/src/legacy/CheckMarker.tsx +0 -72
  103. package/src/legacy/Checkbox.tsx +0 -81
  104. package/src/legacy/ConversationPreviewCard.tsx +0 -169
  105. package/src/legacy/DismissBackdrop.tsx +0 -68
  106. package/src/legacy/EmptyState.tsx +0 -63
  107. package/src/legacy/ExperimentalBadge.tsx +0 -19
  108. package/src/legacy/FormField.tsx +0 -106
  109. package/src/legacy/KeyValueRow.tsx +0 -67
  110. package/src/legacy/Lightbox.tsx +0 -119
  111. package/src/legacy/NotificationCenter.tsx +0 -217
  112. package/src/legacy/PanelHeader.tsx +0 -94
  113. package/src/legacy/PreviewShell.tsx +0 -40
  114. package/src/legacy/QuotedMessageCard.tsx +0 -181
  115. package/src/legacy/ReorderablePanelTabs.tsx +0 -156
  116. package/src/legacy/SandboxedPreviewFrame.tsx +0 -59
  117. package/src/legacy/SearchInput.tsx +0 -23
  118. package/src/legacy/SectionEyebrow.tsx +0 -60
  119. package/src/legacy/SectionHeader.tsx +0 -68
  120. package/src/legacy/SegmentedControl.tsx +0 -74
  121. package/src/legacy/SlugInput.tsx +0 -29
  122. package/src/legacy/Spinner.tsx +0 -89
  123. package/src/legacy/StatusDot.tsx +0 -51
  124. package/src/legacy/SurfaceListItem.tsx +0 -32
  125. package/src/legacy/Textarea.tsx +0 -137
  126. package/src/legacy/button.tsx +0 -100
  127. package/src/legacy/context-menu-divider.tsx +0 -12
  128. package/src/legacy/menu-item.tsx +0 -66
  129. package/src/legacy/selection-popover.tsx +0 -212
  130. package/src/legacy/server-switcher-menu.tsx +0 -203
  131. package/src/legacy/source.css +0 -240
  132. package/src/lib/cn.ts +0 -1
  133. package/src/lib/theme/theme-context.ts +0 -28
  134. package/src/lib/theme/theme-provider.tsx +0 -181
  135. package/src/lib/theme/use-theme.ts +0 -12
  136. package/src/lib/tv.ts +0 -29
  137. package/src/lib/without-children.ts +0 -6
  138. package/src/wip.ts +0 -291
@@ -1,152 +0,0 @@
1
- import { Dialog } from "@base-ui/react/dialog";
2
- import { mergeProps } from "@base-ui/react/merge-props";
3
- import { useRender } from "@base-ui/react/use-render";
4
- import { tv } from "../../lib/tv";
5
- import type { StyledProps } from "../../lib/styled-props";
6
- import { useThemeFamily } from "../../lib/theme/use-theme";
7
-
8
- // Mobile bottom sheet, composed from base-ui Dialog parts and slot parts
9
- // (`BottomSheetTrigger`, `BottomSheetContent`, `BottomSheetHeader`,
10
- // `BottomSheetFooter`, `BottomSheetTitle`, `BottomSheetDescription`,
11
- // `BottomSheetClose`). Dialog owns open state, the modal scroll-lock, ESC, and
12
- // native outside-press dismissal, so unlike Lightbox there's no dim layer and
13
- // no manual backdrop onClick: the sheet card carries the brutal frame itself.
14
- //
15
- // All styled parts share one `tv()` slots config so theme styling lives in a
16
- // single place, ready for the elegant family to add per-slot overrides under
17
- // `theme`. Each part resolves its own slot with the active theme, so they stay
18
- // independently composable. `shadow-brutal-lg` maps to the --shadow-lg token.
19
- const bottomSheet = tv({
20
- slots: {
21
- content: [
22
- "fixed inset-x-3 bottom-[max(12px,env(safe-area-inset-bottom))] z-50 mx-auto max-w-md",
23
- ],
24
- header: ["flex flex-col gap-1 p-4"],
25
- footer: ["mt-auto flex flex-col gap-2 p-4"],
26
- title: ["text-base font-bold text-foreground-strong"],
27
- description: ["text-sm text-foreground/60"],
28
- },
29
- variants: {
30
- theme: {
31
- brutal: { content: ["border-2 border-line-strong bg-layer-panel shadow-xl"] },
32
- // Elegant styling is deferred; see the component TODO.
33
- elegant: {},
34
- },
35
- },
36
- });
37
-
38
- export type BottomSheetProps = Dialog.Root.Props;
39
-
40
- // Composition root: a thin pass-through over Dialog.Root that owns open state.
41
- // Renders no DOM element of its own.
42
- export function BottomSheet(props: BottomSheetProps) {
43
- return <Dialog.Root {...props} />;
44
- }
45
-
46
- export type BottomSheetTriggerProps = Dialog.Trigger.Props;
47
-
48
- // Opens the sheet. Compose your own affordance via `render` (e.g. a Button).
49
- export function BottomSheetTrigger(props: BottomSheetTriggerProps) {
50
- return <Dialog.Trigger data-slot="bottom-sheet-trigger" {...props} />;
51
- }
52
-
53
- export type BottomSheetPortalProps = Dialog.Portal.Props;
54
-
55
- // Portals the sheet to the document body. BottomSheetContent wraps this for you.
56
- export function BottomSheetPortal(props: BottomSheetPortalProps) {
57
- return <Dialog.Portal data-slot="bottom-sheet-portal" {...props} />;
58
- }
59
-
60
- export type BottomSheetContentProps = StyledProps<Dialog.Popup.Props>;
61
-
62
- // The sheet card: portaled, anchored to the bottom safe area, centered up to
63
- // `max-w-md`, carrying the brutal frame. `inset-x-3` + the safe-area bottom inset
64
- // reproduce the original 12px gutter. Close affordances are composed in by the
65
- // caller via `BottomSheetClose`.
66
- export function BottomSheetContent({ className, ...props }: BottomSheetContentProps) {
67
- const theme = useThemeFamily();
68
- const { content } = bottomSheet({ theme });
69
- return (
70
- <BottomSheetPortal>
71
- <Dialog.Popup
72
- data-slot="bottom-sheet-content"
73
- data-side="bottom"
74
- className={content({ className })}
75
- {...props}
76
- />
77
- </BottomSheetPortal>
78
- );
79
- }
80
-
81
- export type BottomSheetCloseProps = Dialog.Close.Props;
82
-
83
- // Closes the sheet. Compose your own affordance via `render` (e.g. a Button).
84
- export function BottomSheetClose(props: BottomSheetCloseProps) {
85
- return <Dialog.Close data-slot="bottom-sheet-close" {...props} />;
86
- }
87
-
88
- export type BottomSheetHeaderProps = useRender.ComponentProps<"div">;
89
-
90
- // Stacks the title + description at the top of the sheet.
91
- export function BottomSheetHeader({ className, render, ...props }: BottomSheetHeaderProps) {
92
- const theme = useThemeFamily();
93
- const { header } = bottomSheet({ theme });
94
- const defaultProps: useRender.ElementProps<"div"> = {
95
- className: header({ className }),
96
- };
97
-
98
- return useRender({
99
- defaultTagName: "div",
100
- render,
101
- props: mergeProps<"div">(defaultProps, props),
102
- state: {
103
- slot: "bottom-sheet-header",
104
- },
105
- });
106
- }
107
-
108
- export type BottomSheetFooterProps = useRender.ComponentProps<"div">;
109
-
110
- // Trailing action area, pushed to the bottom of the sheet.
111
- export function BottomSheetFooter({ className, render, ...props }: BottomSheetFooterProps) {
112
- const theme = useThemeFamily();
113
- const { footer } = bottomSheet({ theme });
114
- const defaultProps: useRender.ElementProps<"div"> = {
115
- className: footer({ className }),
116
- };
117
-
118
- return useRender({
119
- defaultTagName: "div",
120
- render,
121
- props: mergeProps<"div">(defaultProps, props),
122
- state: {
123
- slot: "bottom-sheet-footer",
124
- },
125
- });
126
- }
127
-
128
- export type BottomSheetTitleProps = StyledProps<Dialog.Title.Props>;
129
-
130
- // Accessible heading for the sheet (labels the dialog for screen readers).
131
- export function BottomSheetTitle({ className, ...props }: BottomSheetTitleProps) {
132
- const theme = useThemeFamily();
133
- const { title } = bottomSheet({ theme });
134
- return (
135
- <Dialog.Title data-slot="bottom-sheet-title" className={title({ className })} {...props} />
136
- );
137
- }
138
-
139
- export type BottomSheetDescriptionProps = StyledProps<Dialog.Description.Props>;
140
-
141
- // Secondary supporting copy under the title; also the dialog's a11y description.
142
- export function BottomSheetDescription({ className, ...props }: BottomSheetDescriptionProps) {
143
- const theme = useThemeFamily();
144
- const { description } = bottomSheet({ theme });
145
- return (
146
- <Dialog.Description
147
- data-slot="bottom-sheet-description"
148
- className={description({ className })}
149
- {...props}
150
- />
151
- );
152
- }
@@ -1,22 +0,0 @@
1
- export {
2
- BottomSheet,
3
- BottomSheetTrigger,
4
- BottomSheetPortal,
5
- BottomSheetContent,
6
- BottomSheetClose,
7
- BottomSheetHeader,
8
- BottomSheetFooter,
9
- BottomSheetTitle,
10
- BottomSheetDescription,
11
- } from "./bottom-sheet";
12
- export type {
13
- BottomSheetProps,
14
- BottomSheetTriggerProps,
15
- BottomSheetPortalProps,
16
- BottomSheetContentProps,
17
- BottomSheetCloseProps,
18
- BottomSheetHeaderProps,
19
- BottomSheetFooterProps,
20
- BottomSheetTitleProps,
21
- BottomSheetDescriptionProps,
22
- } from "./bottom-sheet";
@@ -1,499 +0,0 @@
1
- import { Button as BaseButton } from "@base-ui/react/button";
2
- import type { ReactElement } from "react";
3
- import { tv, type VariantProps } from "../../lib/tv";
4
- import type { StyledProps } from "../../lib/styled-props";
5
- import { useThemeFamily } from "../../lib/theme/use-theme";
6
- import { Spinner } from "../spinner/index";
7
-
8
- export const buttonVariants = tv({
9
- slots: {
10
- root: [
11
- "relative inline-flex shrink-0 items-center justify-center",
12
- "font-heading leading-none whitespace-nowrap select-none",
13
- "border-line rounded-none",
14
- "shadow-sm transition-all duration-100",
15
- "outline outline-[1px] outline-offset-2 outline-transparent",
16
- "data-[loading=true]:cursor-wait",
17
- "disabled:pointer-events-none disabled:opacity-40 data-[loading=true]:opacity-100",
18
- "disabled:transform-none",
19
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
20
- ],
21
- content:
22
- "relative z-10 inline-flex items-center justify-center gap-[inherit] data-[loading=true]:invisible",
23
- loadingIndicator: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center",
24
- },
25
- variants: {
26
- theme: {
27
- brutal: {
28
- root: ["border-2 font-bold focus-visible:outline-transparent"],
29
- },
30
- elegant: {
31
- root: [
32
- "overflow-clip border-0 font-sans font-medium antialiased",
33
- "focus-visible:outline-[var(--button-focus-outline,transparent)]",
34
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.05),0_0_0_1px_var(--line-subtle)]",
35
- "before:pointer-events-none before:absolute before:inset-0 before:z-0 before:rounded-[inherit]",
36
- "active:not-aria-[haspopup]:scale-[0.985]",
37
- ],
38
- },
39
- },
40
- variant: {
41
- primary: {
42
- root: ["border-line-strong bg-primary-400 text-primary-950", "hover:bg-primary-500"],
43
- },
44
- default: {
45
- root: ["border-line-strong bg-layer-panel text-foreground-strong", "hover:bg-layer-panel"],
46
- },
47
- information: {
48
- root: ["border-line-strong bg-info-base text-foreground-inverse", "hover:bg-info-base"],
49
- },
50
- muted: {
51
- root: [
52
- "border-line-strong bg-secondary-400 text-secondary-950",
53
- "hover:border-line-strong hover:bg-secondary-400",
54
- ],
55
- },
56
- accent: {
57
- root: ["border-line-strong bg-accent-400 text-accent-950", "hover:bg-accent-500"],
58
- },
59
- warning: {
60
- root: [
61
- "border-line-strong bg-warning-base text-foreground-inverse",
62
- "hover:bg-warning-base",
63
- ],
64
- },
65
- outline: {
66
- root: [
67
- "border-line-strong bg-transparent text-foreground-strong",
68
- "hover:bg-layer-muted",
69
- "shadow-none",
70
- ],
71
- },
72
- ghost: {
73
- root: [
74
- "border-transparent bg-transparent text-foreground shadow-none",
75
- "hover:border-line-strong hover:bg-layer-muted",
76
- ],
77
- },
78
- link: {
79
- root: [
80
- "border-transparent bg-transparent text-foreground-strong shadow-none underline-offset-4",
81
- "hover:underline",
82
- ],
83
- },
84
- "danger-secondary": {
85
- root: ["border-line-strong bg-danger-lighter text-danger-base", "hover:bg-danger-lighter"],
86
- },
87
- danger: {
88
- root: [
89
- "border-line-strong bg-danger-base text-foreground-inverse",
90
- "hover:border-[oklch(0.595_0.241_26.758)] hover:bg-[oklch(0.595_0.241_26.758)]",
91
- ],
92
- },
93
- "danger-outline": {
94
- root: [
95
- "border-line-strong bg-transparent text-danger-base",
96
- "hover:bg-layer-muted",
97
- "shadow-none",
98
- ],
99
- },
100
- },
101
- size: {
102
- xs: {
103
- root: [
104
- "gap-1 px-2 py-[5px] text-[11px]",
105
- "has-data-[icon=inline-start]:pl-1.5 has-data-[icon=inline-end]:pr-1.5",
106
- "[&_svg:not([class*='size-'])]:size-3",
107
- ],
108
- },
109
- sm: {
110
- root: [
111
- "gap-1.5 px-2.5 py-[6px] text-xs",
112
- "has-data-[icon=inline-start]:pl-2 has-data-[icon=inline-end]:pr-2",
113
- "[&_svg:not([class*='size-'])]:size-3.5",
114
- ],
115
- },
116
- md: {
117
- root: [
118
- "gap-2 px-3 py-2 text-sm",
119
- "has-data-[icon=inline-start]:pl-2.5 has-data-[icon=inline-end]:pr-2.5",
120
- ],
121
- },
122
- lg: {
123
- root: [
124
- "gap-2 px-3.5 py-2.5 text-base",
125
- "has-data-[icon=inline-start]:pl-3 has-data-[icon=inline-end]:pr-3",
126
- "[&_svg:not([class*='size-'])]:size-4",
127
- ],
128
- },
129
- "icon-xs": { root: ["p-[5px] text-[11px]", "[&_svg:not([class*='size-'])]:size-3"] },
130
- "icon-sm": { root: ["p-[6px] text-xs", "[&_svg:not([class*='size-'])]:size-3.5"] },
131
- "icon-md": { root: ["p-2 text-sm", "[&_svg:not([class*='size-'])]:size-4"] },
132
- "icon-lg": { root: ["p-3 text-sm", "[&_svg:not([class*='size-'])]:size-4"] },
133
- },
134
- },
135
- defaultVariants: {
136
- variant: "default",
137
- size: "md",
138
- },
139
- compoundVariants: [
140
- {
141
- theme: "elegant",
142
- size: ["xs", "icon-xs"],
143
- class: { root: "rounded-sm" },
144
- },
145
- {
146
- theme: "elegant",
147
- size: ["sm", "icon-sm"],
148
- class: { root: "rounded" },
149
- },
150
- {
151
- theme: "elegant",
152
- size: ["md", "icon-md"],
153
- class: { root: "rounded-md" },
154
- },
155
- {
156
- theme: "elegant",
157
- size: ["lg", "icon-lg"],
158
- class: { root: "rounded-md" },
159
- },
160
- {
161
- theme: "brutal",
162
- variant: "primary",
163
- class: { root: "bg-brutal-yellow text-black hover:bg-brutal-yellow" },
164
- },
165
- {
166
- theme: "brutal",
167
- variant: "default",
168
- class: { root: "bg-white text-black hover:bg-white" },
169
- },
170
- {
171
- theme: "brutal",
172
- variant: "outline",
173
- class: { root: "bg-white text-black shadow-sm hover:bg-white" },
174
- },
175
- {
176
- theme: "brutal",
177
- variant: "information",
178
- class: { root: "bg-brutal-cyan text-black hover:bg-brutal-cyan" },
179
- },
180
- {
181
- theme: "brutal",
182
- variant: "muted",
183
- class: { root: "bg-brutal-stone text-black hover:bg-brutal-stone" },
184
- },
185
- {
186
- theme: "brutal",
187
- variant: "accent",
188
- class: { root: "bg-brutal-pink text-black hover:bg-brutal-pink" },
189
- },
190
- {
191
- theme: "brutal",
192
- variant: "danger",
193
- class: { root: "bg-brutal-red text-black hover:bg-brutal-red" },
194
- },
195
- {
196
- theme: "brutal",
197
- variant: "warning",
198
- class: {
199
- root: "bg-[oklch(0.785_0.123_50.11)] text-black hover:bg-[oklch(0.785_0.123_50.11)]",
200
- },
201
- },
202
- {
203
- theme: "brutal",
204
- size: "xs",
205
- class: { root: "h-6 px-2 py-0 text-[11px]" },
206
- },
207
- {
208
- theme: "brutal",
209
- size: "sm",
210
- class: { root: "h-7 px-2.5 py-0 text-xs" },
211
- },
212
- {
213
- theme: "brutal",
214
- size: "md",
215
- class: { root: "h-8 px-3 py-0 text-sm" },
216
- },
217
- {
218
- theme: "brutal",
219
- size: "lg",
220
- class: { root: "h-10 px-4 py-0 text-sm" },
221
- },
222
- {
223
- theme: "brutal",
224
- size: "icon-xs",
225
- class: { root: "size-6 p-0 text-[11px]" },
226
- },
227
- {
228
- theme: "brutal",
229
- size: "icon-sm",
230
- class: { root: "size-7 p-0 text-xs" },
231
- },
232
- {
233
- theme: "brutal",
234
- size: "icon-md",
235
- class: { root: "size-8 p-0 text-sm" },
236
- },
237
- {
238
- theme: "brutal",
239
- size: "icon-lg",
240
- class: { root: "size-10 p-0 text-sm" },
241
- },
242
- {
243
- theme: "elegant",
244
- variant: "default",
245
- class: {
246
- root: [
247
- "bg-foreground-strong text-foreground-inverse",
248
- "[--button-focus-outline:var(--foreground-strong)]",
249
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.12),0_0_0_1px_var(--foreground-strong)]",
250
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_8%)_0%,oklab(0%_0_0_/_0%)_100%)]",
251
- "hover:bg-[oklch(0.31_0.006_285)]",
252
- ],
253
- },
254
- },
255
- {
256
- theme: "elegant",
257
- variant: "primary",
258
- class: {
259
- root: [
260
- "bg-primary-400 text-primary-950",
261
- "[--button-focus-outline:var(--primary-400)]",
262
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.15),0_0_0_1px_oklch(0.83_0.14_91.89_/_0.83)]",
263
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_11%)_0%,oklab(100%_0_0_/_0%)_0%,oklab(0%_0_0_/_0%)_100%)]",
264
- "hover:bg-[oklch(0.86_0.15_91.89)]",
265
- ],
266
- },
267
- },
268
- {
269
- theme: "elegant",
270
- variant: "outline",
271
- class: {
272
- root: [
273
- "bg-layer-panel text-foreground-strong",
274
- "[--button-focus-outline:var(--layer-panel)]",
275
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.05),0_0_0_1px_var(--line-subtle)]",
276
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(0%_0_0_/_0%)_30%,oklab(0%_0_0_/_1%)_100%)]",
277
- "hover:bg-layer-muted",
278
- ],
279
- },
280
- },
281
- {
282
- theme: "elegant",
283
- variant: "ghost",
284
- class: {
285
- root: [
286
- "bg-transparent text-foreground-muted shadow-none",
287
- "[--button-focus-outline:var(--line-muted)]",
288
- "before:bg-transparent hover:bg-line-muted",
289
- ],
290
- },
291
- },
292
- {
293
- theme: "elegant",
294
- variant: "danger-secondary",
295
- class: {
296
- root: [
297
- "bg-danger-lighter text-danger-base",
298
- "[--button-focus-outline:var(--state-danger-lighter)]",
299
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.18),0_0_0_1px_var(--state-danger-light)]",
300
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_9%)_0%,oklab(0%_0_0_/_1%)_100%)]",
301
- "hover:bg-danger-light",
302
- ],
303
- },
304
- },
305
- {
306
- theme: "elegant",
307
- variant: "danger",
308
- class: {
309
- root: [
310
- "bg-danger-base text-foreground-inverse",
311
- "[--button-focus-outline:var(--state-danger-base)]",
312
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.12),0_0_0_1px_var(--state-danger-base)]",
313
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_10%)_0%,oklab(0%_0_0_/_0%)_100%)]",
314
- "hover:bg-[oklch(0.56_0.23_26.758)]",
315
- ],
316
- },
317
- },
318
- {
319
- theme: "brutal",
320
- variant: "danger",
321
- class: {
322
- root: [
323
- "border-line-strong bg-brutal-red text-black",
324
- "shadow-sm",
325
- "hover:border-line-strong hover:bg-brutal-red",
326
- "hover:-translate-y-px hover:shadow-md",
327
- "active:not-aria-[haspopup]:translate-x-px active:not-aria-[haspopup]:translate-y-px",
328
- "active:shadow-xs",
329
- ],
330
- },
331
- },
332
- {
333
- theme: "brutal",
334
- variant: "danger-secondary",
335
- class: {
336
- root: [
337
- "border-line-strong bg-danger-lighter text-[color-mix(in_oklab,var(--state-danger-base)_72%,transparent)]",
338
- "shadow-sm",
339
- "hover:border-line-strong hover:bg-danger-lighter",
340
- "hover:-translate-y-px hover:shadow-md",
341
- "active:not-aria-[haspopup]:translate-x-px active:not-aria-[haspopup]:translate-y-px",
342
- "active:shadow-xs",
343
- ],
344
- },
345
- },
346
- {
347
- theme: "elegant",
348
- variant: "danger-outline",
349
- class: {
350
- root: [
351
- "bg-layer-panel text-danger-base",
352
- "[--button-focus-outline:var(--layer-panel)]",
353
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.05),0_0_0_1px_var(--state-danger-light)]",
354
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(0%_0_0_/_0%)_30%,oklab(0%_0_0_/_1%)_100%)]",
355
- "hover:bg-danger-lighter",
356
- ],
357
- },
358
- },
359
- {
360
- theme: "elegant",
361
- variant: "accent",
362
- class: {
363
- root: [
364
- "bg-accent-400 text-white",
365
- "[--button-focus-outline:var(--accent-400)]",
366
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.12),0_0_0_1px_var(--accent-400)]",
367
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_8%)_0%,oklab(0%_0_0_/_0%)_100%)]",
368
- "hover:bg-[oklch(0.72_0.15_0.71)]",
369
- ],
370
- },
371
- },
372
- {
373
- theme: "elegant",
374
- variant: "warning",
375
- class: {
376
- root: [
377
- "bg-warning-base text-foreground-inverse",
378
- "[--button-focus-outline:var(--state-warning-base)]",
379
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.14),0_0_0_1px_var(--state-warning-base)]",
380
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_10%)_0%,oklab(0%_0_0_/_0%)_100%)]",
381
- "hover:bg-[oklch(0.65_0.19_44.441)]",
382
- ],
383
- },
384
- },
385
- {
386
- theme: "elegant",
387
- variant: "link",
388
- class: {
389
- root: [
390
- "bg-transparent text-foreground-muted shadow-none",
391
- "[--button-focus-outline:transparent]",
392
- "before:bg-transparent hover:bg-transparent hover:text-foreground-muted",
393
- ],
394
- },
395
- },
396
- {
397
- theme: "elegant",
398
- variant: "information",
399
- class: {
400
- root: [
401
- "bg-info-base text-foreground-inverse",
402
- "[--button-focus-outline:var(--state-info-base)]",
403
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.12),0_0_0_1px_var(--state-info-base)]",
404
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_8%)_0%,oklab(0%_0_0_/_0%)_100%)]",
405
- "hover:bg-[oklch(0.74_0.13_219.2)]",
406
- ],
407
- },
408
- },
409
- {
410
- theme: "elegant",
411
- variant: "muted",
412
- class: {
413
- root: [
414
- "bg-layer-muted text-foreground-placeholder",
415
- "[--button-focus-outline:var(--layer-muted)]",
416
- "shadow-[inset_0_1px_0.5px_oklch(1_0_0_/_0.05),0_0_0_1px_var(--line-subtle)]",
417
- "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0_/_5%)_0%,oklab(0%_0_0_/_1%)_100%)]",
418
- "hover:bg-line-subtle",
419
- ],
420
- },
421
- },
422
- {
423
- theme: "brutal",
424
- variant: ["primary", "default", "information", "muted", "accent", "warning", "outline"],
425
- class: {
426
- root: [
427
- "hover:-translate-y-px hover:shadow-md",
428
- "active:not-aria-[haspopup]:translate-x-px active:not-aria-[haspopup]:translate-y-px",
429
- "active:shadow-xs",
430
- ],
431
- },
432
- },
433
- ],
434
- });
435
-
436
- export type ButtonProps = StyledProps<BaseButton.Props> &
437
- Omit<VariantProps<typeof buttonVariants>, "theme"> & {
438
- loading?: boolean;
439
- loadingLabel?: string;
440
- };
441
-
442
- function defaultNativeButton(render: BaseButton.Props["render"]): boolean | undefined {
443
- if (!render || typeof render !== "object" || !("type" in render)) {
444
- return undefined;
445
- }
446
-
447
- const element = render as ReactElement;
448
- if (typeof element.type === "string") {
449
- return element.type === "button";
450
- }
451
-
452
- return undefined;
453
- }
454
-
455
- export function Button({
456
- variant,
457
- size,
458
- loading = false,
459
- loadingLabel = "Loading",
460
- disabled,
461
- className,
462
- children,
463
- render,
464
- nativeButton,
465
- ...props
466
- }: ButtonProps) {
467
- const theme = useThemeFamily();
468
- const { root, content, loadingIndicator } = buttonVariants({
469
- theme,
470
- variant,
471
- size,
472
- });
473
-
474
- return (
475
- <BaseButton
476
- {...props}
477
- render={render}
478
- nativeButton={nativeButton ?? defaultNativeButton(render)}
479
- data-slot="button"
480
- className={root({ className })}
481
- data-loading={loading ? "true" : undefined}
482
- disabled={disabled || loading}
483
- aria-disabled={loading || undefined}
484
- >
485
- {loading ? (
486
- <span data-slot="button-loading-indicator" className={loadingIndicator()}>
487
- <Spinner aria-label={loadingLabel} />
488
- </span>
489
- ) : null}
490
- <span
491
- data-slot="button-content"
492
- data-loading={loading ? "true" : undefined}
493
- className={content()}
494
- >
495
- {children}
496
- </span>
497
- </BaseButton>
498
- );
499
- }
@@ -1,2 +0,0 @@
1
- export { Button, buttonVariants } from "./button";
2
- export type { ButtonProps } from "./button";