@nationaldesignstudio/react 0.2.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/background/background.d.ts +13 -27
- package/dist/components/atoms/button/button.d.ts +64 -72
- package/dist/components/atoms/button/button.figma.d.ts +1 -0
- package/dist/components/atoms/button/icon-button.d.ts +62 -110
- package/dist/components/atoms/input/input-group.d.ts +278 -0
- package/dist/components/atoms/input/input.d.ts +121 -0
- package/dist/components/atoms/popover/popover.d.ts +195 -0
- package/dist/components/atoms/select/select.d.ts +131 -0
- package/dist/components/atoms/tooltip/tooltip.d.ts +161 -0
- package/dist/components/organisms/card/card.d.ts +3 -3
- package/dist/components/sections/hero/hero.d.ts +2 -2
- package/dist/components/sections/prose/prose.d.ts +3 -3
- package/dist/components/sections/river/river.d.ts +1 -1
- package/dist/components/sections/tout/tout.d.ts +4 -4
- package/dist/components/shared/floating-arrow.d.ts +34 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +13935 -7622
- package/dist/index.js.map +1 -1
- package/dist/lib/form-control.d.ts +106 -0
- package/dist/tokens.css +4725 -19065
- 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/background/background.tsx +71 -109
- package/src/components/atoms/button/button.figma.tsx +37 -0
- package/src/components/atoms/button/button.stories.tsx +253 -115
- package/src/components/atoms/button/button.test.tsx +289 -5
- package/src/components/atoms/button/button.tsx +40 -101
- package/src/components/atoms/button/button.visual.test.tsx +28 -32
- 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 +81 -224
- package/src/components/atoms/input/index.ts +17 -0
- package/src/components/atoms/input/input-group.stories.tsx +646 -0
- package/src/components/atoms/input/input-group.test.tsx +362 -0
- package/src/components/atoms/input/input-group.tsx +409 -0
- package/src/components/atoms/input/input.stories.tsx +228 -0
- package/src/components/atoms/input/input.test.tsx +167 -0
- package/src/components/atoms/input/input.tsx +104 -0
- 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/index.ts +18 -0
- package/src/components/atoms/select/select.stories.tsx +455 -0
- package/src/components/atoms/select/select.tsx +324 -0
- 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 -17
- package/src/components/dev-tools/dev-toolbar/dev-toolbar.tsx +3 -3
- package/src/components/foundation/typography/typography.stories.tsx +401 -0
- package/src/components/organisms/card/card.stories.tsx +19 -19
- package/src/components/organisms/card/card.test.tsx +1 -1
- package/src/components/organisms/card/card.tsx +3 -3
- package/src/components/organisms/card/card.visual.test.tsx +11 -11
- package/src/components/organisms/navbar/navbar.tsx +2 -2
- 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 +5 -5
- package/src/components/sections/faq-section/faq-section.tsx +2 -2
- package/src/components/sections/hero/hero.stories.tsx +7 -7
- package/src/components/sections/hero/hero.test.tsx +5 -5
- package/src/components/sections/hero/hero.tsx +10 -11
- package/src/components/sections/prose/prose.test.tsx +2 -2
- package/src/components/sections/prose/prose.tsx +6 -7
- package/src/components/sections/river/river.stories.tsx +8 -8
- package/src/components/sections/river/river.test.tsx +4 -4
- package/src/components/sections/river/river.tsx +8 -16
- package/src/components/sections/tout/tout.stories.tsx +7 -31
- package/src/components/sections/tout/tout.test.tsx +1 -1
- package/src/components/sections/tout/tout.tsx +11 -11
- 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 +98 -0
- package/src/lib/form-control.ts +71 -0
- package/src/stories/grid-system.stories.tsx +309 -0
- package/src/stories/{Introduction.mdx → introduction.mdx} +29 -15
- package/src/stories/{ThemeProvider.stories.tsx → theme-provider.stories.tsx} +8 -22
- package/src/stories/{TokenShowcase.stories.tsx → token-showcase.stories.tsx} +1 -20
- package/src/stories/token-showcase.tsx +777 -0
- package/src/styles.css +3 -0
- package/src/tests/token-resolution.test.tsx +298 -0
- 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/TokenShowcase.tsx +0 -1429
|
@@ -43,11 +43,7 @@ Playground.args = {
|
|
|
43
43
|
headline: "Brand-Large/Headline/Small",
|
|
44
44
|
body: "A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action.",
|
|
45
45
|
primaryAction: <Button>Primary</Button>,
|
|
46
|
-
secondaryAction:
|
|
47
|
-
<Button variant="outline" colorScheme="light">
|
|
48
|
-
Secondary
|
|
49
|
-
</Button>
|
|
50
|
-
),
|
|
46
|
+
secondaryAction: <Button variant="secondary-outline">Secondary</Button>,
|
|
51
47
|
backgroundMedia: <PlaceholderBackground />,
|
|
52
48
|
};
|
|
53
49
|
|
|
@@ -61,11 +57,7 @@ export const Desktop: Story = {
|
|
|
61
57
|
headline="Brand-Large/Headline/Small"
|
|
62
58
|
body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
|
|
63
59
|
primaryAction={<Button>Primary</Button>}
|
|
64
|
-
secondaryAction={
|
|
65
|
-
<Button variant="outline" colorScheme="light">
|
|
66
|
-
Secondary
|
|
67
|
-
</Button>
|
|
68
|
-
}
|
|
60
|
+
secondaryAction={<Button variant="secondary-outline">Secondary</Button>}
|
|
69
61
|
backgroundMedia={<PlaceholderBackground />}
|
|
70
62
|
/>
|
|
71
63
|
),
|
|
@@ -80,11 +72,7 @@ export const Tablet: Story = {
|
|
|
80
72
|
headline="Brand-Large/Headline/Small"
|
|
81
73
|
body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
|
|
82
74
|
primaryAction={<Button>Primary</Button>}
|
|
83
|
-
secondaryAction={
|
|
84
|
-
<Button variant="outline" colorScheme="light">
|
|
85
|
-
Secondary
|
|
86
|
-
</Button>
|
|
87
|
-
}
|
|
75
|
+
secondaryAction={<Button variant="secondary-outline">Secondary</Button>}
|
|
88
76
|
backgroundMedia={<PlaceholderBackground />}
|
|
89
77
|
/>
|
|
90
78
|
),
|
|
@@ -100,7 +88,7 @@ export const Mobile: Story = {
|
|
|
100
88
|
body="A river pattern stacks content in a simple vertical flow: one clear heading, a short block of copy, then the next step. It's ideal for guiding citizens through a process or story, keeping focus moving straight down the page with minimal choices and well-timed calls to action."
|
|
101
89
|
primaryAction={<Button size="sm">Primary</Button>}
|
|
102
90
|
secondaryAction={
|
|
103
|
-
<Button size="sm" variant="outline"
|
|
91
|
+
<Button size="sm" variant="secondary-outline">
|
|
104
92
|
Secondary
|
|
105
93
|
</Button>
|
|
106
94
|
}
|
|
@@ -125,11 +113,7 @@ export const WithImage: Story = {
|
|
|
125
113
|
headline="Work with Purpose"
|
|
126
114
|
body="Join a team that's building the future of government services. We're looking for passionate individuals who want to make a difference."
|
|
127
115
|
primaryAction={<Button>View Careers</Button>}
|
|
128
|
-
secondaryAction={
|
|
129
|
-
<Button variant="outline" colorScheme="light">
|
|
130
|
-
Learn More
|
|
131
|
-
</Button>
|
|
132
|
-
}
|
|
116
|
+
secondaryAction={<Button variant="secondary-outline">Learn More</Button>}
|
|
133
117
|
backgroundMedia={<ImageBackground />}
|
|
134
118
|
/>
|
|
135
119
|
),
|
|
@@ -158,11 +142,7 @@ export const WithVideoPlaceholder: Story = {
|
|
|
158
142
|
headline="Experience Innovation"
|
|
159
143
|
body="See how modern technology is transforming the way government serves its citizens."
|
|
160
144
|
primaryAction={<Button>Watch Video</Button>}
|
|
161
|
-
secondaryAction={
|
|
162
|
-
<Button variant="outline" colorScheme="light">
|
|
163
|
-
Learn More
|
|
164
|
-
</Button>
|
|
165
|
-
}
|
|
145
|
+
secondaryAction={<Button variant="secondary-outline">Learn More</Button>}
|
|
166
146
|
backgroundMedia={
|
|
167
147
|
<div className="absolute inset-0 bg-gray-800 flex items-center justify-center">
|
|
168
148
|
<span className="text-gray-400 typography-body-small">
|
|
@@ -183,11 +163,7 @@ export const WithNdstudioFooter: Story = {
|
|
|
183
163
|
headline="Work with Purpose"
|
|
184
164
|
body="Join a team that's building the future of government services. We're looking for passionate individuals who want to make a difference."
|
|
185
165
|
primaryAction={<Button>View Careers</Button>}
|
|
186
|
-
secondaryAction={
|
|
187
|
-
<Button variant="outline" colorScheme="light">
|
|
188
|
-
Learn More
|
|
189
|
-
</Button>
|
|
190
|
-
}
|
|
166
|
+
secondaryAction={<Button variant="secondary-outline">Learn More</Button>}
|
|
191
167
|
backgroundMedia={<ImageBackground />}
|
|
192
168
|
footer={<NdstudioFooter />}
|
|
193
169
|
/>
|
|
@@ -220,7 +220,7 @@ describe("Tout", () => {
|
|
|
220
220
|
);
|
|
221
221
|
|
|
222
222
|
const headline = page.getByRole("heading", { level: 2 });
|
|
223
|
-
await expect.element(headline).toHaveClass(/typography-
|
|
223
|
+
await expect.element(headline).toHaveClass(/typography-h4/);
|
|
224
224
|
await expect.element(headline).toHaveClass(/text-gray-900/);
|
|
225
225
|
});
|
|
226
226
|
|
|
@@ -93,9 +93,9 @@ export interface ToutProps
|
|
|
93
93
|
*
|
|
94
94
|
* This component is self-contained with its own grid.
|
|
95
95
|
* Grid setup:
|
|
96
|
-
* - Desktop (lg): 24 columns, gap-
|
|
97
|
-
* - Tablet (md): 12 columns, gap-
|
|
98
|
-
* - Mobile: 4 columns, gap-
|
|
96
|
+
* - Desktop (lg): 24 columns, gap-20, content spans 9 cols
|
|
97
|
+
* - Tablet (md): 12 columns, gap-20, content spans 9 cols
|
|
98
|
+
* - Mobile: 4 columns, gap-20, content spans all 4 cols
|
|
99
99
|
*
|
|
100
100
|
* @example
|
|
101
101
|
* ```tsx
|
|
@@ -103,7 +103,7 @@ export interface ToutProps
|
|
|
103
103
|
* headline="Feature Headline"
|
|
104
104
|
* body="Description of the feature..."
|
|
105
105
|
* primaryAction={<Button>Primary</Button>}
|
|
106
|
-
* secondaryAction={<Button variant="
|
|
106
|
+
* secondaryAction={<Button variant="outline" colorScheme="light">Secondary</Button>}
|
|
107
107
|
* backgroundMedia={
|
|
108
108
|
* <img
|
|
109
109
|
* src="/background.jpg"
|
|
@@ -163,7 +163,7 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
163
163
|
// Grid setup with responsive columns
|
|
164
164
|
"grid w-full h-full",
|
|
165
165
|
// Mobile: 4 columns with gap-20
|
|
166
|
-
"grid-cols-4 gap-
|
|
166
|
+
"grid-cols-4 gap-20",
|
|
167
167
|
// Tablet (md): 12 columns
|
|
168
168
|
"md:grid-cols-12",
|
|
169
169
|
// Desktop (lg): 24 columns
|
|
@@ -171,9 +171,9 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
171
171
|
// Max width and centering like grid-container
|
|
172
172
|
"max-w-[var(--breakpoint-lg)] mx-auto",
|
|
173
173
|
// Responsive margins matching grid-container - uses primitive spacing tokens
|
|
174
|
-
"px-
|
|
174
|
+
"px-20 md:px-56 lg:px-72",
|
|
175
175
|
// Vertical padding to position content at bottom - uses primitive spacing tokens
|
|
176
|
-
"py-
|
|
176
|
+
"py-36 md:py-56 lg:py-72",
|
|
177
177
|
)}
|
|
178
178
|
style={{
|
|
179
179
|
// Grid spacing theme overrides
|
|
@@ -193,7 +193,7 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
193
193
|
"flex flex-col",
|
|
194
194
|
isCentered ? "justify-start items-center" : "justify-end",
|
|
195
195
|
// Responsive gap between text and buttons - uses primitive spacing tokens
|
|
196
|
-
"gap-
|
|
196
|
+
"gap-28 md:gap-36",
|
|
197
197
|
// Mobile: all 4 cols
|
|
198
198
|
"col-span-4",
|
|
199
199
|
// Tablet & Desktop: 9 cols left-aligned, full width centered
|
|
@@ -203,13 +203,13 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
203
203
|
{/* Text content stack - uses primitive spacing tokens */}
|
|
204
204
|
<div
|
|
205
205
|
className={cn(
|
|
206
|
-
"flex flex-col gap-
|
|
206
|
+
"flex flex-col gap-16",
|
|
207
207
|
isCentered && "items-center text-center",
|
|
208
208
|
)}
|
|
209
209
|
>
|
|
210
210
|
<h2
|
|
211
211
|
className={cn(
|
|
212
|
-
"typography-
|
|
212
|
+
"typography-h4",
|
|
213
213
|
isDark ? "text-gray-100" : "text-gray-900",
|
|
214
214
|
)}
|
|
215
215
|
style={{
|
|
@@ -243,7 +243,7 @@ const Tout = React.forwardRef<HTMLElement, ToutProps>(
|
|
|
243
243
|
"flex flex-row",
|
|
244
244
|
isCentered ? "justify-center" : "items-start",
|
|
245
245
|
// Responsive gap between buttons
|
|
246
|
-
"gap-
|
|
246
|
+
"gap-8 md:gap-12",
|
|
247
247
|
"[&>*]:flex-shrink-0",
|
|
248
248
|
)}
|
|
249
249
|
>
|
|
@@ -16,11 +16,11 @@ const twoColumnSectionVariants = tv({
|
|
|
16
16
|
base: [
|
|
17
17
|
"w-full",
|
|
18
18
|
// Small (mobile): 20px x, 56px top, 20px bottom
|
|
19
|
-
"px-
|
|
19
|
+
"px-20 pt-56 pb-20",
|
|
20
20
|
// Medium (tablet): 56px x, 56px y
|
|
21
|
-
"md:px-
|
|
21
|
+
"md:px-56 md:py-56",
|
|
22
22
|
// Large (desktop): 72px x, 72px top, 112px bottom
|
|
23
|
-
"lg:px-
|
|
23
|
+
"lg:px-72 lg:pt-72 lg:pb-112",
|
|
24
24
|
],
|
|
25
25
|
variants: {
|
|
26
26
|
colorScheme: {
|
|
@@ -108,13 +108,11 @@ const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
|
108
108
|
{/* Inner container with border-top - uses primitive spacing tokens */}
|
|
109
109
|
<div
|
|
110
110
|
className={cn(
|
|
111
|
-
"border-t pt-
|
|
111
|
+
"border-t pt-36",
|
|
112
112
|
colorScheme === "dark" ? "border-gray-700" : "border-gray-300",
|
|
113
113
|
// Grid layout - uses primitive spacing tokens
|
|
114
|
-
"grid grid-cols-1 gap-
|
|
115
|
-
layout === "equal"
|
|
116
|
-
? "md:grid-cols-2"
|
|
117
|
-
: "lg:grid-cols-24 lg:gap-spacing-56",
|
|
114
|
+
"grid grid-cols-1 gap-56",
|
|
115
|
+
layout === "equal" ? "md:grid-cols-2" : "lg:grid-cols-24 lg:gap-56",
|
|
118
116
|
)}
|
|
119
117
|
>
|
|
120
118
|
{/* Title column */}
|
|
@@ -132,7 +130,7 @@ const TwoColumnSection = React.forwardRef<HTMLElement, TwoColumnSectionProps>(
|
|
|
132
130
|
{/* Content column - uses primitive spacing tokens */}
|
|
133
131
|
<div
|
|
134
132
|
className={cn(
|
|
135
|
-
"flex flex-col gap-
|
|
133
|
+
"flex flex-col gap-56",
|
|
136
134
|
layout !== "equal" && "lg:col-span-15",
|
|
137
135
|
)}
|
|
138
136
|
>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { tv } from "tailwind-variants";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared arrow variants for floating UI components
|
|
6
|
+
*
|
|
7
|
+
* Used by Tooltip, Popover, and other floating components.
|
|
8
|
+
* Handles positioning based on the side attribute.
|
|
9
|
+
*/
|
|
10
|
+
export const floatingArrowVariants = tv({
|
|
11
|
+
base: [
|
|
12
|
+
// Display flex to properly size the arrow container
|
|
13
|
+
"flex",
|
|
14
|
+
// Positioning based on floating side (uses spacing tokens since --spacing: 1px)
|
|
15
|
+
"data-[side=bottom]:-top-7",
|
|
16
|
+
"data-[side=left]:-right-12 data-[side=left]:rotate-90",
|
|
17
|
+
"data-[side=right]:-left-12 data-[side=right]:-rotate-90",
|
|
18
|
+
"data-[side=top]:-bottom-7 data-[side=top]:rotate-180",
|
|
19
|
+
// Animation - follows popup
|
|
20
|
+
"data-[starting-style]:opacity-0",
|
|
21
|
+
"data-[ending-style]:opacity-0",
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export interface FloatingArrowSvgProps {
|
|
26
|
+
/** CSS class for the main fill color (e.g., "fill-tooltip-bg" or "fill-overlay-background") */
|
|
27
|
+
fillClassName: string;
|
|
28
|
+
/** CSS class for the border color using fill-* (e.g., "fill-overlay-border") - renders as outline behind main fill */
|
|
29
|
+
borderClassName?: string;
|
|
30
|
+
/** Additional className for the SVG element */
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* FloatingArrowSvg
|
|
36
|
+
*
|
|
37
|
+
* A shared arrow SVG component for floating UI elements.
|
|
38
|
+
* Use with Tooltip, Popover, Dropdown, and other floating components.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* // For dark tooltip (no border)
|
|
43
|
+
* <FloatingArrowSvg fillClassName="fill-tooltip-bg" />
|
|
44
|
+
*
|
|
45
|
+
* // For light popover with border
|
|
46
|
+
* <FloatingArrowSvg
|
|
47
|
+
* fillClassName="fill-overlay-background"
|
|
48
|
+
* borderClassName="fill-overlay-border"
|
|
49
|
+
* />
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export const FloatingArrowSvg = ({
|
|
53
|
+
fillClassName,
|
|
54
|
+
borderClassName,
|
|
55
|
+
className,
|
|
56
|
+
}: FloatingArrowSvgProps) => (
|
|
57
|
+
<svg
|
|
58
|
+
width="20"
|
|
59
|
+
height="10"
|
|
60
|
+
viewBox="0 0 20 10"
|
|
61
|
+
fill="none"
|
|
62
|
+
className={cn("block", className)}
|
|
63
|
+
aria-hidden="true"
|
|
64
|
+
>
|
|
65
|
+
{/* Main fill shape */}
|
|
66
|
+
<path
|
|
67
|
+
d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
|
|
68
|
+
className={fillClassName}
|
|
69
|
+
/>
|
|
70
|
+
{/* Border stroke (rendered on top for outline effect) */}
|
|
71
|
+
{borderClassName && (
|
|
72
|
+
<path
|
|
73
|
+
d="M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z"
|
|
74
|
+
className={borderClassName}
|
|
75
|
+
/>
|
|
76
|
+
)}
|
|
77
|
+
</svg>
|
|
78
|
+
);
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nationaldesignstudio/react
|
|
3
|
+
* Design system components for React applications
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
// =============================================================================
|
|
2
7
|
// Atoms
|
|
3
8
|
// =============================================================================
|
|
@@ -35,6 +40,27 @@ export {
|
|
|
35
40
|
IconButton,
|
|
36
41
|
iconButtonVariants,
|
|
37
42
|
} from "./components/atoms/button";
|
|
43
|
+
export type {
|
|
44
|
+
InputGroupAddonProps,
|
|
45
|
+
InputGroupButtonProps,
|
|
46
|
+
InputGroupInputProps,
|
|
47
|
+
InputGroupProps,
|
|
48
|
+
InputGroupTextareaProps,
|
|
49
|
+
InputGroupTextProps,
|
|
50
|
+
InputProps,
|
|
51
|
+
} from "./components/atoms/input";
|
|
52
|
+
export {
|
|
53
|
+
Input,
|
|
54
|
+
InputGroup,
|
|
55
|
+
InputGroupAddon,
|
|
56
|
+
InputGroupButton,
|
|
57
|
+
InputGroupInput,
|
|
58
|
+
InputGroupText,
|
|
59
|
+
InputGroupTextarea,
|
|
60
|
+
inputGroupAddonVariants,
|
|
61
|
+
inputGroupVariants,
|
|
62
|
+
inputVariants,
|
|
63
|
+
} from "./components/atoms/input";
|
|
38
64
|
export type { NdstudioFooterProps } from "./components/atoms/ndstudio-footer";
|
|
39
65
|
export { NdstudioFooter } from "./components/atoms/ndstudio-footer";
|
|
40
66
|
export type { PagerControlProps } from "./components/atoms/pager-control";
|
|
@@ -42,6 +68,78 @@ export {
|
|
|
42
68
|
PagerControl,
|
|
43
69
|
pagerControlVariants,
|
|
44
70
|
} from "./components/atoms/pager-control";
|
|
71
|
+
export type {
|
|
72
|
+
PopoverArrowProps,
|
|
73
|
+
PopoverBackdropProps,
|
|
74
|
+
PopoverCloseProps,
|
|
75
|
+
PopoverDescriptionProps,
|
|
76
|
+
PopoverPopupProps,
|
|
77
|
+
PopoverPortalProps,
|
|
78
|
+
PopoverPositionerProps,
|
|
79
|
+
PopoverProps,
|
|
80
|
+
PopoverRootProps,
|
|
81
|
+
PopoverTitleProps,
|
|
82
|
+
PopoverTriggerProps,
|
|
83
|
+
} from "./components/atoms/popover";
|
|
84
|
+
export {
|
|
85
|
+
Popover,
|
|
86
|
+
PopoverArrow,
|
|
87
|
+
PopoverBackdrop,
|
|
88
|
+
PopoverClose,
|
|
89
|
+
PopoverDescription,
|
|
90
|
+
PopoverParts,
|
|
91
|
+
PopoverPopup,
|
|
92
|
+
PopoverPortal,
|
|
93
|
+
PopoverPositioner,
|
|
94
|
+
PopoverRoot,
|
|
95
|
+
PopoverTitle,
|
|
96
|
+
PopoverTrigger,
|
|
97
|
+
popoverArrowVariants,
|
|
98
|
+
popoverPopupVariants,
|
|
99
|
+
} from "./components/atoms/popover";
|
|
100
|
+
export type {
|
|
101
|
+
SelectGroupLabelProps,
|
|
102
|
+
SelectGroupProps,
|
|
103
|
+
SelectOptionProps,
|
|
104
|
+
SelectPopupProps,
|
|
105
|
+
SelectProps,
|
|
106
|
+
SelectTriggerProps,
|
|
107
|
+
} from "./components/atoms/select";
|
|
108
|
+
export {
|
|
109
|
+
Select,
|
|
110
|
+
SelectGroup,
|
|
111
|
+
SelectGroupLabel,
|
|
112
|
+
SelectOption,
|
|
113
|
+
SelectPopup,
|
|
114
|
+
SelectRoot,
|
|
115
|
+
SelectTrigger,
|
|
116
|
+
selectOptionVariants,
|
|
117
|
+
selectPopupVariants,
|
|
118
|
+
selectTriggerVariants,
|
|
119
|
+
} from "./components/atoms/select";
|
|
120
|
+
export type {
|
|
121
|
+
TooltipArrowProps,
|
|
122
|
+
TooltipPopupProps,
|
|
123
|
+
TooltipPortalProps,
|
|
124
|
+
TooltipPositionerProps,
|
|
125
|
+
TooltipProps,
|
|
126
|
+
TooltipProviderProps,
|
|
127
|
+
TooltipRootProps,
|
|
128
|
+
TooltipTriggerProps,
|
|
129
|
+
} from "./components/atoms/tooltip";
|
|
130
|
+
export {
|
|
131
|
+
Tooltip,
|
|
132
|
+
TooltipArrow,
|
|
133
|
+
TooltipParts,
|
|
134
|
+
TooltipPopup,
|
|
135
|
+
TooltipPortal,
|
|
136
|
+
TooltipPositioner,
|
|
137
|
+
TooltipProvider,
|
|
138
|
+
TooltipRoot,
|
|
139
|
+
TooltipTrigger,
|
|
140
|
+
tooltipArrowVariants,
|
|
141
|
+
tooltipPopupVariants,
|
|
142
|
+
} from "./components/atoms/tooltip";
|
|
45
143
|
// =============================================================================
|
|
46
144
|
// Dev Tools
|
|
47
145
|
// =============================================================================
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { tv } from "tailwind-variants";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared form control styles for Input, Select, and similar components.
|
|
5
|
+
*
|
|
6
|
+
* These base styles ensure consistent appearance across all form controls:
|
|
7
|
+
* - Consistent height and padding
|
|
8
|
+
* - Unified focus ring and border treatment
|
|
9
|
+
* - Shared hover/disabled states
|
|
10
|
+
*
|
|
11
|
+
* Based on Figma BaseKit / Interface / Input & Dropdown designs.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Base styles shared by all form controls (input, select, etc.)
|
|
16
|
+
*/
|
|
17
|
+
export const formControlBase = [
|
|
18
|
+
// Layout
|
|
19
|
+
"flex w-full items-center",
|
|
20
|
+
// Typography
|
|
21
|
+
"text-16 font-medium leading-14",
|
|
22
|
+
// Border and radius - uses surface ui radius for theming support
|
|
23
|
+
"border border-solid border-ui-color-border rounded-surface-ui-medium",
|
|
24
|
+
// Background
|
|
25
|
+
"bg-ui-control-background",
|
|
26
|
+
// Transitions
|
|
27
|
+
"transition-[background-color,border-color,box-shadow] duration-150",
|
|
28
|
+
// Focus state
|
|
29
|
+
"outline-none focus-visible:border-border-focus focus-visible:ring-4 focus-visible:ring-ui-color-focus",
|
|
30
|
+
// Hover state (when not focused or disabled)
|
|
31
|
+
"hover:bg-ui-control-background-hover hover:focus-visible:bg-ui-control-background",
|
|
32
|
+
// Disabled state
|
|
33
|
+
"disabled:bg-ui-control-background-disabled disabled:cursor-not-allowed disabled:opacity-50",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Size variants shared by form controls
|
|
38
|
+
* Uses spatial tokens for consistent sizing across form controls
|
|
39
|
+
*/
|
|
40
|
+
export const formControlSizes = {
|
|
41
|
+
sm: "h-spatial-ui-control-height-small px-spatial-ui-control-padding-x-small py-spatial-ui-control-padding-y-small text-14",
|
|
42
|
+
default:
|
|
43
|
+
"h-spatial-ui-control-height-medium px-spatial-ui-control-padding-x-medium py-spatial-ui-control-padding-y-medium",
|
|
44
|
+
lg: "h-spatial-ui-control-height-large px-spatial-ui-control-padding-x-large py-spatial-ui-control-padding-y-large text-18",
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Error state styles shared by form controls
|
|
49
|
+
*/
|
|
50
|
+
export const formControlError = {
|
|
51
|
+
true: "border-ui-error-color focus-visible:border-ui-error-color focus-visible:ring-ui-error-color/20 text-ui-error-color",
|
|
52
|
+
false: "",
|
|
53
|
+
} as const;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Form control variants using tailwind-variants
|
|
57
|
+
* Can be composed with other variants for specific components
|
|
58
|
+
*/
|
|
59
|
+
export const formControlVariants = tv({
|
|
60
|
+
base: formControlBase,
|
|
61
|
+
variants: {
|
|
62
|
+
size: formControlSizes,
|
|
63
|
+
error: formControlError,
|
|
64
|
+
},
|
|
65
|
+
defaultVariants: {
|
|
66
|
+
size: "default",
|
|
67
|
+
error: false,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export type FormControlSize = keyof typeof formControlSizes;
|