atlas-react-kit 0.12.0 → 1.0.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.
Files changed (98) hide show
  1. package/COMPONENTS.md +201 -100
  2. package/DESIGN_RULES.md +44 -1
  3. package/README.md +10 -9
  4. package/dist/accordion.d.ts +1 -0
  5. package/dist/alert.d.ts +1 -1
  6. package/dist/avatar.d.ts +1 -0
  7. package/dist/badge.d.ts +4 -5
  8. package/dist/breadcrumb.d.ts +2 -3
  9. package/dist/button.d.ts +4 -5
  10. package/dist/calendar.d.ts +2 -0
  11. package/dist/card.d.ts +3 -0
  12. package/dist/chart.d.ts +152 -0
  13. package/dist/chart.js +177 -0
  14. package/dist/color-legend.d.ts +8 -0
  15. package/dist/combobox.d.ts +13 -4
  16. package/dist/combobox.js +1 -8
  17. package/dist/date-picker.d.ts +16 -6
  18. package/dist/date-picker.js +13 -20
  19. package/dist/date-time-picker.d.ts +5 -2
  20. package/dist/date-time-picker.js +6 -5
  21. package/dist/dialog.d.ts +1 -0
  22. package/dist/dialog.js +4 -2
  23. package/dist/dropdown-menu.d.ts +9 -8
  24. package/dist/empty-panel.d.ts +8 -2
  25. package/dist/empty-panel.js +2 -2
  26. package/dist/error-boundary.d.ts +7 -2
  27. package/dist/field.d.ts +4 -1
  28. package/dist/field.js +1 -1
  29. package/dist/form/checkbox-field.d.ts +45 -0
  30. package/dist/form/checkbox-field.js +39 -0
  31. package/dist/form/combobox-field.d.ts +13 -0
  32. package/dist/form/combobox-field.js +14 -0
  33. package/dist/form/control-field.d.ts +30 -0
  34. package/dist/form/control-field.js +22 -0
  35. package/dist/form/date-picker-field.d.ts +7 -21
  36. package/dist/form/date-picker-field.js +4 -4
  37. package/dist/form/date-time-picker-field.d.ts +7 -22
  38. package/dist/form/date-time-picker-field.js +3 -3
  39. package/dist/form/feedback-field.d.ts +2 -0
  40. package/dist/form/field-error.d.ts +49 -0
  41. package/dist/form/field-shell.d.ts +47 -8
  42. package/dist/form/field-shell.js +24 -7
  43. package/dist/form/markdown-field.d.ts +4 -16
  44. package/dist/form/markdown-field.js +2 -2
  45. package/dist/form/select-field.d.ts +7 -7
  46. package/dist/form/select-field.js +2 -2
  47. package/dist/form/text-field.d.ts +29 -12
  48. package/dist/form/text-field.js +10 -6
  49. package/dist/form/toggle-group-field.d.ts +30 -0
  50. package/dist/form/toggle-group-field.js +19 -0
  51. package/dist/info-tip.d.ts +10 -1
  52. package/dist/internal/as-child.d.ts +8 -0
  53. package/dist/internal/as-child.js +1 -0
  54. package/dist/internal/date-like.d.ts +23 -0
  55. package/dist/internal/form-control.d.ts +3 -2
  56. package/dist/internal/form-control.js +3 -2
  57. package/dist/internal/kanban-layout.d.ts +55 -0
  58. package/dist/internal/kanban-layout.js +80 -0
  59. package/dist/internal/kanban-plugins.d.ts +17 -0
  60. package/dist/internal/kanban-plugins.js +17 -0
  61. package/dist/internal/use-media-query.d.ts +4 -2
  62. package/dist/internal/use-media-query.js +11 -15
  63. package/dist/kanban.d.ts +84 -0
  64. package/dist/kanban.js +197 -0
  65. package/dist/markdown.d.ts +2 -0
  66. package/dist/meter.d.ts +7 -0
  67. package/dist/nav-link.d.ts +23 -0
  68. package/dist/nav-link.js +31 -0
  69. package/dist/next/nav-link.d.ts +11 -0
  70. package/dist/next/nav-link.js +14 -0
  71. package/dist/next/period-stepper.d.ts +11 -0
  72. package/dist/next/period-stepper.js +16 -0
  73. package/dist/page-header.d.ts +19 -0
  74. package/dist/page-header.js +11 -0
  75. package/dist/pagination.d.ts +2 -0
  76. package/dist/period-stepper.d.ts +32 -0
  77. package/dist/period-stepper.js +27 -0
  78. package/dist/picker-shell.d.ts +43 -6
  79. package/dist/picker-shell.js +2 -2
  80. package/dist/progress.d.ts +1 -0
  81. package/dist/search-picker.d.ts +12 -0
  82. package/dist/select.d.ts +1 -0
  83. package/dist/skip-link.d.ts +7 -0
  84. package/dist/skip-link.js +10 -0
  85. package/dist/slider.d.ts +11 -0
  86. package/dist/sortable-table-head.d.ts +2 -0
  87. package/dist/stat-tile.d.ts +5 -0
  88. package/dist/table-body-skeleton.d.ts +2 -0
  89. package/dist/table.d.ts +1 -0
  90. package/dist/tabs.d.ts +9 -5
  91. package/dist/tabs.js +1 -1
  92. package/dist/toast.d.ts +7 -1
  93. package/dist/toggle-group.d.ts +9 -2
  94. package/dist/toggle-group.js +2 -1
  95. package/dist/toggle.d.ts +1 -1
  96. package/package.json +85 -11
  97. package/skills/atlas-react-kit/SKILL.md +2 -0
  98. package/theme.css +11 -0
