atlas-react-kit 0.4.1 → 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/COMPONENTS.md +122 -39
- package/DESIGN_RULES.md +61 -17
- package/README.md +56 -10
- package/dist/accordion.d.ts +8 -0
- package/dist/accordion.js +20 -0
- package/dist/alert.d.ts +19 -0
- package/dist/alert.js +37 -0
- package/dist/avatar.d.ts +9 -0
- package/dist/avatar.js +16 -0
- package/dist/badge.d.ts +2 -2
- package/dist/breadcrumb.d.ts +16 -0
- package/dist/breadcrumb.js +33 -0
- package/dist/button.d.ts +6 -5
- package/dist/button.js +6 -5
- package/dist/calendar.d.ts +1 -1
- package/dist/calendar.js +19 -1
- package/dist/combobox.d.ts +4 -1
- package/dist/combobox.js +10 -5
- package/dist/date-picker.js +14 -3
- package/dist/date-time-picker.d.ts +36 -0
- package/dist/date-time-picker.js +105 -0
- package/dist/dropdown-menu.d.ts +26 -0
- package/dist/dropdown-menu.js +56 -0
- package/dist/error-boundary.d.ts +1 -1
- package/dist/field.js +1 -1
- package/dist/form/date-time-picker-field.d.ts +16 -0
- package/dist/form/date-time-picker-field.js +12 -0
- package/dist/form/text-field.d.ts +7 -1
- package/dist/form/text-field.js +3 -3
- package/dist/pagination.d.ts +18 -0
- package/dist/pagination.js +35 -0
- package/dist/progress.d.ts +8 -0
- package/dist/progress.js +13 -0
- package/dist/radio-group.d.ts +13 -0
- package/dist/radio-group.js +20 -0
- package/dist/spinner.d.ts +8 -0
- package/dist/spinner.js +13 -0
- package/dist/switch.d.ts +9 -0
- package/dist/switch.js +14 -0
- package/dist/table.d.ts +2 -0
- package/dist/table.js +25 -1
- package/dist/tabs.d.ts +6 -3
- package/dist/tabs.js +5 -2
- package/dist/theme-provider.d.ts +2 -1
- package/dist/theme-provider.js +28 -4
- package/dist/toggle.js +1 -1
- package/dist/tooltip.d.ts +15 -0
- package/dist/tooltip.js +26 -0
- package/package.json +58 -5
- package/skills/atlas-react-kit/SKILL.md +139 -0
- package/theme.css +5 -5
package/COMPONENTS.md
CHANGED
|
@@ -5,39 +5,64 @@ underlying element or Radix props, including `className`, alongside their option
|
|
|
5
5
|
Form helpers and `TableBodySkeleton` accept only their documented props. There is
|
|
6
6
|
no root component barrel.
|
|
7
7
|
|
|
8
|
-
| Subpath
|
|
9
|
-
|
|
|
10
|
-
| `
|
|
11
|
-
| `
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
8
|
+
| Subpath | Main exports and options |
|
|
9
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
10
|
+
| `accordion` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`; Radix `type` `single` (with `collapsible`) or `multiple` |
|
|
11
|
+
| `alert` | `Alert`, `AlertTitle`, `AlertDescription`, `alertVariants`; `variant` `default`, `success`, `warning`, `destructive`; tone on title and icon, body stays muted; destructive is `role="alert"` |
|
|
12
|
+
| `avatar` | `Avatar`, `AvatarImage`, `AvatarFallback`; `size` `sm`, `default`, `lg`; round by design |
|
|
13
|
+
| `breadcrumb` | `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink` (`asChild` for router links), `BreadcrumbPage` (`aria-current`), `BreadcrumbSeparator`, `BreadcrumbEllipsis` |
|
|
14
|
+
| `button` | `Button`, `buttonVariants`, `quietButtonInteraction`; `variant`, `size`, `asChild`; outline/ghost hover is brand purple + selected wash, not muted grey |
|
|
15
|
+
| `badge` | `Badge`, `badgeVariants`; `variant`, `tone`, `asChild` |
|
|
16
|
+
| `calendar` | `Calendar`, `CalendarDayButton`; React Day Picker props and `buttonVariant` |
|
|
17
|
+
| `card` | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardAction`, `CardContent`, `CardFooter`; `Card` supports `flush`; root uses `min-h-min shrink-0` so flex columns do not collapse it, and `min-w-0` so nested tables scroll; `CardContent className="px-0"` overrides padding without `!` |
|
|
18
|
+
| `checkbox` | `Checkbox` |
|
|
19
|
+
| `combobox` | `Combobox`; `options` as `{ value, label }[]`, `value`, `onValueChange`; optional placeholder, search, empty text; trigger matches Input/SelectTrigger chrome; keyboard highlight scrolls into view |
|
|
20
|
+
| `date-picker` | `DatePickerButton`, `toDate`, `formatLocalDate`, `DateRange`; `mode` `"single"` (default) or `"range"`; single `value` is `Date` or `yyyy-MM-dd`; range `value` is `{ from, to }`; trigger matches Input chrome; optional `numberOfMonths` (range default 1 below `md`, 2 at `md+`) and `side` |
|
|
21
|
+
| `date-time-picker` | `DateTimePickerButton`, `resolveTimeStep`, `DEFAULT_TIME_STEP`; controlled `value` is `Date` or `null`; `onChange` emits `Date \ |
|
|
22
|
+
| `dialog` | `Dialog`, trigger, portal, overlay, content, close, header, footer, title, description; `DialogContent` supports `showCloseButton` |
|
|
23
|
+
| `dropdown-menu` | `DropdownMenu` family (trigger, content, item, checkbox/radio items, label, separator, shortcut, sub menus); item `variant="destructive"` and `inset`; for commands, not values |
|
|
24
|
+
| `empty-panel` | `EmptyPanel`; required `children`; optional `size`, `muted`, `className` |
|
|
25
|
+
| `error-boundary` | `ErrorBoundary`, `ErrorFallback`; optional `message`; retry resets, reload refreshes the page |
|
|
26
|
+
| `field` | Field, label, legend, description, group, set, title, content, separator, error; `Field` supports `orientation` |
|
|
27
|
+
| `input`, `textarea`, `label` | `Input`, `Textarea`, `Label` |
|
|
28
|
+
| `pagination` | `Pagination`, `PaginationContent`, `PaginationItem`, `PaginationLink` (`isActive` sets `aria-current` and the selected wash), `PaginationPrevious`, `PaginationNext`, `PaginationEllipsis` |
|
|
29
|
+
| `popover` | `Popover`, trigger, anchor, content, header, title, description |
|
|
30
|
+
| `progress` | `Progress`; Radix props, `value` 0–100; label it with `aria-label` or `aria-labelledby` |
|
|
31
|
+
| `radio-group` | `RadioGroup`, `RadioGroupItem`; short visible lists; arrow keys move the selection; round dots |
|
|
32
|
+
| `select` | Select, trigger, value, content, group, label, item, separator, scroll buttons; trigger `size`; trigger text is `text-base md:text-sm` like Input |
|
|
33
|
+
| `separator`, `skeleton` | `Separator`, `Skeleton` |
|
|
34
|
+
| `sortable-table-head` | `SortableTableHead`; `sorted`, `direction` (`asc` \ |
|
|
35
|
+
| `sonner` | `Toaster`; Sonner props, with `next-themes` theme defaults |
|
|
36
|
+
| `spinner` | `Spinner`; `role="status"` with `aria-label` (default `Loading`) |
|
|
37
|
+
| `switch` | `Switch`; settings that apply immediately; square track and thumb |
|
|
38
|
+
| `table` | Table, header, body, footer, row, head, cell, caption; root scroller is `min-w-0 overflow-x-auto` with a fade cue; cells are `px-2` below `sm` |
|
|
39
|
+
| `table-body-skeleton` | `TableBodySkeleton`; `columns`, optional `rows` (default 5) |
|
|
40
|
+
| `tabs` | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`, `TabsNav`, `tabsListVariants`, `tabsTriggerVariants`; list `variant` is `default` or `line`; style `TabsNav` links with `tabsTriggerVariants()` |
|
|
41
|
+
| `toggle` | `Toggle`, `toggleVariants`; `variant`, `size` |
|
|
42
|
+
| `toggle-group` | `ToggleGroup`, `ToggleGroupItem`; `variant`, `size` |
|
|
43
|
+
| `theme-provider` | `ThemeProvider`, `useTheme`; optional `storageKey` (default `atlas-theme`), `enableShortcut` for the `d` toggle |
|
|
44
|
+
| `tooltip` | `Tooltip`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider`; opens on hover and focus; short labels only |
|
|
45
|
+
| `form/text-field` | `FormTextField`, type `TextFieldApi`; controlled field, label, multiline, description, input constraints |
|
|
46
|
+
| `form/select-field` | `FormSelectField`; `value`, `onValueChange`, `label`, optional `meta` and placeholder; select item children |
|
|
47
|
+
| `form/date-picker-field` | `FormDatePickerField`; `value`, `onValueChange`, `label`, optional `meta`, placeholder, and `className` (forwarded to the trigger) |
|
|
48
|
+
| `form/date-time-picker-field` | `FormDateTimePickerField`; `value` is `Date` or `null`; `onValueChange` emits `Date \ |
|
|
49
|
+
| `form/field-error` | `FieldError`, `getFieldErrorMessage`; types `FieldErrorMessage`, `FieldMetaState` |
|
|
50
|
+
| `form/feedback-field` | `FormFeedbackField`; nullable `message` |
|
|
51
|
+
| `next/tabs-nav-link` | `TabsNavLink`; Next Link props and required `active` boolean; requires Next.js 16 |
|
|
52
|
+
| `utils` | `cn`, `onInputChange` |
|
|
53
|
+
| `theme.css` | Tailwind 4 theme; installation in [README](./README.md) |
|
|
54
|
+
|
|
55
|
+
## Status
|
|
56
|
+
|
|
57
|
+
Components are **stable** unless listed here. Stable components change
|
|
58
|
+
through the deprecation policy in
|
|
59
|
+
[CONTRIBUTING.md](https://github.com/Kerubi-5/atlas-design-system/blob/main/CONTRIBUTING.md):
|
|
60
|
+
a deprecation notice first, removal in a later minor release.
|
|
61
|
+
|
|
62
|
+
**Beta** components may still change shape in a minor release; the
|
|
63
|
+
changelog calls out every change: `accordion`, `alert`, `avatar`,
|
|
64
|
+
`breadcrumb`, `date-time-picker`, `dropdown-menu`, `pagination`, `progress`,
|
|
65
|
+
`radio-group`, `spinner`, `switch`, `tooltip`.
|
|
41
66
|
|
|
42
67
|
## Forms
|
|
43
68
|
|
|
@@ -57,10 +82,12 @@ type TextFieldApi = {
|
|
|
57
82
|
|
|
58
83
|
`FormTextField` accepts `field` and `label`; use `multiline` and `rows` for a
|
|
59
84
|
textarea, `inputType` for a specific input, and `showError={false}` to suppress
|
|
60
|
-
error text and invalid styling. `FormSelectField` and
|
|
61
|
-
accept the same error meta shape.
|
|
62
|
-
`yyyy-MM-dd` string and calls
|
|
63
|
-
`
|
|
85
|
+
error text and invalid styling. `FormSelectField`, `FormDatePickerField`, and
|
|
86
|
+
`FormDateTimePickerField` accept the same error meta shape.
|
|
87
|
+
`FormDatePickerField` takes a `Date` or `yyyy-MM-dd` string and calls
|
|
88
|
+
`onValueChange` with `Date | undefined`. `FormDateTimePickerField` takes a
|
|
89
|
+
`Date` or `null` and calls `onValueChange` with `Date | null`. `FieldError`
|
|
90
|
+
accepts either `message` or pre-resolved `text`.
|
|
64
91
|
|
|
65
92
|
`DatePickerButton` is single-day by default. For a from/to range, set
|
|
66
93
|
`mode="range"`; `value` is `{ from, to }` (each side `Date` or `yyyy-MM-dd`)
|
|
@@ -72,10 +99,41 @@ it does not collapse to the default popover width, and includes a Clear
|
|
|
72
99
|
action. Pass `side` to prefer a placement; Radix still flips on collision.
|
|
73
100
|
`FormDatePickerField` forwards `className` to that trigger.
|
|
74
101
|
|
|
102
|
+
`DateTimePickerButton` is the date-and-time control. `value` is a `Date` or
|
|
103
|
+
`null`; `onChange` receives `Date | null`. The trigger matches the same
|
|
104
|
+
form-control chrome. The popover is one month, a labelled Hour and Minute
|
|
105
|
+
pair (24-hour, stepped by `timeStep`, default 15), and Clear. Picking a day
|
|
106
|
+
keeps the popover open so the time can be set; the time selects stay
|
|
107
|
+
disabled until a day is chosen. The panel is `w-auto`, viewport-clamped, and
|
|
108
|
+
capped at `min(100vw - 2rem, 24rem)` so it stays on-screen at 390px. Pass
|
|
109
|
+
`side` to prefer a placement. `FormDateTimePickerField` forwards `className`
|
|
110
|
+
and `timeStep` to that control.
|
|
111
|
+
|
|
75
112
|
Outline and ghost `Button` hover and focus use `border-primary`,
|
|
76
|
-
`text-
|
|
113
|
+
`text-selected-foreground`, and `bg-selected`. They do not use a muted grey fill, including
|
|
77
114
|
when the control sits on a selected row (for example "Clear selection").
|
|
78
115
|
|
|
116
|
+
```tsx
|
|
117
|
+
import { DateTimePickerButton } from "atlas-react-kit/date-time-picker"
|
|
118
|
+
|
|
119
|
+
export function EventStarts({
|
|
120
|
+
value,
|
|
121
|
+
onChange,
|
|
122
|
+
}: {
|
|
123
|
+
value: Date | null
|
|
124
|
+
onChange: (date: Date | null) => void
|
|
125
|
+
}) {
|
|
126
|
+
return (
|
|
127
|
+
<DateTimePickerButton
|
|
128
|
+
value={value}
|
|
129
|
+
onChange={onChange}
|
|
130
|
+
timeStep={15}
|
|
131
|
+
placeholder="Pick a date and time"
|
|
132
|
+
/>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
79
137
|
```tsx
|
|
80
138
|
import { DatePickerButton, type DateRange } from "atlas-react-kit/date-picker"
|
|
81
139
|
|
|
@@ -136,7 +194,32 @@ export function ViewSwitcher({ view }: { view: string }) {
|
|
|
136
194
|
}
|
|
137
195
|
```
|
|
138
196
|
|
|
139
|
-
Outside Next, compose `TabsNav` with your own links
|
|
197
|
+
Outside Next, compose `TabsNav` with your own links: style each one with
|
|
198
|
+
`tabsTriggerVariants()` and set `data-state="active"` plus `aria-current="page"`
|
|
199
|
+
on the active link.
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import { TabsNav, tabsTriggerVariants } from "atlas-react-kit/tabs"
|
|
203
|
+
|
|
204
|
+
export function ViewSwitcher({ view }: { view: string }) {
|
|
205
|
+
return (
|
|
206
|
+
<TabsNav aria-label="Items view">
|
|
207
|
+
{["list", "board"].map((item) => (
|
|
208
|
+
<a
|
|
209
|
+
key={item}
|
|
210
|
+
href={`?view=${item}`}
|
|
211
|
+
data-state={view === item ? "active" : "inactive"}
|
|
212
|
+
aria-current={view === item ? "page" : undefined}
|
|
213
|
+
className={tabsTriggerVariants()}
|
|
214
|
+
>
|
|
215
|
+
{item}
|
|
216
|
+
</a>
|
|
217
|
+
))}
|
|
218
|
+
</TabsNav>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
140
223
|
Hook-driven controls and form handlers declare their client boundary; presentational
|
|
141
224
|
modules such as `button`, `badge`, `card`, and `skeleton` can be composed from
|
|
142
225
|
React Server Components. Pass interactive callbacks from client components.
|
package/DESIGN_RULES.md
CHANGED
|
@@ -12,16 +12,60 @@ light/dark color pairs; tokens already switch with the theme.
|
|
|
12
12
|
|
|
13
13
|
Selected or active navigation, tabs, toggles, chips, rows, and labels use
|
|
14
14
|
`bg-selected text-selected-foreground`. Outline and ghost buttons hover and
|
|
15
|
-
focus with `border-primary text-
|
|
16
|
-
grey fill. Table row hover can stay `hover:bg-muted`. The shipped
|
|
17
|
-
apply this distinction.
|
|
15
|
+
focus with `border-primary`, `text-selected-foreground`, and the selected wash,
|
|
16
|
+
not a muted grey fill. Table row hover can stay `hover:bg-muted`. The shipped
|
|
17
|
+
controls apply this distinction.
|
|
18
|
+
|
|
19
|
+
For brand-colored text (links, hovered labels), use `text-selected-foreground`:
|
|
20
|
+
it is the primary purple in light mode and a lighter purple in dark mode.
|
|
21
|
+
`text-primary` as text fails contrast on the dark background (about 2:1).
|
|
18
22
|
|
|
19
23
|
Use `success`, `warning`, and `destructive` for good, caution, and bad states.
|
|
20
|
-
For tinted status chips, use `Badge variant="soft" tone="success"
|
|
21
|
-
`
|
|
22
|
-
own
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
For tinted status chips, use `Badge variant="soft"` with `tone="success"`,
|
|
25
|
+
`"warning"`, or `"destructive"`; each meets AA as text on the page, a card, and
|
|
26
|
+
its own soft tint in both themes. Status tones have no paired foreground token;
|
|
27
|
+
avoid placing text on solid status fills. Application-specific identity colors
|
|
28
|
+
belong to the application.
|
|
29
|
+
|
|
30
|
+
## Accessibility
|
|
31
|
+
|
|
32
|
+
The target is WCAG 2.2 AA. CI runs axe-core's WCAG 2.2 A and AA rules against
|
|
33
|
+
every Storybook story in light and dark mode (`npm run test:a11y --prefix
|
|
34
|
+
site`), and a violation fails the build. Automated checks do not replace
|
|
35
|
+
keyboard and screen-reader testing.
|
|
36
|
+
|
|
37
|
+
- Text meets 4.5:1 against its background. The token pairs are tuned for it,
|
|
38
|
+
including `text-muted-foreground` on `bg-muted` and status text on its soft
|
|
39
|
+
tint; raw colors and opacity tricks are where contrast breaks.
|
|
40
|
+
- Every control has an accessible name: a `Label` with `htmlFor`, or
|
|
41
|
+
`aria-label` on icon-only buttons and an unlabelled `Combobox`.
|
|
42
|
+
- Visible text is part of the accessible name, so speech users can say what
|
|
43
|
+
they see (the calendar labels days "September 27", not "27th").
|
|
44
|
+
- Keep the focus rings the kit ships. Content that scrolls must be reachable
|
|
45
|
+
by keyboard; `Table` adds itself to the tab order while it overflows.
|
|
46
|
+
|
|
47
|
+
## Writing
|
|
48
|
+
|
|
49
|
+
Write labels and messages in sentence case; components that display uppercase
|
|
50
|
+
(buttons, card and dialog titles, badges) apply it with CSS, so screen readers
|
|
51
|
+
still read normal words.
|
|
52
|
+
|
|
53
|
+
- **Buttons** say what happens: a verb and, when needed, a noun ("Save",
|
|
54
|
+
"Export orders", "Delete order"). Avoid "OK", "Submit", and "Click here".
|
|
55
|
+
In a confirmation dialog, the confirm button repeats the action from the
|
|
56
|
+
title ("Delete order?" / "Delete order").
|
|
57
|
+
- **Errors** say what happened and what to do next, in plain words: "Could
|
|
58
|
+
not save. Check your connection and try again." Don't blame the user or
|
|
59
|
+
show only a code. Field errors name the fix: "Enter an email address like
|
|
60
|
+
name@company.com."
|
|
61
|
+
- **Empty states** say what will appear and how to add the first one: "No
|
|
62
|
+
orders yet. Orders you create show up here."
|
|
63
|
+
- **Toasts** confirm in past tense and stay short ("Settings saved"). Anything
|
|
64
|
+
the user must act on belongs in an `Alert` or dialog, not a toast.
|
|
65
|
+
- **Placeholders** show an example, never the label; every field keeps a
|
|
66
|
+
visible `Label`.
|
|
67
|
+
- Skip "please", exclamation marks, and filler ("Successfully saved" is
|
|
68
|
+
"Saved"). Use numerals, and `tabular-nums` where numbers line up in columns.
|
|
25
69
|
|
|
26
70
|
## Shape and composition
|
|
27
71
|
|
|
@@ -39,19 +83,19 @@ column, and `min-w-0` so nested tables scroll instead of widening the card.
|
|
|
39
83
|
`Dialog` already scrolls inside the viewport on small screens; avoid
|
|
40
84
|
additional height limits.
|
|
41
85
|
|
|
42
|
-
`Input`, `SelectTrigger`, `DatePickerButton`,
|
|
43
|
-
chrome: 40px height, `px-3`,
|
|
44
|
-
`shadow-xs`. Do not restyle those
|
|
45
|
-
code.
|
|
86
|
+
`Input`, `SelectTrigger`, `DatePickerButton`, `DateTimePickerButton`, and
|
|
87
|
+
`Combobox` share form-control chrome: 40px height, `px-3`,
|
|
88
|
+
`text-base md:text-sm`, `border-input`, and `shadow-xs`. Do not restyle those
|
|
89
|
+
triggers as outline buttons in application code.
|
|
46
90
|
|
|
47
91
|
Use `Tabs` with actual `TabsContent` panels. For URL view switches, use a labelled
|
|
48
92
|
`TabsNav` with links and `aria-current="page"` on the active link. The optional
|
|
49
93
|
Next adapter provides `TabsNavLink` with this behavior.
|
|
50
94
|
|
|
51
|
-
Use `FormTextField`, `FormSelectField`, `FormDatePickerField`,
|
|
52
|
-
`FormFeedbackField` for portable form controls,
|
|
53
|
-
messages. `Combobox`, `DatePickerButton` (including
|
|
54
|
-
`ThemeProvider`, `ErrorBoundary`, and
|
|
55
|
-
pieces. Domain data and application shells stay with the application: currency
|
|
95
|
+
Use `FormTextField`, `FormSelectField`, `FormDatePickerField`,
|
|
96
|
+
`FormDateTimePickerField`, and `FormFeedbackField` for portable form controls,
|
|
97
|
+
and `FieldError` for field messages. `Combobox`, `DatePickerButton` (including
|
|
98
|
+
`mode="range"`), `DateTimePickerButton`, `ThemeProvider`, `ErrorBoundary`, and
|
|
99
|
+
`SortableTableHead` are first-class kit pieces. Domain data and application shells stay with the application: currency
|
|
56
100
|
or timezone option lists, query-library error views, markdown editors, kanban
|
|
57
101
|
boards, and dashboard widgets.
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Shared React components and a Tailwind theme with square corners, semantic
|
|
|
4
4
|
colors, and distinct selected states. React 19 and Tailwind 4 are required.
|
|
5
5
|
|
|
6
6
|
```sh
|
|
7
|
-
npm install --save-exact atlas-react-kit@0.
|
|
7
|
+
npm install --save-exact atlas-react-kit@0.5.0
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
Import components by subpath:
|
|
@@ -42,9 +42,33 @@ with the application.
|
|
|
42
42
|
|
|
43
43
|
See [design rules](./DESIGN_RULES.md) for shared styling decisions and the
|
|
44
44
|
[component guide](./COMPONENTS.md) for exports and composition examples. Both
|
|
45
|
-
files ship in the npm package.
|
|
45
|
+
files ship in the npm package.
|
|
46
|
+
|
|
47
|
+
## AI coding assistants
|
|
48
|
+
|
|
49
|
+
The package also ships an agent skill,
|
|
50
|
+
[`skills/atlas-react-kit/SKILL.md`](./skills/atlas-react-kit/SKILL.md). It
|
|
51
|
+
tells an assistant to read the guides for the installed version, pick kit
|
|
52
|
+
components over hand-rolled markup, style with tokens, and check its work. Link
|
|
53
|
+
it into Claude Code from the app root, so it updates with the package:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
mkdir -p .claude/skills
|
|
57
|
+
ln -s ../../node_modules/atlas-react-kit/skills/atlas-react-kit .claude/skills/atlas-react-kit
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
On Windows, or to commit a pinned copy, use
|
|
61
|
+
`cp -r node_modules/atlas-react-kit/skills/atlas-react-kit .claude/skills/`
|
|
62
|
+
instead. For Cursor, Codex, or other agents, point your `AGENTS.md` at
|
|
63
|
+
`node_modules/atlas-react-kit/skills/atlas-react-kit/SKILL.md`. Shared component changes belong in this repository;
|
|
46
64
|
applications compose their feature UI around the package and upgrade deliberately.
|
|
47
65
|
|
|
66
|
+
Public docs and a live playground are at
|
|
67
|
+
[design.querobines.com](https://design.querobines.com). The site is Storybook:
|
|
68
|
+
tokens parsed from `theme.css`, these markdown guides rendered from source, and
|
|
69
|
+
editable component stories with light/dark themes, viewport previews, and
|
|
70
|
+
accessibility checks.
|
|
71
|
+
|
|
48
72
|
## Development and releases
|
|
49
73
|
|
|
50
74
|
```sh
|
|
@@ -52,17 +76,36 @@ npm ci
|
|
|
52
76
|
npm run check
|
|
53
77
|
npm test
|
|
54
78
|
npm pack
|
|
79
|
+
npm ci --prefix site
|
|
80
|
+
npm run build --prefix site
|
|
81
|
+
npm run preview --prefix site
|
|
55
82
|
```
|
|
56
83
|
|
|
57
84
|
`tsc` emits individual ESM files and TypeScript declarations. CSS is shipped
|
|
58
85
|
without compilation and processed by the consuming application's Tailwind build.
|
|
59
|
-
The
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
86
|
+
The public site is Storybook in `site/`. `npm run build --prefix site`
|
|
87
|
+
typechecks the stories, builds Storybook into `site/dist`, then checks the
|
|
88
|
+
static output. Vercel serves that directory; `/playground` and `/storybook`
|
|
89
|
+
redirect to `/`. The site and Storybook dependencies are not part of the npm
|
|
90
|
+
package. The optional Next.js 16 adapter requires Next only when imported. The
|
|
91
|
+
package does not bundle React.
|
|
92
|
+
|
|
93
|
+
Run `npm run dev --prefix site` (or `npm run storybook --prefix site`) for the
|
|
94
|
+
playground on port 6006. Existing examples live in `stories/` and are imported
|
|
95
|
+
by CSF story files in `site/stories/`, so component tests and previews share the
|
|
96
|
+
same examples. Add Storybook entries there when adding an example; the
|
|
97
|
+
static-output check reports any existing demo that has no Storybook entry.
|
|
98
|
+
Interactive stories use Storybook args so changing a control or interacting with
|
|
99
|
+
the component updates the same value. Configuration is in `site/.storybook/`.
|
|
100
|
+
|
|
101
|
+
The Storybook preview disables the kit's theme shortcut and uses the theme
|
|
102
|
+
toolbar instead. The accessibility panel checks the rendered story; it does not
|
|
103
|
+
replace keyboard or assistive-technology testing.
|
|
104
|
+
|
|
105
|
+
Bumping the version in `package.json` and merging to `main` (path-filtered
|
|
106
|
+
to package files) or running `workflow_dispatch` publishes through npm OIDC
|
|
107
|
+
trusted publishing after check, test, and pack gates. Versions already on npm
|
|
108
|
+
are skipped.
|
|
66
109
|
|
|
67
110
|
If trusted publishing is not configured, pack and publish a validated
|
|
68
111
|
artifact with the package owner's npm login:
|
|
@@ -70,9 +113,12 @@ artifact with the package owner's npm login:
|
|
|
70
113
|
```sh
|
|
71
114
|
mkdir -p release-artifacts
|
|
72
115
|
npm pack --pack-destination release-artifacts
|
|
73
|
-
npm publish ./release-artifacts/atlas-react-kit-0.
|
|
116
|
+
npm publish ./release-artifacts/atlas-react-kit-0.5.0.tgz --access public
|
|
74
117
|
```
|
|
75
118
|
|
|
119
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for adding components, the browser
|
|
120
|
+
checks, versioning, and deprecations.
|
|
121
|
+
|
|
76
122
|
Pin an exact package version in consuming applications. Roll back an upgrade by
|
|
77
123
|
restoring the previous version and lockfile. License: MIT; upstream notices are
|
|
78
124
|
preserved in [NOTICE](./NOTICE).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Accordion as AccordionPrimitive } from "radix-ui";
|
|
3
|
+
/** Stacked sections that expand in place (FAQs, settings groups). */
|
|
4
|
+
declare function Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>): React.JSX.Element;
|
|
5
|
+
declare function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>): React.JSX.Element;
|
|
6
|
+
declare function AccordionTrigger({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger>): React.JSX.Element;
|
|
7
|
+
declare function AccordionContent({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Content>): React.JSX.Element;
|
|
8
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Accordion as AccordionPrimitive } from "radix-ui";
|
|
5
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
6
|
+
import { cn } from "./utils.js";
|
|
7
|
+
/** Stacked sections that expand in place (FAQs, settings groups). */
|
|
8
|
+
function Accordion({ ...props }) {
|
|
9
|
+
return _jsx(AccordionPrimitive.Root, { "data-slot": "accordion", ...props });
|
|
10
|
+
}
|
|
11
|
+
function AccordionItem({ className, ...props }) {
|
|
12
|
+
return (_jsx(AccordionPrimitive.Item, { "data-slot": "accordion-item", className: cn("border-b last:border-b-0", className), ...props }));
|
|
13
|
+
}
|
|
14
|
+
function AccordionTrigger({ className, children, ...props }) {
|
|
15
|
+
return (_jsx(AccordionPrimitive.Header, { className: "flex", children: _jsxs(AccordionPrimitive.Trigger, { "data-slot": "accordion-trigger", className: cn("flex flex-1 items-start justify-between gap-4 rounded-none py-4 text-left text-sm font-medium transition-colors outline-none hover:text-selected-foreground focus-visible:text-selected-foreground focus-visible:ring-2 focus-visible:ring-ring/30 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180", className), ...props, children: [children, _jsx(ChevronDownIcon, { className: "pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200" })] }) }));
|
|
16
|
+
}
|
|
17
|
+
function AccordionContent({ className, children, ...props }) {
|
|
18
|
+
return (_jsx(AccordionPrimitive.Content, { "data-slot": "accordion-content", className: "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down", ...props, children: _jsx("div", { className: cn("pt-0 pb-4", className), children: children }) }));
|
|
19
|
+
}
|
|
20
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
package/dist/alert.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
/**
|
|
4
|
+
* Status tone sits on the title and icon. The description stays
|
|
5
|
+
* `text-muted-foreground` on the card face, so body text keeps its contrast
|
|
6
|
+
* (the destructive tint is too faint for text in light mode).
|
|
7
|
+
*/
|
|
8
|
+
declare const alertVariants: (props?: ({
|
|
9
|
+
variant?: "default" | "success" | "warning" | "destructive" | null | undefined;
|
|
10
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Inline message about the page or a section (save failed, trial ending).
|
|
13
|
+
* Destructive alerts use `role="alert"` so screen readers announce them;
|
|
14
|
+
* others are `role="status"`. Use a toast for transient confirmations.
|
|
15
|
+
*/
|
|
16
|
+
declare function Alert({ className, variant, role, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>): React.JSX.Element;
|
|
17
|
+
declare function AlertTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
18
|
+
declare function AlertDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
19
|
+
export { Alert, AlertDescription, AlertTitle, alertVariants };
|
package/dist/alert.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { cn } from "./utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* Status tone sits on the title and icon. The description stays
|
|
7
|
+
* `text-muted-foreground` on the card face, so body text keeps its contrast
|
|
8
|
+
* (the destructive tint is too faint for text in light mode).
|
|
9
|
+
*/
|
|
10
|
+
const alertVariants = cva("relative grid w-full grid-cols-[0_1fr] items-start gap-y-1 rounded-none border bg-card px-4 py-3 text-sm text-card-foreground has-[>svg]:grid-cols-[--spacing(4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5", {
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
default: "[&>svg]:text-foreground",
|
|
14
|
+
success: "border-success/40 *:data-[slot=alert-title]:text-success [&>svg]:text-success",
|
|
15
|
+
warning: "border-warning/40 *:data-[slot=alert-title]:text-warning [&>svg]:text-warning",
|
|
16
|
+
destructive: "border-destructive/40 *:data-[slot=alert-title]:text-destructive [&>svg]:text-destructive",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
variant: "default",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Inline message about the page or a section (save failed, trial ending).
|
|
25
|
+
* Destructive alerts use `role="alert"` so screen readers announce them;
|
|
26
|
+
* others are `role="status"`. Use a toast for transient confirmations.
|
|
27
|
+
*/
|
|
28
|
+
function Alert({ className, variant = "default", role, ...props }) {
|
|
29
|
+
return (_jsx("div", { "data-slot": "alert", "data-variant": variant, role: role ?? (variant === "destructive" ? "alert" : "status"), className: cn(alertVariants({ variant }), className), ...props }));
|
|
30
|
+
}
|
|
31
|
+
function AlertTitle({ className, ...props }) {
|
|
32
|
+
return (_jsx("div", { "data-slot": "alert-title", className: cn("col-start-2 min-h-4 text-xs font-semibold tracking-wider uppercase", className), ...props }));
|
|
33
|
+
}
|
|
34
|
+
function AlertDescription({ className, ...props }) {
|
|
35
|
+
return (_jsx("div", { "data-slot": "alert-description", className: cn("col-start-2 grid justify-items-start gap-1 text-sm leading-relaxed text-muted-foreground [&_p]:leading-relaxed", className), ...props }));
|
|
36
|
+
}
|
|
37
|
+
export { Alert, AlertDescription, AlertTitle, alertVariants };
|
package/dist/avatar.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
3
|
+
/** Person or workspace image with initials while loading or on error. Round by design. */
|
|
4
|
+
declare function Avatar({ className, size, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
|
|
5
|
+
size?: "sm" | "default" | "lg";
|
|
6
|
+
}): React.JSX.Element;
|
|
7
|
+
declare function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>): React.JSX.Element;
|
|
8
|
+
declare function AvatarFallback({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Fallback>): React.JSX.Element;
|
|
9
|
+
export { Avatar, AvatarFallback, AvatarImage };
|
package/dist/avatar.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
5
|
+
import { cn } from "./utils.js";
|
|
6
|
+
/** Person or workspace image with initials while loading or on error. Round by design. */
|
|
7
|
+
function Avatar({ className, size = "default", ...props }) {
|
|
8
|
+
return (_jsx(AvatarPrimitive.Root, { "data-slot": "avatar", "data-size": size, className: cn("relative flex shrink-0 overflow-hidden rounded-full select-none data-[size=default]:size-8 data-[size=lg]:size-10 data-[size=sm]:size-6", className), ...props }));
|
|
9
|
+
}
|
|
10
|
+
function AvatarImage({ className, ...props }) {
|
|
11
|
+
return (_jsx(AvatarPrimitive.Image, { "data-slot": "avatar-image", className: cn("aspect-square size-full object-cover", className), ...props }));
|
|
12
|
+
}
|
|
13
|
+
function AvatarFallback({ className, ...props }) {
|
|
14
|
+
return (_jsx(AvatarPrimitive.Fallback, { "data-slot": "avatar-fallback", className: cn("flex size-full items-center justify-center rounded-full bg-muted text-xs font-semibold text-muted-foreground uppercase", className), ...props }));
|
|
15
|
+
}
|
|
16
|
+
export { Avatar, AvatarFallback, AvatarImage };
|
package/dist/badge.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "
|
|
5
|
-
tone?: "
|
|
4
|
+
variant?: "default" | "link" | "destructive" | "secondary" | "outline" | "ghost" | "soft" | null | undefined;
|
|
5
|
+
tone?: "success" | "warning" | "destructive" | "neutral" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
declare function Badge({ className, variant, tone, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
8
8
|
asChild?: boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Where the current page sits in a hierarchy. The last item is
|
|
4
|
+
* `BreadcrumbPage` (plain text with `aria-current="page"`), not a link.
|
|
5
|
+
*/
|
|
6
|
+
declare function Breadcrumb({ ...props }: React.ComponentProps<"nav">): React.JSX.Element;
|
|
7
|
+
declare function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">): React.JSX.Element;
|
|
8
|
+
declare function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
|
|
9
|
+
/** Pass `asChild` to render a router link (e.g. Next `Link`) with these styles. */
|
|
10
|
+
declare function BreadcrumbLink({ asChild, className, ...props }: React.ComponentProps<"a"> & {
|
|
11
|
+
asChild?: boolean;
|
|
12
|
+
}): React.JSX.Element;
|
|
13
|
+
declare function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
14
|
+
declare function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
|
|
15
|
+
declare function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
16
|
+
export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, };
|