@nationaldesignstudio/react 0.3.0 → 0.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/dist/component-registry.md +1310 -127
- package/dist/components/atoms/button/button.d.ts +55 -47
- package/dist/components/atoms/button/button.figma.d.ts +1 -0
- package/dist/components/atoms/input/input.d.ts +24 -24
- package/dist/components/atoms/popover/popover.d.ts +195 -0
- package/dist/components/atoms/select/select.d.ts +24 -24
- package/dist/components/atoms/tooltip/tooltip.d.ts +161 -0
- package/dist/components/organisms/card/card.d.ts +1 -1
- package/dist/components/sections/hero/hero.d.ts +2 -2
- package/dist/components/sections/tout/tout.d.ts +3 -3
- package/dist/components/shared/floating-arrow.d.ts +34 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +11602 -8499
- package/dist/index.js.map +1 -1
- package/dist/lib/form-control.d.ts +25 -24
- package/dist/tokens.css +4797 -3940
- package/package.json +2 -1
- package/src/components/atoms/accordion/accordion.stories.tsx +1 -1
- package/src/components/atoms/accordion/accordion.tsx +2 -2
- package/src/components/atoms/button/button.figma.tsx +37 -0
- package/src/components/atoms/button/button.stories.tsx +236 -140
- package/src/components/atoms/button/button.test.tsx +289 -5
- package/src/components/atoms/button/button.tsx +37 -33
- package/src/components/atoms/button/button.visual.test.tsx +26 -76
- package/src/components/atoms/button/icon-button.stories.tsx +44 -101
- package/src/components/atoms/button/icon-button.test.tsx +26 -94
- package/src/components/atoms/button/icon-button.tsx +3 -3
- package/src/components/atoms/input/input-group.stories.tsx +4 -8
- package/src/components/atoms/input/input-group.test.tsx +14 -28
- package/src/components/atoms/input/input-group.tsx +57 -32
- package/src/components/atoms/input/input.stories.tsx +14 -18
- package/src/components/atoms/input/input.test.tsx +4 -20
- package/src/components/atoms/input/input.tsx +16 -9
- package/src/components/atoms/pager-control/pager-control.stories.tsx +6 -8
- package/src/components/atoms/pager-control/pager-control.tsx +12 -12
- package/src/components/atoms/popover/index.ts +30 -0
- package/src/components/atoms/popover/popover.stories.tsx +531 -0
- package/src/components/atoms/popover/popover.test.tsx +486 -0
- package/src/components/atoms/popover/popover.tsx +488 -0
- package/src/components/atoms/select/select.tsx +12 -8
- package/src/components/atoms/tooltip/index.ts +24 -0
- package/src/components/atoms/tooltip/tooltip.stories.tsx +348 -0
- package/src/components/atoms/tooltip/tooltip.test.tsx +363 -0
- package/src/components/atoms/tooltip/tooltip.tsx +347 -0
- package/src/components/dev-tools/dev-toolbar/dev-toolbar.stories.tsx +8 -13
- package/src/components/dev-tools/dev-toolbar/dev-toolbar.tsx +3 -3
- package/src/components/organisms/card/card.stories.tsx +19 -19
- package/src/components/organisms/card/card.tsx +1 -1
- package/src/components/organisms/card/card.visual.test.tsx +11 -11
- package/src/components/organisms/navbar/navbar.visual.test.tsx +2 -2
- package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +2 -2
- package/src/components/sections/banner/banner.stories.tsx +1 -5
- package/src/components/sections/banner/banner.test.tsx +2 -2
- package/src/components/sections/banner/banner.tsx +6 -6
- package/src/components/sections/card-grid/card-grid.tsx +4 -4
- package/src/components/sections/hero/hero.stories.tsx +7 -7
- package/src/components/sections/hero/hero.tsx +10 -11
- package/src/components/sections/prose/prose.tsx +2 -2
- package/src/components/sections/river/river.test.tsx +3 -3
- package/src/components/sections/river/river.tsx +6 -12
- package/src/components/sections/tout/tout.stories.tsx +7 -31
- package/src/components/sections/tout/tout.tsx +9 -9
- package/src/components/sections/two-column-section/two-column-section.tsx +7 -9
- package/src/components/shared/floating-arrow.tsx +78 -0
- package/src/components/shared/index.ts +5 -0
- package/src/index.ts +57 -0
- package/src/lib/form-control.ts +8 -6
- package/src/stories/grid-system.stories.tsx +309 -0
- package/src/stories/{ThemeProvider.stories.tsx → theme-provider.stories.tsx} +7 -19
- package/src/stories/{TokenShowcase.stories.tsx → token-showcase.stories.tsx} +1 -1
- package/src/stories/{TokenShowcase.tsx → token-showcase.tsx} +34 -34
- package/src/styles.css +3 -3
- package/src/tests/token-resolution.test.tsx +6 -9
- package/src/theme/hooks.ts +1 -1
- package/src/theme/index.ts +1 -1
- package/src/theme/theme-provider.test.tsx +270 -0
- package/src/theme/{ThemeProvider.tsx → theme-provider.tsx} +18 -2
- package/src/stories/GridSystem.stories.tsx +0 -84
- /package/src/stories/{Introduction.mdx → introduction.mdx} +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type * as React from "react";
|
|
4
4
|
import { tv, type VariantProps } from "tailwind-variants";
|
|
5
|
+
import { formControlBase } from "@/lib/form-control";
|
|
5
6
|
import { cn } from "@/lib/utils";
|
|
6
7
|
import { Button, type ButtonProps } from "../button";
|
|
7
8
|
|
|
@@ -11,25 +12,33 @@ import { Button, type ButtonProps } from "../button";
|
|
|
11
12
|
|
|
12
13
|
const inputGroupVariants = tv({
|
|
13
14
|
base: [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
15
|
+
...formControlBase,
|
|
16
|
+
// InputGroup-specific: Container layout and styling
|
|
17
|
+
"group/input-group relative flex w-full items-center justify-start",
|
|
18
|
+
"shadow-xs",
|
|
19
|
+
// Override focus state to work with child focus detection
|
|
20
|
+
"focus-visible:border-ui-color-border focus-visible:ring-0",
|
|
21
|
+
// Override hover to work with InputGroup structure
|
|
22
|
+
"hover:bg-ui-control-background",
|
|
23
|
+
// Height and layout (overridden by size variants)
|
|
24
|
+
"min-w-0",
|
|
19
25
|
"has-[>textarea]:h-auto",
|
|
20
26
|
"has-[>[data-align=inline-start]]:[&>input]:pl-6",
|
|
21
27
|
"has-[>[data-align=inline-end]]:[&>input]:pr-6",
|
|
22
|
-
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-
|
|
23
|
-
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:
|
|
24
|
-
|
|
28
|
+
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pt-spatial-ui-input-group-gap-block has-[>[data-align=block-start]]:[&>input]:pb-spatial-ui-input-group-padding-y-medium",
|
|
29
|
+
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pb-spatial-ui-input-group-gap-block",
|
|
30
|
+
// Focus state detection on child input (overrides formControlBase focus)
|
|
31
|
+
"has-[[data-slot=input-group-control]:focus-visible]:border-ui-accent-base has-[[data-slot=input-group-control]:focus-visible]:ring-4 has-[[data-slot=input-group-control]:focus-visible]:ring-ui-color-focus",
|
|
32
|
+
// Error state detection on child elements
|
|
25
33
|
"has-[[data-slot][aria-invalid=true]]:border-ui-error-color has-[[data-slot][aria-invalid=true]]:ring-ui-error-color/20",
|
|
34
|
+
// Disabled state (overrides formControlBase disabled)
|
|
26
35
|
"data-[disabled=true]:bg-ui-control-background-disabled data-[disabled=true]:opacity-50 data-[disabled=true]:cursor-not-allowed",
|
|
27
36
|
],
|
|
28
37
|
variants: {
|
|
29
38
|
size: {
|
|
30
|
-
sm: "h-
|
|
31
|
-
default: "h-
|
|
32
|
-
lg: "h-
|
|
39
|
+
sm: "h-spatial-ui-input-group-height-small",
|
|
40
|
+
default: "h-spatial-ui-input-group-height-medium",
|
|
41
|
+
lg: "h-spatial-ui-input-group-height-large",
|
|
33
42
|
},
|
|
34
43
|
},
|
|
35
44
|
defaultVariants: {
|
|
@@ -44,23 +53,37 @@ const inputGroupVariants = tv({
|
|
|
44
53
|
const inputGroupAddonVariants = tv({
|
|
45
54
|
base: [
|
|
46
55
|
"flex items-center justify-center gap-6",
|
|
47
|
-
"text-
|
|
56
|
+
"typography-ui-text-sm text-text-muted",
|
|
48
57
|
"select-none cursor-text",
|
|
49
|
-
"[&>svg:not([class*='size-'])]:size-
|
|
58
|
+
"[&>svg:not([class*='size-'])]:size-16",
|
|
50
59
|
"[&_button]:text-[unset] [&_button]:cursor-pointer",
|
|
51
60
|
"group-data-[disabled=true]/input-group:opacity-50",
|
|
52
61
|
],
|
|
53
62
|
variants: {
|
|
54
63
|
align: {
|
|
55
|
-
"inline-start": [
|
|
56
|
-
|
|
64
|
+
"inline-start": [
|
|
65
|
+
"order-first h-full",
|
|
66
|
+
"pl-spatial-ui-input-group-padding-x-medium",
|
|
67
|
+
"has-[>button]:ml-[-6px]",
|
|
68
|
+
],
|
|
69
|
+
"inline-end": [
|
|
70
|
+
"order-last h-full",
|
|
71
|
+
"pr-spatial-ui-input-group-padding-x-medium",
|
|
72
|
+
"has-[>button]:mr-[-6px]",
|
|
73
|
+
],
|
|
57
74
|
"block-start": [
|
|
58
|
-
"order-first h-auto w-full justify-start
|
|
59
|
-
"
|
|
75
|
+
"order-first h-auto w-full justify-start",
|
|
76
|
+
"px-spatial-ui-input-group-padding-x-medium pt-spatial-ui-input-group-padding-y-medium",
|
|
77
|
+
"[.border-b]:pb-spatial-ui-input-group-padding-y-medium",
|
|
78
|
+
// Use shared text style for block addons (12px, Regular weight per Figma)
|
|
79
|
+
"typography-ui-text-xs",
|
|
60
80
|
],
|
|
61
81
|
"block-end": [
|
|
62
|
-
"order-last h-auto w-full justify-start
|
|
63
|
-
"
|
|
82
|
+
"order-last h-auto w-full justify-start",
|
|
83
|
+
"px-spatial-ui-input-group-padding-x-medium pb-spatial-ui-input-group-padding-y-medium",
|
|
84
|
+
"[.border-t]:pt-spatial-ui-input-group-padding-y-medium",
|
|
85
|
+
// Use shared text style for block addons (12px, Regular weight per Figma)
|
|
86
|
+
"typography-ui-text-xs",
|
|
64
87
|
],
|
|
65
88
|
},
|
|
66
89
|
},
|
|
@@ -119,7 +142,7 @@ function InputGroup({ className, size, disabled, ...props }: InputGroupProps) {
|
|
|
119
142
|
data-disabled={disabled || undefined}
|
|
120
143
|
disabled={disabled}
|
|
121
144
|
className={cn(
|
|
122
|
-
"
|
|
145
|
+
"p-0 m-0 min-w-0",
|
|
123
146
|
inputGroupVariants({ size, class: className }),
|
|
124
147
|
)}
|
|
125
148
|
{...props}
|
|
@@ -210,16 +233,18 @@ function InputGroupAddon({
|
|
|
210
233
|
|
|
211
234
|
const inputGroupButtonVariants = tv({
|
|
212
235
|
base: [
|
|
213
|
-
"
|
|
236
|
+
"typography-ui-button-small shadow-none flex gap-6 items-center",
|
|
214
237
|
"focus-visible:ring-1 focus-visible:ring-offset-0 focus-visible:ring-ui-color-border",
|
|
215
238
|
"transition-opacity duration-150",
|
|
216
239
|
],
|
|
217
240
|
variants: {
|
|
218
241
|
size: {
|
|
219
|
-
xs: "!h-24 gap-4 px-8 rounded-
|
|
220
|
-
sm: "!h-28 px-10 gap-6 rounded-
|
|
221
|
-
"icon-xs":
|
|
222
|
-
|
|
242
|
+
xs: "!h-24 gap-4 px-8 rounded-surface-ui-small [&>svg:not([class*='size-'])]:size-16 has-[>svg]:px-6",
|
|
243
|
+
sm: "!h-28 px-10 gap-6 rounded-surface-ui-medium has-[>svg]:px-8",
|
|
244
|
+
"icon-xs":
|
|
245
|
+
"!size-24 rounded-surface-ui-small p-0 [&>svg:not([class*='size-'])]:size-16 has-[>svg]:p-0",
|
|
246
|
+
"icon-sm":
|
|
247
|
+
"!size-28 rounded-surface-ui-medium p-0 [&>svg:not([class*='size-'])]:size-16 has-[>svg]:p-0",
|
|
223
248
|
},
|
|
224
249
|
},
|
|
225
250
|
defaultVariants: {
|
|
@@ -291,8 +316,8 @@ function InputGroupText({ className, ...props }: InputGroupTextProps) {
|
|
|
291
316
|
return (
|
|
292
317
|
<span
|
|
293
318
|
className={cn(
|
|
294
|
-
"flex items-center gap-6 text-
|
|
295
|
-
"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-
|
|
319
|
+
"flex items-center gap-6 typography-ui-text-sm text-text-muted",
|
|
320
|
+
"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-16",
|
|
296
321
|
className,
|
|
297
322
|
)}
|
|
298
323
|
{...props}
|
|
@@ -324,10 +349,10 @@ function InputGroupInput({ className, ...props }: InputGroupInputProps) {
|
|
|
324
349
|
<input
|
|
325
350
|
data-slot="input-group-control"
|
|
326
351
|
className={cn(
|
|
327
|
-
"flex-1 min-w-0 h-full",
|
|
352
|
+
"flex-1 min-w-0 h-full w-full",
|
|
328
353
|
"border-0 bg-transparent shadow-none outline-none",
|
|
329
|
-
"text-
|
|
330
|
-
"px-
|
|
354
|
+
"typography-ui-text-sm text-left placeholder:text-text-muted",
|
|
355
|
+
"px-spatial-ui-input-group-padding-x-medium",
|
|
331
356
|
"focus-visible:ring-0",
|
|
332
357
|
className,
|
|
333
358
|
)}
|
|
@@ -362,8 +387,8 @@ function InputGroupTextarea({ className, ...props }: InputGroupTextareaProps) {
|
|
|
362
387
|
className={cn(
|
|
363
388
|
"flex-1 min-w-0 w-full resize-none",
|
|
364
389
|
"border-0 bg-transparent shadow-none outline-none",
|
|
365
|
-
"text-
|
|
366
|
-
"px-
|
|
390
|
+
"typography-ui-text-sm text-left placeholder:text-text-muted",
|
|
391
|
+
"px-spatial-ui-input-group-padding-x-medium py-spatial-ui-input-group-padding-y-medium",
|
|
367
392
|
"focus-visible:ring-0",
|
|
368
393
|
className,
|
|
369
394
|
)}
|
|
@@ -70,33 +70,29 @@ export const Disabled = () => <Input disabled placeholder="Disabled input" />;
|
|
|
70
70
|
* All states comparison
|
|
71
71
|
*/
|
|
72
72
|
export const AllStates = () => (
|
|
73
|
-
<div className="flex flex-col gap-
|
|
73
|
+
<div className="flex flex-col gap-16 max-w-[320px]">
|
|
74
74
|
<div>
|
|
75
|
-
<p className="mb-
|
|
75
|
+
<p className="mb-8 text-12 text-text-muted">Default</p>
|
|
76
76
|
<Input placeholder="Enter text..." />
|
|
77
77
|
</div>
|
|
78
78
|
<div>
|
|
79
|
-
<p className="mb-
|
|
80
|
-
Hover (hover the input)
|
|
81
|
-
</p>
|
|
79
|
+
<p className="mb-8 text-12 text-text-muted">Hover (hover the input)</p>
|
|
82
80
|
<Input placeholder="Hover me..." />
|
|
83
81
|
</div>
|
|
84
82
|
<div>
|
|
85
|
-
<p className="mb-
|
|
86
|
-
Focus (click the input)
|
|
87
|
-
</p>
|
|
83
|
+
<p className="mb-8 text-12 text-text-muted">Focus (click the input)</p>
|
|
88
84
|
<Input placeholder="Click to focus..." />
|
|
89
85
|
</div>
|
|
90
86
|
<div>
|
|
91
|
-
<p className="mb-
|
|
87
|
+
<p className="mb-8 text-12 text-text-muted">Filled</p>
|
|
92
88
|
<Input defaultValue="Filled content" />
|
|
93
89
|
</div>
|
|
94
90
|
<div>
|
|
95
|
-
<p className="mb-
|
|
91
|
+
<p className="mb-8 text-12 text-text-muted">Error</p>
|
|
96
92
|
<Input error placeholder="Invalid input" />
|
|
97
93
|
</div>
|
|
98
94
|
<div>
|
|
99
|
-
<p className="mb-
|
|
95
|
+
<p className="mb-8 text-12 text-text-muted">Disabled</p>
|
|
100
96
|
<Input disabled placeholder="Disabled input" />
|
|
101
97
|
</div>
|
|
102
98
|
</div>
|
|
@@ -127,17 +123,17 @@ export const Large = () => <Input size="lg" placeholder="Large input" />;
|
|
|
127
123
|
* All sizes comparison
|
|
128
124
|
*/
|
|
129
125
|
export const AllSizes = () => (
|
|
130
|
-
<div className="flex flex-col gap-
|
|
126
|
+
<div className="flex flex-col gap-16 max-w-[320px]">
|
|
131
127
|
<div>
|
|
132
|
-
<p className="mb-
|
|
128
|
+
<p className="mb-8 text-12 text-text-muted">Small (36px)</p>
|
|
133
129
|
<Input size="sm" placeholder="Small input" />
|
|
134
130
|
</div>
|
|
135
131
|
<div>
|
|
136
|
-
<p className="mb-
|
|
132
|
+
<p className="mb-8 text-12 text-text-muted">Default (48px)</p>
|
|
137
133
|
<Input size="default" placeholder="Default input" />
|
|
138
134
|
</div>
|
|
139
135
|
<div>
|
|
140
|
-
<p className="mb-
|
|
136
|
+
<p className="mb-8 text-12 text-text-muted">Large (56px)</p>
|
|
141
137
|
<Input size="lg" placeholder="Large input" />
|
|
142
138
|
</div>
|
|
143
139
|
</div>
|
|
@@ -181,7 +177,7 @@ export const SearchType = () => <Input type="search" placeholder="Search..." />;
|
|
|
181
177
|
* Form field example with label
|
|
182
178
|
*/
|
|
183
179
|
export const WithLabel = () => (
|
|
184
|
-
<div className="flex flex-col gap-
|
|
180
|
+
<div className="flex flex-col gap-8 max-w-[320px]">
|
|
185
181
|
<label
|
|
186
182
|
htmlFor="email-input"
|
|
187
183
|
className="text-14 font-medium text-text-primary"
|
|
@@ -196,7 +192,7 @@ export const WithLabel = () => (
|
|
|
196
192
|
* Form field with error message
|
|
197
193
|
*/
|
|
198
194
|
export const WithErrorMessage = () => (
|
|
199
|
-
<div className="flex flex-col gap-
|
|
195
|
+
<div className="flex flex-col gap-8 max-w-[320px]">
|
|
200
196
|
<label
|
|
201
197
|
htmlFor="email-error"
|
|
202
198
|
className="text-14 font-medium text-text-primary"
|
|
@@ -220,7 +216,7 @@ export const WithErrorMessage = () => (
|
|
|
220
216
|
* Required field indicator
|
|
221
217
|
*/
|
|
222
218
|
export const RequiredField = () => (
|
|
223
|
-
<div className="flex flex-col gap-
|
|
219
|
+
<div className="flex flex-col gap-8 max-w-[320px]">
|
|
224
220
|
<label
|
|
225
221
|
htmlFor="required-input"
|
|
226
222
|
className="text-14 font-medium text-text-primary"
|
|
@@ -105,44 +105,28 @@ describe("Input", () => {
|
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
describe("Variants", () => {
|
|
108
|
-
test("applies default size
|
|
108
|
+
test("applies default size", async () => {
|
|
109
109
|
render(<Input placeholder="Default" />);
|
|
110
110
|
const input = page.getByRole("textbox");
|
|
111
111
|
await expect.element(input).toHaveAttribute("data-size", "default");
|
|
112
|
-
await expect.element(input).toHaveClass(/h-48/);
|
|
113
112
|
});
|
|
114
113
|
|
|
115
|
-
test("applies small size
|
|
114
|
+
test("applies small size", async () => {
|
|
116
115
|
render(<Input size="sm" placeholder="Small" />);
|
|
117
116
|
const input = page.getByRole("textbox");
|
|
118
117
|
await expect.element(input).toHaveAttribute("data-size", "sm");
|
|
119
|
-
await expect.element(input).toHaveClass(/h-36/);
|
|
120
118
|
});
|
|
121
119
|
|
|
122
|
-
test("applies large size
|
|
120
|
+
test("applies large size", async () => {
|
|
123
121
|
render(<Input size="lg" placeholder="Large" />);
|
|
124
122
|
const input = page.getByRole("textbox");
|
|
125
123
|
await expect.element(input).toHaveAttribute("data-size", "lg");
|
|
126
|
-
await expect.element(input).toHaveClass(/h-56/);
|
|
127
124
|
});
|
|
128
125
|
|
|
129
|
-
test("applies error state
|
|
126
|
+
test("applies error state", async () => {
|
|
130
127
|
render(<Input error placeholder="Error" />);
|
|
131
128
|
const input = page.getByRole("textbox");
|
|
132
129
|
await expect.element(input).toHaveAttribute("data-error", "true");
|
|
133
|
-
await expect.element(input).toHaveClass(/border-ui-error-color/);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test("applies semantic token classes for background", async () => {
|
|
137
|
-
render(<Input placeholder="Default" />);
|
|
138
|
-
const input = page.getByRole("textbox");
|
|
139
|
-
await expect.element(input).toHaveClass(/bg-ui-control-background/);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test("applies semantic token classes for border", async () => {
|
|
143
|
-
render(<Input placeholder="Default" />);
|
|
144
|
-
const input = page.getByRole("textbox");
|
|
145
|
-
await expect.element(input).toHaveClass(/border-ui-color-border/);
|
|
146
130
|
});
|
|
147
131
|
});
|
|
148
132
|
|
|
@@ -2,13 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { tv, type VariantProps } from "tailwind-variants";
|
|
5
|
-
import {
|
|
6
|
-
formControlBase,
|
|
7
|
-
formControlError,
|
|
8
|
-
formControlSizes,
|
|
9
|
-
} from "@/lib/form-control";
|
|
5
|
+
import { formControlBase, formControlError } from "@/lib/form-control";
|
|
10
6
|
import { cn } from "@/lib/utils";
|
|
11
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Input-specific size variants using semantic input tokens.
|
|
10
|
+
* These tokens allow input sizing to be customized independently from other controls.
|
|
11
|
+
*/
|
|
12
|
+
const inputSizes = {
|
|
13
|
+
sm: "h-spatial-ui-input-height-small px-spatial-ui-input-padding-x-small py-spatial-ui-input-padding-y-small typography-body-sm-md",
|
|
14
|
+
default:
|
|
15
|
+
"h-spatial-ui-input-height-medium px-spatial-ui-input-padding-x-medium py-spatial-ui-input-padding-y-medium typography-body-md-md",
|
|
16
|
+
lg: "h-spatial-ui-input-height-large px-spatial-ui-input-padding-x-large py-spatial-ui-input-padding-y-large typography-body-md-lg",
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
12
19
|
/**
|
|
13
20
|
* Input variants for styling based on Figma BaseKit / Interface / Input
|
|
14
21
|
*
|
|
@@ -20,9 +27,9 @@ import { cn } from "@/lib/utils";
|
|
|
20
27
|
* - Disabled: Disabled background (via :disabled)
|
|
21
28
|
*
|
|
22
29
|
* Sizes:
|
|
23
|
-
* - sm: Smaller height and padding
|
|
24
|
-
* - default: Standard 48px
|
|
25
|
-
* - lg: Larger height and padding
|
|
30
|
+
* - sm: Smaller height and padding (36px)
|
|
31
|
+
* - default: Standard height (48px)
|
|
32
|
+
* - lg: Larger height and padding (56px)
|
|
26
33
|
*/
|
|
27
34
|
const inputVariants = tv({
|
|
28
35
|
base: [
|
|
@@ -31,7 +38,7 @@ const inputVariants = tv({
|
|
|
31
38
|
"placeholder:text-text-muted",
|
|
32
39
|
],
|
|
33
40
|
variants: {
|
|
34
|
-
size:
|
|
41
|
+
size: inputSizes,
|
|
35
42
|
error: {
|
|
36
43
|
...formControlError,
|
|
37
44
|
true: `${formControlError.true} placeholder:text-ui-error-color/60`,
|
|
@@ -130,28 +130,26 @@ export const Controlled = () => {
|
|
|
130
130
|
const [activeIndex, setActiveIndex] = React.useState(0);
|
|
131
131
|
|
|
132
132
|
return (
|
|
133
|
-
<div className="flex flex-col items-center gap-
|
|
133
|
+
<div className="flex flex-col items-center gap-24">
|
|
134
134
|
<PagerControl
|
|
135
135
|
count={4}
|
|
136
136
|
activeIndex={activeIndex}
|
|
137
137
|
onChange={setActiveIndex}
|
|
138
138
|
autoPlay={false}
|
|
139
139
|
/>
|
|
140
|
-
<div className="flex gap-
|
|
140
|
+
<div className="flex gap-10">
|
|
141
141
|
<button
|
|
142
142
|
type="button"
|
|
143
143
|
onClick={() => setActiveIndex((prev) => Math.max(0, prev - 1))}
|
|
144
|
-
className="rounded bg-gray-200 px-
|
|
144
|
+
className="rounded bg-gray-200 px-12 py-6"
|
|
145
145
|
>
|
|
146
146
|
Previous
|
|
147
147
|
</button>
|
|
148
|
-
<span className="px-
|
|
149
|
-
Page {activeIndex + 1} of 4
|
|
150
|
-
</span>
|
|
148
|
+
<span className="px-12 py-6">Page {activeIndex + 1} of 4</span>
|
|
151
149
|
<button
|
|
152
150
|
type="button"
|
|
153
151
|
onClick={() => setActiveIndex((prev) => Math.min(3, prev + 1))}
|
|
154
|
-
className="rounded bg-gray-200 px-
|
|
152
|
+
className="rounded bg-gray-200 px-12 py-6"
|
|
155
153
|
>
|
|
156
154
|
Next
|
|
157
155
|
</button>
|
|
@@ -174,7 +172,7 @@ export const WithCarousel = () => {
|
|
|
174
172
|
];
|
|
175
173
|
|
|
176
174
|
return (
|
|
177
|
-
<div className="flex w-[400px] flex-col gap-
|
|
175
|
+
<div className="flex w-[400px] flex-col gap-16">
|
|
178
176
|
<div className="relative h-[200px] overflow-hidden rounded-radius-12">
|
|
179
177
|
{slides.map((slide, index) => (
|
|
180
178
|
<div
|
|
@@ -9,9 +9,9 @@ const pagerControlVariants = tv({
|
|
|
9
9
|
variants: {
|
|
10
10
|
size: {
|
|
11
11
|
// Uses primitive spacing tokens
|
|
12
|
-
sm: "gap-
|
|
13
|
-
default: "gap-
|
|
14
|
-
lg: "gap-
|
|
12
|
+
sm: "gap-2",
|
|
13
|
+
default: "gap-2",
|
|
14
|
+
lg: "gap-4",
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
defaultVariants: {
|
|
@@ -24,9 +24,9 @@ const dotBaseVariants = tv({
|
|
|
24
24
|
variants: {
|
|
25
25
|
size: {
|
|
26
26
|
// Uses primitive spacing tokens
|
|
27
|
-
sm: "h-
|
|
28
|
-
default: "h-
|
|
29
|
-
lg: "h-
|
|
27
|
+
sm: "h-6",
|
|
28
|
+
default: "h-10",
|
|
29
|
+
lg: "h-16",
|
|
30
30
|
},
|
|
31
31
|
variant: {
|
|
32
32
|
charcoal: "",
|
|
@@ -245,20 +245,20 @@ const PagerControl = React.forwardRef<HTMLDivElement, PagerControlProps>(
|
|
|
245
245
|
if (isActive) {
|
|
246
246
|
switch (size) {
|
|
247
247
|
case "sm":
|
|
248
|
-
return "w-
|
|
248
|
+
return "w-16";
|
|
249
249
|
case "lg":
|
|
250
|
-
return "w-
|
|
250
|
+
return "w-36";
|
|
251
251
|
default:
|
|
252
|
-
return "w-
|
|
252
|
+
return "w-28";
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
255
|
switch (size) {
|
|
256
256
|
case "sm":
|
|
257
|
-
return "w-
|
|
257
|
+
return "w-6";
|
|
258
258
|
case "lg":
|
|
259
|
-
return "w-
|
|
259
|
+
return "w-16";
|
|
260
260
|
default:
|
|
261
|
-
return "w-
|
|
261
|
+
return "w-10";
|
|
262
262
|
}
|
|
263
263
|
};
|
|
264
264
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
PopoverArrowProps,
|
|
3
|
+
PopoverBackdropProps,
|
|
4
|
+
PopoverCloseProps,
|
|
5
|
+
PopoverDescriptionProps,
|
|
6
|
+
PopoverPopupProps,
|
|
7
|
+
PopoverPortalProps,
|
|
8
|
+
PopoverPositionerProps,
|
|
9
|
+
PopoverProps,
|
|
10
|
+
PopoverRootProps,
|
|
11
|
+
PopoverTitleProps,
|
|
12
|
+
PopoverTriggerProps,
|
|
13
|
+
} from "./popover";
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
Popover,
|
|
17
|
+
PopoverArrow,
|
|
18
|
+
PopoverBackdrop,
|
|
19
|
+
PopoverClose,
|
|
20
|
+
PopoverDescription,
|
|
21
|
+
PopoverParts,
|
|
22
|
+
PopoverPopup,
|
|
23
|
+
PopoverPortal,
|
|
24
|
+
PopoverPositioner,
|
|
25
|
+
PopoverRoot,
|
|
26
|
+
PopoverTitle,
|
|
27
|
+
PopoverTrigger,
|
|
28
|
+
popoverArrowVariants,
|
|
29
|
+
popoverPopupVariants,
|
|
30
|
+
} from "./popover";
|