package/COMPONENTS.md CHANGED
@@ -20,68 +20,81 @@ Core entries need only the kit. These feature entries need an extra install
20
20
  (same version ranges as the kit's optional peers). `Toaster` also reads the
21
21
  theme from `next-themes`, so toast consumers install that too.
22
22
 
23
- | Entry points | Extra install |
24
- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
25
- | `calendar`, `date-picker`, `date-time-picker`, `form/date-picker-field`, `form/date-time-picker-field` | `npm i react-day-picker@^10.0.1 date-fns@^4.4.0` |
26
- | `markdown`, `form/markdown-field` | `npm i react-markdown@^10.1.0 remark-gfm@^4.0.1` |
27
- | `theme-provider` | `npm i next-themes@^0.4.6` |
28
- | `toast` | `npm i sonner@^2.0.7 next-themes@^0.4.6` |
29
- | `next/tabs-nav-link` | `npm i next@^16.0.0` |
30
-
31
- | Subpath | Main exports and options |
32
- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
33
- | `accordion` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`; Radix `type` `single` (with `collapsible`) or `multiple` |
34
- | `alert` | `Alert`, `AlertTitle`, `AlertDescription`, `alertVariants`; `variant` `default`, `success`, `warning`, `destructive`; tone on title and icon, body stays muted; destructive is `role="alert"` |
35
- | `avatar` | `Avatar`, `AvatarImage`, `AvatarFallback`; `size` `sm`, `default`, `lg`; round by design |
36
- | `breadcrumb` | `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink` (`asChild` for router links), `BreadcrumbPage` (`aria-current`), `BreadcrumbSeparator`, `BreadcrumbEllipsis` |
37
- | `button` | `Button`, `buttonVariants`, `quietButtonInteraction`; `variant`, `size`, `asChild`; outline/ghost hover is brand purple + selected wash, not muted grey |
38
- | `badge` | `Badge`, `badgeVariants`; `variant`, `tone`, `asChild` |
39
- | `calendar` | `Calendar`, `CalendarDayButton`; React Day Picker props and `buttonVariant` |
40
- | `card` | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardAction`, `CardContent`, `CardFooter`; `Card` supports `flush`; `CardTitle as="h2"` (up to `h4`) makes it a section heading; 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 `!` |
41
- | `checkbox` | `Checkbox` |
42
- | `color-legend` | `ColorLegend`; `title`, `items` as `{ color, range?, label }[]`, optional `caption`, `children`, `aria-label`, `className` (overlay chrome). No attribution. |
43
- | `combobox` | `Combobox`; `options` as `{ value, label }[]`, `value`, `onValueChange`; optional placeholder, search, empty text, `creatable`, `normalizeCreateValue` (query → value or `null`), `createLabel`; trigger matches Input/SelectTrigger chrome; keyboard highlight scrolls into view; create is a listbox option selected with Enter |
44
- | `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+`), `minDate` / `maxDate` (days outside are disabled), `side`, `aria-labelledby`, and `aria-describedby` |
45
- | `date-time-picker` | `DateTimePickerButton`, `resolveTimeStep`, `DEFAULT_TIME_STEP`; controlled `value` is `Date` or `null`; `onChange` emits `Date \ |
46
- | `dialog` | `Dialog`, trigger, portal, overlay, content, close, header, footer, title, description; `DialogContent` supports `showCloseButton` |
47
- | `dropdown-menu` | `DropdownMenu` family (trigger, content, item, checkbox/radio items, label, separator, shortcut, sub menus); item `variant="destructive"` and `inset`; for commands, not values |
48
- | `empty-panel` | `EmptyPanel`; required `children`; optional `size`, `muted`, `className` |
49
- | `error-boundary` | `ErrorBoundary`, `ErrorFallback`; optional `message`; retry resets, reload refreshes the page |
50
- | `field` | Field, label, legend, description, group, set, title, content, separator, error; `Field` supports `orientation` |
51
- | `info-tip` | `InfoTip`, `InlineTip`; required `label` (aria-label); `title`, `description`, `children`, `layout` `box` \| `inline`, `side`, `align`, `badge`, `icon`, `className`. Popover, 20px glyph, 44px hit. Hover opens only on a fine pointer. Not a Tooltip. |
52
- | `input`, `textarea`, `label` | `Input`, `Textarea`, `Label`; `Label` `required` shows a visible marker (set `required` on the control too) |
53
- | `markdown` | `Markdown`, `MarkdownContent`; `content`, optional `className`. GFM via `react-markdown` + `remark-gfm` in this subpath only. Sanitized (no raw HTML; http/https/mailto/#/`/` URLs). Token styles, no typography plugin. |
54
- | `meter` | `Meter`; `value`, `max`, optional `min` (default 0), `fillClassName`, `markers` as `{ position, className? }[]`, required `aria-label`, `className`. `role="meter"`. Not `Progress`. |
55
- | `pagination` | `Pagination`, `PaginationContent`, `PaginationItem`, `PaginationLink` (`isActive` sets `aria-current`, the selected wash, and a selected border; `disabled` drops the `href` for a page that does not exist, such as Previous on page 1), `PaginationPrevious`, `PaginationNext` (custom text becomes the link name), `PaginationEllipsis` |
56
- | `popover` | `Popover`, trigger, anchor, content, header, title, description |
57
- | `progress` | `Progress`; Radix props, `value` 0–100; label it with `aria-label` or `aria-labelledby`. For a value against a scale with ticks, use `Meter`. |
58
- | `radio-group` | `RadioGroup`, `RadioGroupItem`; short visible lists; arrow keys move the selection; round dots |
59
- | `search-picker` | `SearchPicker<T>`; always-visible combobox + listbox; `items`, `getValue`, `getLabel`, optional `filter` (default casefold + accent-fold includes), `value`, `onSelect`, `label`, `placeholder`, `emptyText`, `listLabel`, `disabled`, `className`. Arrows, Home/End, PageUp/PageDown, Enter, Escape. |
60
- | `select` | Select, trigger, value, content, group, label, item, separator, scroll buttons; trigger `size`; trigger text is `text-base md:text-sm` like Input |
61
- | `separator`, `skeleton` | `Separator`, `Skeleton` |
62
- | `slider` | `Slider`; `value` number, `onValueChange`, optional `onValueCommit`, `min`, `max`, `step`, `disabled`, `id`, `aria-labelledby`, `className`. Radix Slider; 44px thumb hit; square track; primary fill. Name it with `aria-labelledby`. |
63
- | `sortable-table-head` | `SortableTableHead`; `sorted`, `direction` (`asc` \ |
64
- | `spinner` | `Spinner`; `role="status"` with `aria-label` (default `Loading`) |
65
- | `stat-tile` | `StatTile`, `statTileGrid`, `sectionLabel`; `label`, `value`, optional `sub`, `children`, `className`. |
66
- | `switch` | `Switch`; settings that apply immediately; square track and thumb |
67
- | `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` |
68
- | `table-body-skeleton` | `TableBodySkeleton`; `columns`, optional `rows` (default 5) |
69
- | `tabs` | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`, `TabsNav`, `tabsListVariants`, `tabsTriggerVariants`; list `variant` is `default` or `line`; style `TabsNav` links with `tabsTriggerVariants()`; `TabsNav` / `TabsList` scroll horizontally only (`overflow-y` hidden, `p-1` counted in the scroller height, edge fade, active item into view) — do not wrap them in `overflow-x-auto` |
70
- | `toast` | `Toaster`, `toast`; mount one `Toaster` (`position`, `closeButton` (default on), `expand`, `visibleToasts`, `duration`), then `toast(message, options)`. The stack expands on hover and while keyboard focus is inside it; collapsed toasts behind the front one are hidden, `.success`, `.info`, `.warning`, `.error`, `.loading`, `.dismiss(id?)`. Options: `id` (replaces that toast), `description`, `duration`, `action` / `cancel` as `{ label, onClick }`. Kit-owned API: no toast library is exposed |
71
- | `toggle` | `Toggle`, `toggleVariants`, `selectedToggleChrome`; `variant`, `size`. Pressed state is the selected wash, text, and border via `data-state=on`, `aria-pressed`, and `aria-checked` |
72
- | `toggle-group` | `ToggleGroup`, `ToggleGroupItem`; `variant`, `size`. Items share `toggleVariants`, so single (radio) and multiple selections match a pressed `Toggle` |
73
- | `theme-provider` | `ThemeProvider`, `useTheme`; optional `storageKey` (default `atlas-theme`), `enableShortcut` for the `d` toggle |
74
- | `tooltip` | `Tooltip`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider`; opens on hover and focus; short labels only |
75
- | `form/markdown-field` | `FormMarkdownField`; `field` is `TextFieldApi`; `label`, optional `id`, `placeholder`, `rows`, `showError`, `required`. Write / preview; preview uses `Markdown`. |
76
- | `form/text-field` | `FormTextField`, type `TextFieldApi`; controlled field, label, multiline, description, input constraints; `required` also marks the label |
77
- | `form/select-field` | `FormSelectField`; `value`, `onValueChange`, `label`, optional `meta`, placeholder, and `required`; select item children |
78
- | `form/date-picker-field` | `FormDatePickerField`; `value`, `onValueChange`, `label`, optional `meta`, placeholder, `required`, `minDate` / `maxDate`, and `className` (forwarded to the trigger) |
79
- | `form/date-time-picker-field` | `FormDateTimePickerField`; `value` is `Date` or `null`; `onValueChange` emits `Date` or `null`; optional `meta`, placeholder, `timeStep`, `required`, `minDate` / `maxDate`, and `className` (forwarded to the trigger) |
80
- | `form/field-error` | `FieldError` (optional `id`), `getFieldErrorMessage`; types `FieldErrorMessage`, `FieldMetaState` |
81
- | `form/feedback-field` | `FormFeedbackField`; nullable `message` |
82
- | `next/tabs-nav-link` | `TabsNavLink`; Next Link props and required `active` boolean; requires Next.js 16 |
83
- | `utils` | `cn`, `onInputChange` |
84
- | `theme.css` | Tailwind 4 theme; installation in [README](./README.md) |
23
+ | Entry points | Extra install |
24
+ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------- |
25
+ | `calendar`, `date-picker`, `date-time-picker`, `form/date-picker-field`, `form/date-time-picker-field` | `npm i react-day-picker@^10.0.1 date-fns@^4.4.0` |
26
+ | `markdown`, `form/markdown-field` | `npm i react-markdown@^10.1.0 remark-gfm@^4.0.1` |
27
+ | `kanban` | `npm i @dnd-kit/react@^0.4.0 @dnd-kit/dom@^0.4.0` |
28
+ | `theme-provider` | `npm i next-themes@^0.4.6` |
29
+ | `toast` | `npm i sonner@^2.0.7 next-themes@^0.4.6` |
30
+ | `next/nav-link`, `next/period-stepper`, `next/tabs-nav-link` | `npm i next@^16.0.0` |
31
+
32
+ | Subpath | Main exports and options |
33
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
34
+ | `accordion` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`; Radix `type` `single` (with `collapsible`) or `multiple` |
35
+ | `alert` | `Alert`, `AlertTitle`, `AlertDescription`, `alertVariants`; `variant` `default`, `success`, `warning`, `destructive`; tone on title and icon, body stays muted; destructive is `role="alert"` |
36
+ | `avatar` | `Avatar`, `AvatarImage`, `AvatarFallback`; `size` `sm`, `default`, `lg`; round by design |
37
+ | `breadcrumb` | `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink` (`asChild` for router links), `BreadcrumbPage` (`aria-current`), `BreadcrumbSeparator`, `BreadcrumbEllipsis` |
38
+ | `button` | `Button`, `buttonVariants`, `quietButtonInteraction`; `variant`, `size`, `asChild`; outline/ghost hover is brand purple + selected wash, not muted grey |
39
+ | `badge` | `Badge`, `badgeVariants`; `variant`, `tone`, `asChild` |
40
+ | `calendar` | `Calendar`, `CalendarDayButton`; React Day Picker props and `buttonVariant` |
41
+ | `card` | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardAction`, `CardContent`, `CardFooter`; `Card` supports `flush`; `CardTitle as="h2"` (up to `h4`) makes it a section heading; 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 `!` |
42
+ | `chart` | `chartFrame(height, { width?, padding? })` (viewBox and plot box: `left`, `right`, `top`, `bottom`, `plotWidth`, `plotHeight`, `viewBox`), `niceCeil`, `niceTicks`, `scaleLinear`, `linePath`, `roundedTopBarPath`, `compactNumber`, `indexAtPlotX`, `stepIndex`, `useChartScrub({ frame, steps, min, max })` (pointer and arrow-key crosshair; Escape clears), `ChartYAxisGrid` (`frame`, `yMax`, optional `tickCount`, `format`), `ChartTooltip` (`xPct`, `yPct`; `role="status"`; flips left past 55%), `ChartTooltipRow`, `ChartLegend`, `ChartLegendKey` (`swatchClassName`, `dashed`). No chart library; draw the series in your own `<svg>`. |
43
+ | `checkbox` | `Checkbox` |
44
+ | `color-legend` | `ColorLegend`; `title`, `items` as `{ color, range?, label }[]`, optional `caption`, `children`, `aria-label`, `className` (overlay chrome). No attribution. |
45
+ | `combobox` | `Combobox`; `options` as `{ value, label }[]`, `value`, `onValueChange`; optional placeholder, search, empty text, `creatable`, `normalizeCreateValue` (query → value or `null`), `createLabel`; trigger matches Input/SelectTrigger chrome; keyboard highlight scrolls into view; create is a listbox option selected with Enter |
46
+ | `date-picker` | `DatePickerButton`, `toDate`, `formatLocalDate`, and the kit's own `DateRange`, `DateMatcher`, `DateLike`, and `DatePickerCalendarProps` types (no Day Picker types); `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+`), `minDate` / `maxDate` (days outside are disabled), `side`, `aria-labelledby`, and `aria-describedby` |
47
+ | `date-time-picker` | `DateTimePickerButton`, `resolveTimeStep`, `DEFAULT_TIME_STEP`; controlled `value` is `Date` or `null`; `onValueChange` emits `Date \ |
48
+ | `dialog` | `Dialog`, trigger, portal, overlay, content, close, header, footer, title, description; `DialogContent` supports `showCloseButton` |
49
+ | `dropdown-menu` | `DropdownMenu` family (trigger, content, item, checkbox/radio items, label, separator, shortcut, sub menus); item `variant="destructive"` and `inset`; for commands, not values |
50
+ | `empty-panel` | `EmptyPanel`; required `children`; optional `size` (`sm`, `default`, `lg`), `muted`, `className` |
51
+ | `error-boundary` | `ErrorBoundary`, `ErrorFallback`; optional `message`; retry resets, reload refreshes the page |
52
+ | `field` | Field, label, legend, description, group, set, title, content, separator, error; `Field` supports `orientation` |
53
+ | `info-tip` | `InfoTip`, `InlineTip`; required `label` (aria-label); `title`, `description`, `children`, `layout` `box` \| `inline`, `side`, `align`, `badge`, `icon`, `className`. Popover, 20px glyph, 44px hit. Hover opens only on a fine pointer. Not a Tooltip. |
54
+ | `kanban` | `KanbanBoard<T>`, `KanbanSkeleton`, `KanbanColumn` and `KanbanDropTarget` types; `columns` (`{ id, label, color?, badge?, emptyLabel? }`), `items` (`{ id, position }`), `getColumnId`, `onMove(item, toColumnId, { beforePosition, afterPosition })` for every column change or reorder, `renderCard`; optional `onCardClick` (body becomes a button), `onComplete` / `onDelete` (Finish / Remove drop zones while dragging), `isLoading` (skeleton cards on a first load, dimmed board on a refetch), `emptyLabel`, `completeLabel`, `deleteLabel`. Layout comes from `items`, so an optimistic cache update is the only state. Keep `renderCard` and `onCardClick` stable (`useCallback`) and only the changed card re-renders. Cards drag by the grip (`Drag to move`); dnd-kit edge-scrolls while dragging, and off-screen columns get fades and scroll buttons. `KanbanSkeleton` takes `columnCount` (default 4). |
55
+ | `input`, `textarea`, `label` | `Input`, `Textarea`, `Label`; `Label` `required` shows a visible marker (set `required` on the control too) |
56
+ | `markdown` | `Markdown`, `MarkdownContent`; `content`, optional `className`. GFM via `react-markdown` + `remark-gfm` in this subpath only. Sanitized (no raw HTML; http/https/mailto/#/`/` URLs). Token styles, no typography plugin. |
57
+ | `meter` | `Meter`; `value`, `max`, optional `min` (default 0), `fillClassName`, `markers` as `{ position, className? }[]`, required `aria-label`, `className`. `role="meter"`. Not `Progress`. |
58
+ | `nav-link` | `NavLink`, `navLinkVariants`; required `active` boolean, `asChild` for router links. Pill chrome: inactive `text-muted-foreground` + `hover:bg-accent`, active selected wash. No router. |
59
+ | `page-header` | `PageHeader`; `title`, optional `description`, `actions`, `children` (under the description), `titleAs` (`h1` default), `titleClassName`. Stacks below `sm`. |
60
+ | `pagination` | `Pagination`, `PaginationContent`, `PaginationItem`, `PaginationLink` (`isActive` sets `aria-current`, the selected wash, and a selected border; `disabled` drops the `href` for a page that does not exist, such as Previous on page 1), `PaginationPrevious`, `PaginationNext` (custom text becomes the link name), `PaginationEllipsis` |
61
+ | `period-stepper` | `PeriodStepper`; `label` (announced with `aria-live`), `stepLabel` ("month" names "Previous month"), `onPrevious`, `onNext`, optional `onToday` (no Today button without it), `labelClassName`. `PeriodStepperFrame` takes a `control(step, content)` render for another router's links. `next/period-stepper` takes `previousHref`, `todayHref`, `nextHref` instead. |
62
+ | `popover` | `Popover`, trigger, anchor, content, header, title, description |
63
+ | `progress` | `Progress`; Radix props, `value` 0–100; label it with `aria-label` or `aria-labelledby`. For a value against a scale with ticks, use `Meter`. |
64
+ | `radio-group` | `RadioGroup`, `RadioGroupItem`; short visible lists; arrow keys move the selection; round dots |
65
+ | `search-picker` | `SearchPicker<T>`; always-visible combobox + listbox; `items`, `getValue`, `getLabel`, optional `filter` (default casefold + accent-fold includes), `value`, `onSelect`, `label`, `placeholder`, `emptyText`, `listLabel`, `disabled`, `className`. Arrows, Home/End, PageUp/PageDown, Enter, Escape. |
66
+ | `select` | Select, trigger, value, content, group, label, item, separator, scroll buttons; trigger `size`; trigger text is `text-base md:text-sm` like Input |
67
+ | `separator`, `skeleton` | `Separator`, `Skeleton` |
68
+ | `skip-link` | `SkipLink`; `href` (default `#main-content`), children (default "Skip to content"). Visually hidden until focused. |
69
+ | `slider` | `Slider`; `value` number, `onValueChange`, optional `onValueCommit`, `min`, `max`, `step`, `disabled`, `id`, `aria-labelledby`, `className`. Radix Slider; 44px thumb hit; square track; primary fill. Name it with `aria-labelledby`. |
70
+ | `sortable-table-head` | `SortableTableHead`; `sorted`, `direction` (`asc` \ |
71
+ | `spinner` | `Spinner`; `role="status"` with `aria-label` (default `Loading`) |
72
+ | `stat-tile` | `StatTile`, `statTileGrid`, `sectionLabel`; `label`, `value`, optional `sub`, `children`, `className`. |
73
+ | `switch` | `Switch`; settings that apply immediately; square track and thumb |
74
+ | `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` |
75
+ | `table-body-skeleton` | `TableBodySkeleton`; `columns`, optional `rows` (default 5) |
76
+ | `tabs` | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`, `TabsNav`, `tabsListVariants`, `tabsTriggerVariants`; list `variant` is `default` or `line`; style `TabsNav` links with `tabsTriggerVariants()`; `TabsNav` / `TabsList` scroll horizontally only (`overflow-y` hidden, `p-1` counted in the scroller height, edge fade, active item into view) — do not wrap them in `overflow-x-auto` |
77
+ | `toast` | `Toaster`, `toast`; mount one `Toaster` (`position`, `closeButton` (default on), `expand`, `visibleToasts`, `duration`), then `toast(message, options)`. The stack expands on hover and while keyboard focus is inside it; collapsed toasts behind the front one are hidden, `.success`, `.info`, `.warning`, `.error`, `.loading`, `.dismiss(id?)`. Options: `id` (replaces that toast), `description`, `duration`, `action` / `cancel` as `{ label, onClick }`. Kit-owned API: no toast library is exposed |
78
+ | `toggle` | `Toggle`, `toggleVariants`, `selectedToggleChrome`; `variant`, `size`. Pressed state is the selected wash, text, and border via `data-state=on`, `aria-pressed`, and `aria-checked` |
79
+ | `toggle-group` | `ToggleGroup`, `ToggleGroupItem`; `variant`, `size`. Items share `toggleVariants`, so single (radio) and multiple selections match a pressed `Toggle` |
80
+ | `theme-provider` | `ThemeProvider`, `useTheme`; optional `storageKey` (default `atlas-theme`), `enableShortcut` for the `d` toggle |
81
+ | `tooltip` | `Tooltip`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider`; opens on hover and focus; short labels only |
82
+ | `form/checkbox-field` | `FormCheckboxField` (`checked`, `onCheckedChange(boolean)`, `label`, optional `description`, `controlPosition` `start` \| `end`, `meta`, `required`, `disabled`, `onBlur`) and `FormCheckboxGroupField<T>` (`label` as legend, `options` `{ value, label }[]`, `value: T[]`, `onValueChange` in option order, `className` lays out the options). |
83
+ | `form/combobox-field` | `FormComboboxField`; every `Combobox` prop plus `label`, `description`, `meta`, `required`; pass the field's `onBlur`. |
84
+ | `form/control-field` | `FormControlField`, type `FormControlProps`; `label`, optional `id`, `description`, `required`, `meta`, `submitted`, `showError`; `children` renders the control from `{ id, aria-invalid, aria-describedby, aria-required }` |
85
+ | `form/markdown-field` | `FormMarkdownField`; `field` is `TextFieldApi`; `label`, optional `id`, `placeholder`, `rows`, `showError`, `required`. Write / preview; preview uses `Markdown`. |
86
+ | `form/text-field` | `FormTextField`, type `TextFieldApi`; controlled field, label, multiline, description, input constraints; `required` also marks the label |
87
+ | `form/select-field` | `FormSelectField`; `value`, `onValueChange`, `label`, optional `meta`, placeholder, and `required`; select item children |
88
+ | `form/date-picker-field` | `FormDatePickerField`; `value`, `onValueChange`, `label`, optional `meta`, placeholder, `required`, `minDate` / `maxDate`, and `className` (forwarded to the trigger) |
89
+ | `form/date-time-picker-field` | `FormDateTimePickerField`; `value` is `Date` or `null`; `onValueChange` emits `Date` or `null`; optional `meta`, placeholder, `timeStep`, `required`, `minDate` / `maxDate`, and `className` (forwarded to the trigger) |
90
+ | `form/field-error` | `FieldError` (optional `id`), `getFieldErrorMessage`; types `FieldErrorMessage`, `FieldMetaState`, `ErrorTimingProps` |
91
+ | `form/feedback-field` | `FormFeedbackField`; nullable `message` |
92
+ | `form/toggle-group-field` | `FormToggleGroupField<T>`; one choice from `options` `{ value, label }[]` as a joined outline toggle group named by its label; `value` (`""` for none), `onValueChange(T)` (pressing the active item keeps it), optional `description`, `meta`, `size` (`sm` default). |
93
+ | `next/nav-link` | `NavLink`; Next Link props and required `active` boolean; same pill as `nav-link`; requires Next.js 16 |
94
+ | `next/period-stepper` | `PeriodStepper` with prefetched Next links: `previousHref`, `nextHref`, optional `todayHref`. |
95
+ | `next/tabs-nav-link` | `TabsNavLink`; Next Link props and required `active` boolean; requires Next.js 16 |
96
+ | `utils` | `cn`, `onInputChange` |
97
+ | `theme.css` | Tailwind 4 theme; installation in [README](./README.md) |
85
98
 
86
99
  ## Status
87
100
 
@@ -90,11 +103,11 @@ through the deprecation policy in
90
103
  [CONTRIBUTING.md](https://github.com/Kerubi-5/atlas-design-system/blob/main/CONTRIBUTING.md):
91
104
  a deprecation notice first, removal in a later minor release.
92
105
 
93
- **Beta** components may still change shape in a minor release; the
94
- changelog calls out every change: `accordion`, `alert`, `avatar`,
95
- `breadcrumb`, `color-legend`, `date-time-picker`, `dropdown-menu`, `info-tip`,
96
- `markdown`, `meter`, `pagination`, `progress`, `radio-group`, `search-picker`,
97
- `slider`, `spinner`, `stat-tile`, `switch`, `tooltip`.
106
+ **Beta** components may still change shape in a minor release, before and
107
+ after 1.0; they are exempt from semver, and the changelog calls out every
108
+ change: `accordion`, `avatar`, `breadcrumb`, `chart`, `dropdown-menu`,
109
+ `kanban`, `nav-link`, `page-header`, `pagination`, `period-stepper`,
110
+ `radio-group`, `skip-link`, `spinner`, `switch`.
98
111
 
99
112
  ## Styling parts
100
113
 
@@ -103,27 +116,31 @@ through to it. Where a part sits inside a component, a prop names it, and
103
116
  each part carries a `data-slot` for parent selectors such as
104
117
  `*:data-[slot=stat-tile-value]:text-2xl`.
105
118
 
106
- | Component | Part props | Slots |
107
- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
108
- | `DialogContent` | `overlayClassName`, `closeButtonClassName` | `dialog-close-button` (the built-in X; your own `DialogClose` keeps `dialog-close`) |
109
- | `SelectTrigger` | a `className` height replaces `size` | `select-icon`, `select-viewport`, `select-item-indicator` |
110
- | `TooltipContent` | `arrowClassName` | `tooltip-arrow` |
111
- | `Combobox` | `contentClassName` (panel, default trigger width), `listClassName`; button props go to trigger | `combobox-search`, `combobox-list`, `combobox-option` |
112
- | `SearchPicker` | `listClassName`; div props go to the root | `search-picker-option`, `search-picker-empty` |
113
- | `InfoTip` | `contentClassName`; button props go to the trigger | |
114
- | `Label`, `FieldLabel` | `requiredClassName` | `label-required` |
115
- | `DatePickerButton`, `DateTimePickerButton` | `contentClassName`, `calendarProps` (disabled days, `startMonth`, `endMonth`, `weekStartsOn`, `locale`); `minDate` / `maxDate` add to its disabled days | `date-picker-value`, `date-picker-footer`, `date-time-picker-time` |
116
- | `form/*` fields | `fieldClassName` (wrapper); `className` styles the control; `FormSelectField` `contentClassName`; `FormMarkdownField` `previewClassName` | `form-field`, `form-field-header`, `form-field-description`, `form-field-error`, `form-feedback`, `form-markdown-preview` |
117
- | `Table` | `containerClassName` (the scroll box, e.g. `max-h-96 overflow-y-auto`); `className` styles the `<table>` | |
118
- | `TabsList`, `TabsNav` | `scrollerClassName`; `TabsNav` `listClassName`; a list `className` height replaces `h-11` | `tabs-scroller` |
119
- | `SortableTableHead` | `buttonClassName` | `sortable-table-head-button` |
120
- | `AccordionTrigger`, `AccordionContent` | `headerClassName`; `AccordionContent` `className` styles the inner box | `accordion-header`, `accordion-content-inner` |
121
- | `Progress` | `indicatorClassName` | `progress-indicator` |
122
- | `Meter` | `fillClassName` | `meter-fill`, `meter-marker` |
123
- | `StatTile` | | `stat-tile-label`, `stat-tile-value`, `stat-tile-sub` |
124
- | `ColorLegend` | | `color-legend-title`, `-list`, `-item`, `-swatch`, `-range`, `-label`, `-caption` |
125
- | `RadioGroupItem` | | `radio-group-dot` |
126
- | `EmptyPanel`, `ErrorFallback`, `TableBodySkeleton` | `className` | `empty-panel`, `error-boundary` |
119
+ | Component | Part props | Slots |
120
+ | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
121
+ | `DialogContent` | `overlayClassName`, `closeButtonClassName` | `dialog-close-button` (the built-in X; your own `DialogClose` keeps `dialog-close`) |
122
+ | `SelectTrigger` | a `className` height replaces `size` | `select-icon`, `select-viewport`, `select-item-indicator` |
123
+ | `TooltipContent` | `arrowClassName` | `tooltip-arrow` |
124
+ | `Combobox` | `contentClassName` (panel, default trigger width), `listClassName`; button props go to trigger | `combobox-search`, `combobox-list`, `combobox-option` |
125
+ | `SearchPicker` | `listClassName`; div props go to the root | `search-picker-option`, `search-picker-empty` |
126
+ | `InfoTip` | `contentClassName`; button props go to the trigger | |
127
+ | `KanbanBoard` | `scrollerClassName`, `columnClassName` (default `w-72 min-w-72` and a drop-area min height), `cardClassName` (cards and the drag overlay); div props go to the root | `kanban-board`, `kanban-scroller`, `kanban-column`, `kanban-column-header`, `kanban-column-empty`, `kanban-card`, `kanban-card-handle`, `kanban-card-body`, `kanban-drag-overlay`, `kanban-action-rail`, `kanban-action-zone`, `kanban-scroll-button`, `kanban-overflow-fade`, `kanban-skeleton` |
128
+ | `chart` pieces | `ChartTooltip` and `ChartLegend` take div props; `ChartLegendKey` `className` | `chart-y-axis`, `chart-tooltip`, `chart-tooltip-row`, `chart-legend`, `chart-legend-key` |
129
+ | `PageHeader`, `PeriodStepper`, `SkipLink` | `PageHeader` `titleClassName`; `PeriodStepper` `labelClassName` | `page-header`, `page-header-heading`, `page-header-title`, `page-header-description`, `page-header-actions`, `period-stepper`, `period-stepper-label`, `skip-link` |
130
+ | `FormCheckboxGroupField` | `className` (the options box), `fieldClassName` (the fieldset) | `form-checkbox-group-options` |
131
+ | `Label`, `FieldLabel` | `requiredClassName` | `label-required` |
132
+ | `DatePickerButton`, `DateTimePickerButton` | `contentClassName`, `calendarProps` (`disabled` / `hidden` days, `startMonth`, `endMonth`, `weekStartsOn`, date-fns `locale`, `showOutsideDays`, `fixedWeeks`, `showWeekNumber`, `captionLayout`, `today`, `className`); `minDate` / `maxDate` add to its disabled days | `date-picker-value`, `date-picker-footer`, `date-time-picker-time` |
133
+ | `form/*` fields | `fieldClassName` (wrapper); `className` styles the control (on `FormControlField`, the wrapper); `FormSelectField` `contentClassName`; `FormMarkdownField` `previewClassName` | `form-field`, `form-field-header`, `form-field-description`, `form-field-error`, `form-feedback`, `form-markdown-preview` |
134
+ | `Table` | `containerClassName` (the scroll box, e.g. `max-h-96 overflow-y-auto`); `className` styles the `<table>` | |
135
+ | `TabsList`, `TabsNav` | `scrollerClassName`; `TabsNav` `listClassName`; a list `className` height replaces `h-11` | `tabs-scroller` |
136
+ | `SortableTableHead` | `buttonClassName` | `sortable-table-head-button` |
137
+ | `AccordionTrigger`, `AccordionContent` | `headerClassName`; `AccordionContent` `className` styles the inner box | `accordion-header`, `accordion-content-inner` |
138
+ | `Progress` | `indicatorClassName` | `progress-indicator` |
139
+ | `Meter` | `fillClassName` | `meter-fill`, `meter-marker` |
140
+ | `StatTile` | | `stat-tile-label`, `stat-tile-value`, `stat-tile-sub` |
141
+ | `ColorLegend` | | `color-legend-title`, `-list`, `-item`, `-swatch`, `-range`, `-label`, `-caption` |
142
+ | `RadioGroupItem` | | `radio-group-dot` |
143
+ | `EmptyPanel`, `ErrorFallback`, `TableBodySkeleton` | `className` | `empty-panel`, `error-boundary` |
127
144
 
128
145
  ## Forms
129
146
 
@@ -134,7 +151,10 @@ type TextFieldApi = {
134
151
  name: string
135
152
  state: {
136
153
  value: string
137
- meta: { errors: (string | { message?: string } | undefined)[] }
154
+ meta: {
155
+ errors: (string | { message?: string } | undefined)[]
156
+ isTouched?: boolean
157
+ }
138
158
  }
139
159
  handleChange: (value: string) => void
140
160
  handleBlur: () => void
@@ -156,6 +176,38 @@ description. The date fields label their trigger with `aria-labelledby` (the
156
176
  label, then the trigger) rather than `<label for>`, so the picked date is
157
177
  part of its name.
158
178
 
179
+ Errors wait for the person. When `meta.isTouched` is `false`, a `form/*`
180
+ field hides its error text and invalid styling until the field is touched or
181
+ its `submitted` prop is set (TanStack Form:
182
+ `form.state.submissionAttempts > 0`). Pass TanStack's `field.state.meta` as
183
+ is and this works on its own; meta without `isTouched` shows errors as soon
184
+ as they exist, as before. `showError={false}` always hides them. Every
185
+ `form/*` field, `FormSelectField` and both date fields included, takes
186
+ `submitted` and `showError`.
187
+
188
+ `FormControlField` gives a control the kit does not ship the same label,
189
+ required marker, hint, error, ids, and error timing. `children` is a
190
+ function that receives the props to spread on the control:
191
+
192
+ ```tsx
193
+ <div className="grid grid-cols-2 items-start gap-3">
194
+ <FormTextField field={amount} label="Amount" required />
195
+ <FormControlField label="Currency" meta={currency.state.meta}>
196
+ {(control) => (
197
+ <Combobox
198
+ {...control}
199
+ options={options}
200
+ value={value}
201
+ onValueChange={set}
202
+ />
203
+ )}
204
+ </FormControlField>
205
+ </div>
206
+ ```
207
+
208
+ Errors sit below the control and take no space until they show, so use
209
+ `items-start` on a row of fields to keep the controls on one top edge.
210
+
159
211
  Set `required` on a `form/*` field to mark its label with a visible `*`.
160
212
  The marker is hidden from screen readers, which announce the control's own
161
213
  `required` (`aria-required` on the select trigger). The date pickers are
@@ -165,9 +217,11 @@ draws the same marker; set `required` on the control yourself.
165
217
 
166
218
  `DatePickerButton` is single-day by default. For a from/to range, set
167
219
  `mode="range"`; `value` is `{ from, to }` (each side `Date` or `yyyy-MM-dd`)
168
- and `onChange` receives `DateRange | undefined`. The trigger uses the same
169
- form-control chrome as `Input` and `SelectTrigger`. The range popover shows
170
- one month below `md` and two months at `md+` unless `numberOfMonths` is set,
220
+ and `onValueChange` receives `DateRange | undefined`. The trigger uses the same
221
+ form-control chrome as `Input` and `SelectTrigger`. Long picker values wrap
222
+ inside narrow triggers; ordinary one-line values stay 40px tall, and consumer
223
+ height classes still override that default. The range popover shows one
224
+ month below `md` and two months at `md+` unless `numberOfMonths` is set,
171
225
  clamps to the viewport with collision padding and scroll, stays `w-auto` so
172
226
  it does not collapse to the default popover width, and includes a Clear
173
227
  action. Pass `side` to prefer a placement; Radix still flips on collision.
@@ -183,8 +237,11 @@ the trigger text's id (a `<label for>` alone names the button by the label
183
237
  only).
184
238
  `FormDatePickerField` forwards `className` to that trigger.
185
239
 
240
+ Both pickers took `onChange` before 0.14; it still works as a deprecated
241
+ alias until 2.0.
242
+
186
243
  `DateTimePickerButton` is the date-and-time control. `value` is a `Date` or
187
- `null`; `onChange` receives `Date | null`. The trigger matches the same
244
+ `null`; `onValueChange` receives `Date | null`. The trigger matches the same
188
245
  form-control chrome. The popover is one month, a labelled Hour and Minute
189
246
  pair (24-hour, stepped by `timeStep`, default 15), and Clear. Picking a day
190
247
  keeps the popover open so the time can be set; the time selects stay
@@ -205,15 +262,15 @@ import { DateTimePickerButton } from "atlas-react-kit/date-time-picker"
205
262
 
206
263
  export function EventStarts({
207
264
  value,
208
- onChange,
265
+ onValueChange,
209
266
  }: {
210
267
  value: Date | null
211
- onChange: (date: Date | null) => void
268
+ onValueChange: (date: Date | null) => void
212
269
  }) {
213
270
  return (
214
271
  <DateTimePickerButton
215
272
  value={value}
216
- onChange={onChange}
273
+ onValueChange={onValueChange}
217
274
  timeStep={15}
218
275
  placeholder="Pick a date and time"
219
276
  />
@@ -226,16 +283,16 @@ import { DatePickerButton, type DateRange } from "atlas-react-kit/date-picker"
226
283
 
227
284
  export function ExportRange({
228
285
  value,
229
- onChange,
286
+ onValueChange,
230
287
  }: {
231
288
  value: DateRange | undefined
232
- onChange: (range: DateRange | undefined) => void
289
+ onValueChange: (range: DateRange | undefined) => void
233
290
  }) {
234
291
  return (
235
292
  <DatePickerButton
236
293
  mode="range"
237
294
  value={value}
238
- onChange={onChange}
295
+ onValueChange={onValueChange}
239
296
  numberOfMonths={2}
240
297
  placeholder="Export range"
241
298
  />
@@ -262,6 +319,50 @@ choice under `atlas-theme` unless `storageKey` is set. The `d` dark/light toggle
262
319
  is off by default; pass `enableShortcut` to turn it on, and give people a setting
263
320
  to turn it off again, since a single-key shortcut can fire by accident (WCAG 2.1.4).
264
321
 
322
+ ## App shell navigation
323
+
324
+ Pill links for top-level destinations (Calendar, Tasks, Settings). Pass
325
+ `active` from the route; the kit does not read the URL. Wrap a router link
326
+ with `asChild`, or use the optional Next adapter.
327
+
328
+ ```tsx
329
+ import Link from "next/link"
330
+ import { NavLink } from "atlas-react-kit/nav-link"
331
+
332
+ export function AppNav({ pathname }: { pathname: string }) {
333
+ return (
334
+ <nav aria-label="App" className="flex items-center gap-1">
335
+ <NavLink asChild active={pathname === "/calendar"}>
336
+ <Link href="/calendar">Calendar</Link>
337
+ </NavLink>
338
+ <NavLink asChild active={pathname === "/tasks"}>
339
+ <Link href="/tasks">Tasks</Link>
340
+ </NavLink>
341
+ </nav>
342
+ )
343
+ }
344
+ ```
345
+
346
+ ```tsx
347
+ import { NavLink } from "atlas-react-kit/next/nav-link"
348
+
349
+ export function AppNav({ pathname }: { pathname: string }) {
350
+ return (
351
+ <nav aria-label="App" className="flex items-center gap-1">
352
+ <NavLink href="/calendar" active={pathname === "/calendar"}>
353
+ Calendar
354
+ </NavLink>
355
+ <NavLink href="/tasks" active={pathname === "/tasks"}>
356
+ Tasks
357
+ </NavLink>
358
+ </nav>
359
+ )
360
+ }
361
+ ```
362
+
363
+ In-page view switches that still belong in the URL use `TabsNav`, not
364
+ `NavLink`.
365
+
265
366
  ## URL navigation in Next.js
266
367
 
267
368
  ```tsx
@@ -309,5 +410,5 @@ export function ViewSwitcher({ view }: { view: string }) {
309
410
  ```
310
411
 
311
412
  Hook-driven controls and form handlers declare their client boundary; presentational
312
- modules such as `button`, `badge`, `card`, and `skeleton` can be composed from
413
+ modules such as `button`, `badge`, `card`, `nav-link`, and `skeleton` can be composed from
313
414
  React Server Components. Pass interactive callbacks from client components.