@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
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Tooltip as BaseTooltip } from "@base-ui-components/react/tooltip";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { tv, type VariantProps } from "tailwind-variants";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
import {
|
|
8
|
+
FloatingArrowSvg,
|
|
9
|
+
floatingArrowVariants,
|
|
10
|
+
} from "../../shared/floating-arrow";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Tooltip popup variants
|
|
14
|
+
*
|
|
15
|
+
* Uses semantic tokens for themeable styling:
|
|
16
|
+
* - color.tooltip.bg - Dark background
|
|
17
|
+
* - color.tooltip.text - Light text
|
|
18
|
+
* - surface.tooltip.radius - Small border radius
|
|
19
|
+
* - spatial.component.tooltip.padding-x/y - Consistent padding
|
|
20
|
+
*/
|
|
21
|
+
const tooltipPopupVariants = tv({
|
|
22
|
+
base: [
|
|
23
|
+
// Layout - uses component tooltip tokens
|
|
24
|
+
"px-spatial-component-tooltip-padding-x py-spatial-component-tooltip-padding-y",
|
|
25
|
+
// Background and text - uses tooltip color tokens
|
|
26
|
+
"bg-tooltip-bg text-tooltip-text",
|
|
27
|
+
// Border radius - uses surface tooltip token
|
|
28
|
+
"rounded-surface-tooltip",
|
|
29
|
+
// Typography - uses semantic body text composite
|
|
30
|
+
"typography-body-sm-md font-medium",
|
|
31
|
+
// Shadow for elevation
|
|
32
|
+
"shadow-md",
|
|
33
|
+
// Allow arrow to extend outside popup bounds
|
|
34
|
+
"overflow-visible",
|
|
35
|
+
// Animation
|
|
36
|
+
"origin-[var(--transform-origin)]",
|
|
37
|
+
"transition-[transform,scale,opacity] duration-150",
|
|
38
|
+
"data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
|
|
39
|
+
"data-[ending-style]:scale-95 data-[ending-style]:opacity-0",
|
|
40
|
+
// Ensure it's above other content
|
|
41
|
+
"z-50",
|
|
42
|
+
],
|
|
43
|
+
variants: {
|
|
44
|
+
variant: {
|
|
45
|
+
default: "",
|
|
46
|
+
// Future variants can be added here (e.g., light, primary)
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
variant: "default",
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Tooltip arrow variants - uses shared floating arrow variants
|
|
56
|
+
*/
|
|
57
|
+
const tooltipArrowVariants = floatingArrowVariants;
|
|
58
|
+
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Tooltip Provider
|
|
61
|
+
// ============================================================================
|
|
62
|
+
|
|
63
|
+
export interface TooltipProviderProps extends BaseTooltip.Provider.Props {
|
|
64
|
+
children: React.ReactNode;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Tooltip Provider
|
|
69
|
+
*
|
|
70
|
+
* Manages shared delays across multiple tooltips.
|
|
71
|
+
* Wrap your app or a section with this to enable tooltip delay grouping.
|
|
72
|
+
*/
|
|
73
|
+
const TooltipProvider = ({ children, ...props }: TooltipProviderProps) => {
|
|
74
|
+
return <BaseTooltip.Provider {...props}>{children}</BaseTooltip.Provider>;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Tooltip Root
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
export interface TooltipRootProps extends BaseTooltip.Root.Props {
|
|
82
|
+
children: React.ReactNode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Tooltip Root
|
|
87
|
+
*
|
|
88
|
+
* Groups all tooltip parts. Does not render an element.
|
|
89
|
+
*/
|
|
90
|
+
const TooltipRoot = ({ children, ...props }: TooltipRootProps) => {
|
|
91
|
+
return <BaseTooltip.Root {...props}>{children}</BaseTooltip.Root>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Tooltip Trigger
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
export interface TooltipTriggerProps
|
|
99
|
+
extends React.ComponentProps<typeof BaseTooltip.Trigger> {
|
|
100
|
+
className?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Tooltip Trigger
|
|
105
|
+
*
|
|
106
|
+
* The element that triggers the tooltip on hover/focus.
|
|
107
|
+
* Renders as the child element with tooltip behavior attached.
|
|
108
|
+
* When children is a single React element, uses `render` prop to avoid wrapper element.
|
|
109
|
+
*/
|
|
110
|
+
const TooltipTrigger = React.forwardRef<HTMLButtonElement, TooltipTriggerProps>(
|
|
111
|
+
({ className, children, ...props }, ref) => {
|
|
112
|
+
// If children is a single React element, use render prop to avoid wrapper
|
|
113
|
+
const isSingleElement = React.isValidElement(children);
|
|
114
|
+
|
|
115
|
+
if (isSingleElement) {
|
|
116
|
+
return (
|
|
117
|
+
<BaseTooltip.Trigger
|
|
118
|
+
ref={ref}
|
|
119
|
+
className={className}
|
|
120
|
+
render={children}
|
|
121
|
+
{...props}
|
|
122
|
+
/>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<BaseTooltip.Trigger ref={ref} className={className} {...props}>
|
|
128
|
+
{children}
|
|
129
|
+
</BaseTooltip.Trigger>
|
|
130
|
+
);
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
TooltipTrigger.displayName = "TooltipTrigger";
|
|
134
|
+
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// Tooltip Portal
|
|
137
|
+
// ============================================================================
|
|
138
|
+
|
|
139
|
+
export interface TooltipPortalProps extends BaseTooltip.Portal.Props {
|
|
140
|
+
children: React.ReactNode;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Tooltip Portal
|
|
145
|
+
*
|
|
146
|
+
* Renders the tooltip popup in a portal outside the DOM hierarchy.
|
|
147
|
+
*/
|
|
148
|
+
const TooltipPortal = ({ children, ...props }: TooltipPortalProps) => {
|
|
149
|
+
return <BaseTooltip.Portal {...props}>{children}</BaseTooltip.Portal>;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// Tooltip Positioner
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
export interface TooltipPositionerProps
|
|
157
|
+
extends Omit<
|
|
158
|
+
React.ComponentProps<typeof BaseTooltip.Positioner>,
|
|
159
|
+
"className"
|
|
160
|
+
> {
|
|
161
|
+
className?: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Tooltip Positioner
|
|
166
|
+
*
|
|
167
|
+
* Positions the tooltip popup relative to the trigger.
|
|
168
|
+
*/
|
|
169
|
+
const TooltipPositioner = React.forwardRef<
|
|
170
|
+
HTMLDivElement,
|
|
171
|
+
TooltipPositionerProps
|
|
172
|
+
>(({ className, side = "top", sideOffset = 8, ...props }, ref) => {
|
|
173
|
+
return (
|
|
174
|
+
<BaseTooltip.Positioner
|
|
175
|
+
ref={ref}
|
|
176
|
+
side={side}
|
|
177
|
+
sideOffset={sideOffset}
|
|
178
|
+
className={className}
|
|
179
|
+
{...props}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
TooltipPositioner.displayName = "TooltipPositioner";
|
|
184
|
+
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// Tooltip Popup
|
|
187
|
+
// ============================================================================
|
|
188
|
+
|
|
189
|
+
export interface TooltipPopupProps
|
|
190
|
+
extends Omit<React.ComponentProps<typeof BaseTooltip.Popup>, "className">,
|
|
191
|
+
VariantProps<typeof tooltipPopupVariants> {
|
|
192
|
+
className?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Tooltip Popup
|
|
197
|
+
*
|
|
198
|
+
* The tooltip content container with styled appearance.
|
|
199
|
+
*/
|
|
200
|
+
const TooltipPopup = React.forwardRef<HTMLDivElement, TooltipPopupProps>(
|
|
201
|
+
({ className, variant, ...props }, ref) => {
|
|
202
|
+
return (
|
|
203
|
+
<BaseTooltip.Popup
|
|
204
|
+
ref={ref}
|
|
205
|
+
role="tooltip"
|
|
206
|
+
className={cn(tooltipPopupVariants({ variant }), className)}
|
|
207
|
+
{...props}
|
|
208
|
+
/>
|
|
209
|
+
);
|
|
210
|
+
},
|
|
211
|
+
);
|
|
212
|
+
TooltipPopup.displayName = "TooltipPopup";
|
|
213
|
+
|
|
214
|
+
// ============================================================================
|
|
215
|
+
// Tooltip Arrow
|
|
216
|
+
// ============================================================================
|
|
217
|
+
|
|
218
|
+
export interface TooltipArrowProps
|
|
219
|
+
extends Omit<React.ComponentProps<typeof BaseTooltip.Arrow>, "className"> {
|
|
220
|
+
className?: string;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Tooltip Arrow
|
|
225
|
+
*
|
|
226
|
+
* Visual pointer element for the tooltip.
|
|
227
|
+
* Uses shared FloatingArrowSvg with tooltip-bg color token.
|
|
228
|
+
*/
|
|
229
|
+
const TooltipArrow = React.forwardRef<HTMLDivElement, TooltipArrowProps>(
|
|
230
|
+
({ className, ...props }, ref) => {
|
|
231
|
+
return (
|
|
232
|
+
<BaseTooltip.Arrow
|
|
233
|
+
ref={ref}
|
|
234
|
+
className={cn(tooltipArrowVariants(), className)}
|
|
235
|
+
{...props}
|
|
236
|
+
>
|
|
237
|
+
<FloatingArrowSvg fillClassName="fill-tooltip-bg" />
|
|
238
|
+
</BaseTooltip.Arrow>
|
|
239
|
+
);
|
|
240
|
+
},
|
|
241
|
+
);
|
|
242
|
+
TooltipArrow.displayName = "TooltipArrow";
|
|
243
|
+
|
|
244
|
+
// ============================================================================
|
|
245
|
+
// Simple Tooltip Component
|
|
246
|
+
// ============================================================================
|
|
247
|
+
|
|
248
|
+
export interface TooltipProps {
|
|
249
|
+
/** The content to show in the tooltip */
|
|
250
|
+
content: React.ReactNode;
|
|
251
|
+
/** The element that triggers the tooltip */
|
|
252
|
+
children: React.ReactNode;
|
|
253
|
+
/** Side of the trigger to show the tooltip */
|
|
254
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
255
|
+
/** Offset from the trigger */
|
|
256
|
+
sideOffset?: number;
|
|
257
|
+
/** Alignment along the side */
|
|
258
|
+
align?: "start" | "center" | "end";
|
|
259
|
+
/** Delay before showing the tooltip (ms) */
|
|
260
|
+
delay?: number;
|
|
261
|
+
/** Delay before hiding the tooltip (ms) */
|
|
262
|
+
closeDelay?: number;
|
|
263
|
+
/** Whether to show an arrow */
|
|
264
|
+
showArrow?: boolean;
|
|
265
|
+
/** Controlled open state */
|
|
266
|
+
open?: boolean;
|
|
267
|
+
/** Default open state */
|
|
268
|
+
defaultOpen?: boolean;
|
|
269
|
+
/** Callback when open state changes */
|
|
270
|
+
onOpenChange?: (open: boolean) => void;
|
|
271
|
+
/** Additional className for the popup */
|
|
272
|
+
className?: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Tooltip
|
|
277
|
+
*
|
|
278
|
+
* A simple, pre-composed tooltip component for common use cases.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```tsx
|
|
282
|
+
* <Tooltip content="Save your changes">
|
|
283
|
+
* <Button>Save</Button>
|
|
284
|
+
* </Tooltip>
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
const Tooltip = ({
|
|
288
|
+
content,
|
|
289
|
+
children,
|
|
290
|
+
side = "top",
|
|
291
|
+
sideOffset = 8,
|
|
292
|
+
align = "center",
|
|
293
|
+
delay,
|
|
294
|
+
closeDelay,
|
|
295
|
+
showArrow = true,
|
|
296
|
+
open,
|
|
297
|
+
defaultOpen,
|
|
298
|
+
onOpenChange,
|
|
299
|
+
className,
|
|
300
|
+
}: TooltipProps) => {
|
|
301
|
+
return (
|
|
302
|
+
<TooltipRoot
|
|
303
|
+
open={open}
|
|
304
|
+
defaultOpen={defaultOpen}
|
|
305
|
+
onOpenChange={onOpenChange}
|
|
306
|
+
>
|
|
307
|
+
<TooltipTrigger delay={delay} closeDelay={closeDelay}>
|
|
308
|
+
{children}
|
|
309
|
+
</TooltipTrigger>
|
|
310
|
+
<TooltipPortal>
|
|
311
|
+
<TooltipPositioner side={side} sideOffset={sideOffset} align={align}>
|
|
312
|
+
<TooltipPopup className={className}>
|
|
313
|
+
{showArrow && <TooltipArrow />}
|
|
314
|
+
{content}
|
|
315
|
+
</TooltipPopup>
|
|
316
|
+
</TooltipPositioner>
|
|
317
|
+
</TooltipPortal>
|
|
318
|
+
</TooltipRoot>
|
|
319
|
+
);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
// ============================================================================
|
|
323
|
+
// Compound Component Export
|
|
324
|
+
// ============================================================================
|
|
325
|
+
|
|
326
|
+
export const TooltipParts = Object.assign(TooltipRoot, {
|
|
327
|
+
Provider: TooltipProvider,
|
|
328
|
+
Root: TooltipRoot,
|
|
329
|
+
Trigger: TooltipTrigger,
|
|
330
|
+
Portal: TooltipPortal,
|
|
331
|
+
Positioner: TooltipPositioner,
|
|
332
|
+
Popup: TooltipPopup,
|
|
333
|
+
Arrow: TooltipArrow,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
export {
|
|
337
|
+
Tooltip,
|
|
338
|
+
TooltipProvider,
|
|
339
|
+
TooltipRoot,
|
|
340
|
+
TooltipTrigger,
|
|
341
|
+
TooltipPortal,
|
|
342
|
+
TooltipPositioner,
|
|
343
|
+
TooltipPopup,
|
|
344
|
+
TooltipArrow,
|
|
345
|
+
tooltipPopupVariants,
|
|
346
|
+
tooltipArrowVariants,
|
|
347
|
+
};
|
|
@@ -18,30 +18,25 @@ export default meta;
|
|
|
18
18
|
type Story = StoryObj<typeof meta>;
|
|
19
19
|
|
|
20
20
|
const DemoContent = () => (
|
|
21
|
-
<div className="min-h-screen bg-gray-100 py-
|
|
21
|
+
<div className="min-h-screen bg-gray-100 py-64">
|
|
22
22
|
<div className="w-full max-w-[90rem] mx-auto px-[var(--spatial-grid-small-margin)] md:px-[var(--spatial-grid-medium-margin)] lg:px-[var(--spatial-grid-large-margin)]">
|
|
23
|
-
<h1 className="typography-h2 mb-
|
|
24
|
-
<p className="typography-body-medium text-gray-600 mb-
|
|
23
|
+
<h1 className="typography-h2 mb-16">Dev Toolbar Demo</h1>
|
|
24
|
+
<p className="typography-body-medium text-gray-600 mb-8">
|
|
25
25
|
Click the bar at the bottom to expand, then toggle the Grid overlay.
|
|
26
26
|
</p>
|
|
27
|
-
<p className="typography-body-medium text-gray-600 mb-
|
|
27
|
+
<p className="typography-body-medium text-gray-600 mb-32">
|
|
28
28
|
Keyboard shortcut:{" "}
|
|
29
|
-
<kbd className="px-
|
|
30
|
-
|
|
31
|
-
</kbd>{" "}
|
|
32
|
-
or{" "}
|
|
33
|
-
<kbd className="px-spacing-8 py-spacing-4 bg-gray-200 rounded-radius-8">
|
|
34
|
-
Ctrl+G
|
|
35
|
-
</kbd>
|
|
29
|
+
<kbd className="px-8 py-4 bg-gray-200 rounded-radius-8">⌘G</kbd> or{" "}
|
|
30
|
+
<kbd className="px-8 py-4 bg-gray-200 rounded-radius-8">Ctrl+G</kbd>
|
|
36
31
|
</p>
|
|
37
32
|
|
|
38
33
|
<div className="grid grid-cols-4 md:grid-cols-12 lg:grid-cols-24 gap-[var(--spatial-grid-small-gutter)] md:gap-[var(--spatial-grid-medium-gutter)] lg:gap-[var(--spatial-grid-large-gutter)]">
|
|
39
34
|
{["alpha", "beta", "gamma", "delta", "epsilon", "zeta"].map((id) => (
|
|
40
35
|
<div
|
|
41
36
|
key={id}
|
|
42
|
-
className="col-span-4 md:col-span-4 lg:col-span-8 bg-white p-
|
|
37
|
+
className="col-span-4 md:col-span-4 lg:col-span-8 bg-white p-16 rounded-radius-12 shadow"
|
|
43
38
|
>
|
|
44
|
-
<h3 className="typography-h4 mb-
|
|
39
|
+
<h3 className="typography-h4 mb-8">Card {id}</h3>
|
|
45
40
|
<p className="typography-body-small text-gray-500">
|
|
46
41
|
Sample content to visualize how the grid overlay aligns with your
|
|
47
42
|
layout.
|
|
@@ -152,7 +152,7 @@ export function DevToolbar({ defaultExpanded = false }: DevToolbarProps) {
|
|
|
152
152
|
data-testid="dev-toolbar"
|
|
153
153
|
>
|
|
154
154
|
<div
|
|
155
|
-
className={`bg-gray-1100 rounded-radius-16 shadow-lg flex flex-col items-center overflow-hidden px-
|
|
155
|
+
className={`bg-gray-1100 rounded-radius-16 shadow-lg flex flex-col items-center overflow-hidden px-12 py-8 ${isExpanded ? "gap-4" : ""}`}
|
|
156
156
|
>
|
|
157
157
|
<div
|
|
158
158
|
className={`
|
|
@@ -165,7 +165,7 @@ export function DevToolbar({ defaultExpanded = false }: DevToolbarProps) {
|
|
|
165
165
|
type="button"
|
|
166
166
|
onClick={toggleGrid}
|
|
167
167
|
className={`
|
|
168
|
-
size-
|
|
168
|
+
size-40 rounded-full flex items-center justify-center transition-colors
|
|
169
169
|
${
|
|
170
170
|
showGrid
|
|
171
171
|
? "text-gray-50"
|
|
@@ -186,7 +186,7 @@ export function DevToolbar({ defaultExpanded = false }: DevToolbarProps) {
|
|
|
186
186
|
onTouchStart={handleBarTouchStart}
|
|
187
187
|
onClick={handleBarClick}
|
|
188
188
|
className={`
|
|
189
|
-
w-
|
|
189
|
+
w-32 h-4 bg-gray-50 rounded-full transition-opacity
|
|
190
190
|
${isDragging ? "opacity-100 cursor-grabbing" : "opacity-60 hover:opacity-100 cursor-grab"}
|
|
191
191
|
`}
|
|
192
192
|
aria-label={isExpanded ? "Close dev tools" : "Open dev tools"}
|
|
@@ -34,7 +34,7 @@ export const Default: Story = {
|
|
|
34
34
|
<CardContent>
|
|
35
35
|
<CardBody>
|
|
36
36
|
<CardEyebrow>Optional Eyebrow</CardEyebrow>
|
|
37
|
-
<div className="flex flex-col gap-
|
|
37
|
+
<div className="flex flex-col gap-6">
|
|
38
38
|
<CardTitle>Card Title</CardTitle>
|
|
39
39
|
<CardDescription>
|
|
40
40
|
Use cards when citizens need to scan items at a glance, either
|
|
@@ -43,10 +43,10 @@ export const Default: Story = {
|
|
|
43
43
|
</div>
|
|
44
44
|
</CardBody>
|
|
45
45
|
<CardActions>
|
|
46
|
-
<Button size="
|
|
46
|
+
<Button size="md" variant="primary">
|
|
47
47
|
Primary
|
|
48
48
|
</Button>
|
|
49
|
-
<Button size="
|
|
49
|
+
<Button size="md" variant="primary-outline">
|
|
50
50
|
Secondary
|
|
51
51
|
</Button>
|
|
52
52
|
</CardActions>
|
|
@@ -68,7 +68,7 @@ export const Vertical: Story = {
|
|
|
68
68
|
<CardContent>
|
|
69
69
|
<CardBody>
|
|
70
70
|
<CardEyebrow>Optional Eyebrow</CardEyebrow>
|
|
71
|
-
<div className="flex flex-col gap-
|
|
71
|
+
<div className="flex flex-col gap-6">
|
|
72
72
|
<CardTitle>Card Title</CardTitle>
|
|
73
73
|
<CardDescription>
|
|
74
74
|
Use cards when citizens need to scan items at a glance, either
|
|
@@ -77,10 +77,10 @@ export const Vertical: Story = {
|
|
|
77
77
|
</div>
|
|
78
78
|
</CardBody>
|
|
79
79
|
<CardActions>
|
|
80
|
-
<Button size="
|
|
80
|
+
<Button size="md" variant="primary">
|
|
81
81
|
Primary
|
|
82
82
|
</Button>
|
|
83
|
-
<Button size="
|
|
83
|
+
<Button size="md" variant="primary-outline">
|
|
84
84
|
Secondary
|
|
85
85
|
</Button>
|
|
86
86
|
</CardActions>
|
|
@@ -98,7 +98,7 @@ export const Horizontal: Story = {
|
|
|
98
98
|
<CardContent>
|
|
99
99
|
<CardBody>
|
|
100
100
|
<CardEyebrow>Eyebrow</CardEyebrow>
|
|
101
|
-
<div className="flex flex-col gap-
|
|
101
|
+
<div className="flex flex-col gap-8">
|
|
102
102
|
<CardTitle>
|
|
103
103
|
Cards can support multi line headings easily.
|
|
104
104
|
</CardTitle>
|
|
@@ -109,10 +109,10 @@ export const Horizontal: Story = {
|
|
|
109
109
|
</div>
|
|
110
110
|
</CardBody>
|
|
111
111
|
<CardActions>
|
|
112
|
-
<Button size="sm" variant="
|
|
112
|
+
<Button size="sm" variant="primary">
|
|
113
113
|
Primary
|
|
114
114
|
</Button>
|
|
115
|
-
<Button size="sm" variant="outline">
|
|
115
|
+
<Button size="sm" variant="primary-outline">
|
|
116
116
|
Secondary
|
|
117
117
|
</Button>
|
|
118
118
|
</CardActions>
|
|
@@ -133,7 +133,7 @@ export const WithoutImage: Story = {
|
|
|
133
133
|
<CardContent>
|
|
134
134
|
<CardBody>
|
|
135
135
|
<CardEyebrow>Category</CardEyebrow>
|
|
136
|
-
<div className="flex flex-col gap-
|
|
136
|
+
<div className="flex flex-col gap-6">
|
|
137
137
|
<CardTitle>Card Without Image</CardTitle>
|
|
138
138
|
<CardDescription>
|
|
139
139
|
Cards can be used without images for text-focused content.
|
|
@@ -141,7 +141,7 @@ export const WithoutImage: Story = {
|
|
|
141
141
|
</div>
|
|
142
142
|
</CardBody>
|
|
143
143
|
<CardActions>
|
|
144
|
-
<Button size="
|
|
144
|
+
<Button size="md" variant="primary">
|
|
145
145
|
Learn More
|
|
146
146
|
</Button>
|
|
147
147
|
</CardActions>
|
|
@@ -158,7 +158,7 @@ export const WithoutEyebrow: Story = {
|
|
|
158
158
|
<CardImage />
|
|
159
159
|
<CardContent>
|
|
160
160
|
<CardBody>
|
|
161
|
-
<div className="flex flex-col gap-
|
|
161
|
+
<div className="flex flex-col gap-6">
|
|
162
162
|
<CardTitle>Card Title</CardTitle>
|
|
163
163
|
<CardDescription>
|
|
164
164
|
The eyebrow is optional and can be omitted when not needed.
|
|
@@ -166,7 +166,7 @@ export const WithoutEyebrow: Story = {
|
|
|
166
166
|
</div>
|
|
167
167
|
</CardBody>
|
|
168
168
|
<CardActions>
|
|
169
|
-
<Button size="
|
|
169
|
+
<Button size="md" variant="primary">
|
|
170
170
|
Primary
|
|
171
171
|
</Button>
|
|
172
172
|
</CardActions>
|
|
@@ -184,7 +184,7 @@ export const WithoutActions: Story = {
|
|
|
184
184
|
<CardContent>
|
|
185
185
|
<CardBody>
|
|
186
186
|
<CardEyebrow>Information</CardEyebrow>
|
|
187
|
-
<div className="flex flex-col gap-
|
|
187
|
+
<div className="flex flex-col gap-6">
|
|
188
188
|
<CardTitle>Informational Card</CardTitle>
|
|
189
189
|
<CardDescription>
|
|
190
190
|
Cards without actions can be used for purely informational
|
|
@@ -228,7 +228,7 @@ export const CardGrid: Story = {
|
|
|
228
228
|
<CardContent>
|
|
229
229
|
<CardBody>
|
|
230
230
|
<CardEyebrow>Category {i}</CardEyebrow>
|
|
231
|
-
<div className="flex flex-col gap-
|
|
231
|
+
<div className="flex flex-col gap-6">
|
|
232
232
|
<CardTitle>Card Title {i}</CardTitle>
|
|
233
233
|
<CardDescription>
|
|
234
234
|
Brief description of the card content goes here.
|
|
@@ -236,7 +236,7 @@ export const CardGrid: Story = {
|
|
|
236
236
|
</div>
|
|
237
237
|
</CardBody>
|
|
238
238
|
<CardActions>
|
|
239
|
-
<Button size="sm" variant="
|
|
239
|
+
<Button size="sm" variant="primary">
|
|
240
240
|
Action
|
|
241
241
|
</Button>
|
|
242
242
|
</CardActions>
|
|
@@ -262,7 +262,7 @@ export const Playground: Story = {
|
|
|
262
262
|
<CardContent>
|
|
263
263
|
<CardBody>
|
|
264
264
|
<CardEyebrow>Eyebrow</CardEyebrow>
|
|
265
|
-
<div className="flex flex-col gap-
|
|
265
|
+
<div className="flex flex-col gap-6">
|
|
266
266
|
<CardTitle>Card Title</CardTitle>
|
|
267
267
|
<CardDescription>
|
|
268
268
|
Use cards when citizens need to scan items at a glance.
|
|
@@ -270,10 +270,10 @@ export const Playground: Story = {
|
|
|
270
270
|
</div>
|
|
271
271
|
</CardBody>
|
|
272
272
|
<CardActions>
|
|
273
|
-
<Button size="
|
|
273
|
+
<Button size="md" variant="primary">
|
|
274
274
|
Primary
|
|
275
275
|
</Button>
|
|
276
|
-
<Button size="
|
|
276
|
+
<Button size="md" variant="primary-outline">
|
|
277
277
|
Secondary
|
|
278
278
|
</Button>
|
|
279
279
|
</CardActions>
|
|
@@ -240,7 +240,7 @@ const CardBody = React.forwardRef<HTMLDivElement, CardBodyProps>(
|
|
|
240
240
|
CardBody.displayName = "CardBody";
|
|
241
241
|
|
|
242
242
|
const cardActionsVariants = tv({
|
|
243
|
-
base: "flex gap-
|
|
243
|
+
base: "flex gap-12",
|
|
244
244
|
});
|
|
245
245
|
|
|
246
246
|
export interface CardActionsProps
|
|
@@ -24,7 +24,7 @@ describe("Card Visual Regression", () => {
|
|
|
24
24
|
<CardContent>
|
|
25
25
|
<CardBody>
|
|
26
26
|
<CardEyebrow>Optional Eyebrow</CardEyebrow>
|
|
27
|
-
<div className="flex flex-col gap-
|
|
27
|
+
<div className="flex flex-col gap-6">
|
|
28
28
|
<CardTitle>Card Title</CardTitle>
|
|
29
29
|
<CardDescription>
|
|
30
30
|
Use cards when citizens need to scan items at a glance.
|
|
@@ -32,10 +32,10 @@ describe("Card Visual Regression", () => {
|
|
|
32
32
|
</div>
|
|
33
33
|
</CardBody>
|
|
34
34
|
<CardActions>
|
|
35
|
-
<Button size="
|
|
35
|
+
<Button size="md" variant="primary">
|
|
36
36
|
Primary
|
|
37
37
|
</Button>
|
|
38
|
-
<Button size="
|
|
38
|
+
<Button size="md" variant="primary-outline">
|
|
39
39
|
Secondary
|
|
40
40
|
</Button>
|
|
41
41
|
</CardActions>
|
|
@@ -59,7 +59,7 @@ describe("Card Visual Regression", () => {
|
|
|
59
59
|
<CardContent>
|
|
60
60
|
<CardBody>
|
|
61
61
|
<CardEyebrow>Eyebrow</CardEyebrow>
|
|
62
|
-
<div className="flex flex-col gap-
|
|
62
|
+
<div className="flex flex-col gap-8">
|
|
63
63
|
<CardTitle>
|
|
64
64
|
Cards can support multi line headings easily.
|
|
65
65
|
</CardTitle>
|
|
@@ -69,10 +69,10 @@ describe("Card Visual Regression", () => {
|
|
|
69
69
|
</div>
|
|
70
70
|
</CardBody>
|
|
71
71
|
<CardActions>
|
|
72
|
-
<Button size="sm" variant="
|
|
72
|
+
<Button size="sm" variant="primary">
|
|
73
73
|
Primary
|
|
74
74
|
</Button>
|
|
75
|
-
<Button size="sm" variant="outline">
|
|
75
|
+
<Button size="sm" variant="primary-outline">
|
|
76
76
|
Secondary
|
|
77
77
|
</Button>
|
|
78
78
|
</CardActions>
|
|
@@ -93,7 +93,7 @@ describe("Card Visual Regression", () => {
|
|
|
93
93
|
<CardContent>
|
|
94
94
|
<CardBody>
|
|
95
95
|
<CardEyebrow>Category</CardEyebrow>
|
|
96
|
-
<div className="flex flex-col gap-
|
|
96
|
+
<div className="flex flex-col gap-6">
|
|
97
97
|
<CardTitle>Card Without Image</CardTitle>
|
|
98
98
|
<CardDescription>
|
|
99
99
|
Cards can be used without images for text-focused content.
|
|
@@ -101,7 +101,7 @@ describe("Card Visual Regression", () => {
|
|
|
101
101
|
</div>
|
|
102
102
|
</CardBody>
|
|
103
103
|
<CardActions>
|
|
104
|
-
<Button size="
|
|
104
|
+
<Button size="md" variant="primary">
|
|
105
105
|
Learn More
|
|
106
106
|
</Button>
|
|
107
107
|
</CardActions>
|
|
@@ -124,7 +124,7 @@ describe("Card Visual Regression", () => {
|
|
|
124
124
|
<CardImage />
|
|
125
125
|
<CardContent>
|
|
126
126
|
<CardBody>
|
|
127
|
-
<div className="flex flex-col gap-
|
|
127
|
+
<div className="flex flex-col gap-6">
|
|
128
128
|
<CardTitle>Card Title</CardTitle>
|
|
129
129
|
<CardDescription>
|
|
130
130
|
The eyebrow is optional and can be omitted when not needed.
|
|
@@ -132,7 +132,7 @@ describe("Card Visual Regression", () => {
|
|
|
132
132
|
</div>
|
|
133
133
|
</CardBody>
|
|
134
134
|
<CardActions>
|
|
135
|
-
<Button size="
|
|
135
|
+
<Button size="md" variant="primary">
|
|
136
136
|
Primary
|
|
137
137
|
</Button>
|
|
138
138
|
</CardActions>
|
|
@@ -156,7 +156,7 @@ describe("Card Visual Regression", () => {
|
|
|
156
156
|
<CardContent>
|
|
157
157
|
<CardBody>
|
|
158
158
|
<CardEyebrow>Information</CardEyebrow>
|
|
159
|
-
<div className="flex flex-col gap-
|
|
159
|
+
<div className="flex flex-col gap-6">
|
|
160
160
|
<CardTitle>Informational Card</CardTitle>
|
|
161
161
|
<CardDescription>
|
|
162
162
|
Cards without actions can be used for purely informational
|
|
@@ -26,7 +26,7 @@ describe("Navbar Visual Regression", () => {
|
|
|
26
26
|
<NavbarLink href="#">Contact</NavbarLink>
|
|
27
27
|
</NavbarLinks>
|
|
28
28
|
<NavbarActions>
|
|
29
|
-
<Button size="sm" variant="
|
|
29
|
+
<Button size="sm" variant="primary">
|
|
30
30
|
Sign In
|
|
31
31
|
</Button>
|
|
32
32
|
</NavbarActions>
|
|
@@ -55,7 +55,7 @@ describe("Navbar Visual Regression", () => {
|
|
|
55
55
|
<NavbarLink href="#">Contact</NavbarLink>
|
|
56
56
|
</NavbarLinks>
|
|
57
57
|
<NavbarActions>
|
|
58
|
-
<Button size="sm" variant="
|
|
58
|
+
<Button size="sm" variant="primary">
|
|
59
59
|
Sign In
|
|
60
60
|
</Button>
|
|
61
61
|
</NavbarActions>
|
|
@@ -3,8 +3,8 @@ import { tv, type VariantProps } from "tailwind-variants";
|
|
|
3
3
|
|
|
4
4
|
const usGovBannerVariants = tv({
|
|
5
5
|
slots: {
|
|
6
|
-
root: "flex w-full items-center justify-center py-
|
|
7
|
-
content: "flex items-center gap-
|
|
6
|
+
root: "flex w-full items-center justify-center py-12",
|
|
7
|
+
content: "flex items-center gap-8",
|
|
8
8
|
text: "text-[11px] leading-[13px] tracking-[0.17px]",
|
|
9
9
|
},
|
|
10
10
|
variants: {
|