atlas-react-kit 0.8.1 → 0.9.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 CHANGED
@@ -5,6 +5,18 @@ 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
+ Core entries need only the kit. These feature entries need an extra install
9
+ (same version ranges as the kit's optional peers). `Toaster` also reads the
10
+ theme from `next-themes`, so toast consumers install that too.
11
+
12
+ | Entry points | Extra install |
13
+ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
14
+ | `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` |
15
+ | `markdown`, `form/markdown-field` | `npm i react-markdown@^10.1.0 remark-gfm@^4.0.1` |
16
+ | `theme-provider` | `npm i next-themes@^0.4.6` |
17
+ | `toast` | `npm i sonner@^2.0.7 next-themes@^0.4.6` |
18
+ | `next/tabs-nav-link` | `npm i next@^16.0.0` |
19
+
8
20
  | Subpath | Main exports and options |
9
21
  | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10
22
  | `accordion` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`; Radix `type` `single` (with `collapsible`) or `multiple` |
@@ -43,7 +55,7 @@ no root component barrel.
43
55
  | `switch` | `Switch`; settings that apply immediately; square track and thumb |
44
56
  | `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` |
45
57
  | `table-body-skeleton` | `TableBodySkeleton`; `columns`, optional `rows` (default 5) |
46
- | `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, edge fade, active item into view) — do not wrap them in `overflow-x-auto` |
58
+ | `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` |
47
59
  | `toast` | `Toaster`, `toast`; mount one `Toaster` (`position`, `closeButton` (default on), `expand`, `visibleToasts`, `duration`), then `toast(message, options)`, `.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 |
48
60
  | `toggle` | `Toggle`, `toggleVariants`, `selectedToggleChrome`; `variant`, `size`. Pressed state is the selected wash, text, and border via `data-state=on`, `aria-pressed`, and `aria-checked` |
49
61
  | `toggle-group` | `ToggleGroup`, `ToggleGroupItem`; `variant`, `size`. Items share `toggleVariants`, so single (radio) and multiple selections match a pressed `Toggle` |
package/DESIGN_RULES.md CHANGED
@@ -105,9 +105,10 @@ Use `Tabs` with actual `TabsContent` panels. For URL view switches, use a labell
105
105
  `TabsNav` with links and `aria-current="page"` on the active link. The optional
106
106
  Next adapter provides `TabsNavLink` with this behavior. `TabsNav` and `TabsList`
107
107
  scroll overflowing labels inside themselves (`overflow-x-auto overflow-y-hidden`,
108
- with padding for the active border and focus ring, and an edge fade like
109
- `Table`). Do not wrap them in another `overflow-x-auto` — that pairing forces
110
- `overflow-y: auto` and a stray vertical scrollbar.
108
+ with padding for the active border and focus ring counted in the scroller
109
+ height, and an edge fade like `Table`). Do not wrap them in another
110
+ `overflow-x-auto` — that pairing forces `overflow-y: auto` and a stray
111
+ vertical scrollbar.
111
112
 
112
113
  Use `FormTextField`, `FormSelectField`, `FormDatePickerField`,
113
114
  `FormDateTimePickerField`, `FormMarkdownField`, and `FormFeedbackField` for
package/README.md CHANGED
@@ -7,7 +7,7 @@ keeping locally (`InfoTip`, `ColorLegend`, `SearchPicker`, `Markdown`,
7
7
  React 19 and Tailwind 4 are required.
8
8
 
9
9
  ```sh
10
- npm install --save-exact atlas-react-kit@0.8.1
10
+ npm install --save-exact atlas-react-kit@0.9.0
11
11
  ```
12
12
 
13
13
  Import components by subpath:
@@ -27,6 +27,18 @@ export function Example() {
27
27
  }
28
28
  ```
29
29
 
30
+ Core entries need only the kit. These feature entries need an extra install
31
+ (same version ranges as the kit's optional peers). `Toaster` also reads the
32
+ theme from `next-themes`, so toast consumers install that too.
33
+
34
+ | Entry points | Extra install |
35
+ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
36
+ | `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` |
37
+ | `markdown`, `form/markdown-field` | `npm i react-markdown@^10.1.0 remark-gfm@^4.0.1` |
38
+ | `theme-provider` | `npm i next-themes@^0.4.6` |
39
+ | `toast` | `npm i sonner@^2.0.7 next-themes@^0.4.6` |
40
+ | `next/tabs-nav-link` | `npm i next@^16.0.0` |
41
+
30
42
  In your global stylesheet, import the theme after Tailwind and register the
31
43
  installed JavaScript directory. Paths in `@source` are relative to that stylesheet;
32
44
  this example assumes it is one directory below the project root.
@@ -90,8 +102,9 @@ The public site is Storybook in `site/`. `npm run build --prefix site`
90
102
  typechecks the stories, builds Storybook into `site/dist`, then checks the
91
103
  static output. Vercel serves that directory; `/playground` and `/storybook`
92
104
  redirect to `/`. The site and Storybook dependencies are not part of the npm
93
- package. The optional Next.js 16 adapter requires Next only when imported. The
94
- package does not bundle React.
105
+ package. Optional feature libraries (markdown, dates, toasts, theme, Next) are
106
+ peer dependencies and are required only when those entry points are imported.
107
+ The package does not bundle React.
95
108
 
96
109
  Run `npm run dev --prefix site` (or `npm run storybook --prefix site`) for the
97
110
  playground on port 6006. Existing examples live in `stories/` and are imported
@@ -116,7 +129,7 @@ artifact with the package owner's npm login:
116
129
  ```sh
117
130
  mkdir -p release-artifacts
118
131
  npm pack --pack-destination release-artifacts
119
- npm publish ./release-artifacts/atlas-react-kit-0.8.1.tgz --access public
132
+ npm publish ./release-artifacts/atlas-react-kit-0.9.0.tgz --access public
120
133
  ```
121
134
 
122
135
  See [CONTRIBUTING.md](./CONTRIBUTING.md) for adding components, the browser
@@ -1,5 +1,17 @@
1
1
  declare const tabsListVariants: (props?: ({
2
2
  variant?: "default" | "line" | null | undefined;
3
3
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
4
+ /**
5
+ * Horizontal scroller around a tab row. `p-1` leaves room for the active
6
+ * border and focus ring; the height is the `h-11` list plus that padding
7
+ * (`h-13` = 44px + 8px) so the list fits the content box. Putting padding
8
+ * on an overflow box without this height makes `scrollHeight` 4px taller
9
+ * than `clientHeight` (48 vs 44) and a vertical scrollbar appears if
10
+ * `overflow-y` is not hidden. Line variant adds `pb-2` for the underline
11
+ * (`h-14` = 44px + 4px + 8px).
12
+ */
13
+ declare const tabsScrollerVariants: (props?: ({
14
+ variant?: "default" | "line" | null | undefined;
15
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
4
16
  declare const tabsTriggerVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
5
- export { tabsListVariants, tabsTriggerVariants };
17
+ export { tabsListVariants, tabsScrollerVariants, tabsTriggerVariants };
@@ -11,6 +11,26 @@ const tabsListVariants = cva('group/tabs-list inline-flex w-max min-w-full items
11
11
  variant: "default",
12
12
  },
13
13
  });
14
+ /**
15
+ * Horizontal scroller around a tab row. `p-1` leaves room for the active
16
+ * border and focus ring; the height is the `h-11` list plus that padding
17
+ * (`h-13` = 44px + 8px) so the list fits the content box. Putting padding
18
+ * on an overflow box without this height makes `scrollHeight` 4px taller
19
+ * than `clientHeight` (48 vs 44) and a vertical scrollbar appears if
20
+ * `overflow-y` is not hidden. Line variant adds `pb-2` for the underline
21
+ * (`h-14` = 44px + 4px + 8px).
22
+ */
23
+ const tabsScrollerVariants = cva("relative box-border w-full min-w-0 max-w-full overflow-x-auto overflow-y-hidden overscroll-x-contain p-1 [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden", {
24
+ variants: {
25
+ variant: {
26
+ default: 'group-data-[orientation="horizontal"]/tabs:h-13',
27
+ line: 'group-data-[orientation="horizontal"]/tabs:h-14 pb-2',
28
+ },
29
+ },
30
+ defaultVariants: {
31
+ variant: "default",
32
+ },
33
+ });
14
34
  const tabsTriggerVariants = cva([
15
35
  focusRing,
16
36
  disabledState,
@@ -22,4 +42,4 @@ const tabsTriggerVariants = cva([
22
42
  selectedState.active,
23
43
  'after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation="horizontal"]/tabs:after:inset-x-0 group-data-[orientation="horizontal"]/tabs:after:bottom-[-5px] group-data-[orientation="horizontal"]/tabs:after:h-0.5 group-data-[orientation="vertical"]/tabs:after:inset-y-0 group-data-[orientation="vertical"]/tabs:after:-right-1 group-data-[orientation="vertical"]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state="active"]:after:opacity-100',
24
44
  ]);
25
- export { tabsListVariants, tabsTriggerVariants };
45
+ export { tabsListVariants, tabsScrollerVariants, tabsTriggerVariants };
@@ -9,8 +9,8 @@ export type MarkdownProps = {
9
9
  };
10
10
  /**
11
11
  * GitHub-flavoured Markdown, token-styled and sanitized. No Next, no raw
12
- * HTML, no typography plugin. `react-markdown` and `remark-gfm` stay in this
13
- * module so other subpaths do not pay for them.
12
+ * HTML, no typography plugin. `react-markdown` and `remark-gfm` are optional
13
+ * peers imported only here so other subpaths do not pay for them.
14
14
  */
15
15
  declare function Markdown({ content, className }: MarkdownProps): import("react").JSX.Element;
16
16
  /** Alias used by apps that imported MarkdownContent. */
package/dist/markdown.js CHANGED
@@ -51,8 +51,8 @@ const markdownComponents = {
51
51
  };
52
52
  /**
53
53
  * GitHub-flavoured Markdown, token-styled and sanitized. No Next, no raw
54
- * HTML, no typography plugin. `react-markdown` and `remark-gfm` stay in this
55
- * module so other subpaths do not pay for them.
54
+ * HTML, no typography plugin. `react-markdown` and `remark-gfm` are optional
55
+ * peers imported only here so other subpaths do not pay for them.
56
56
  */
57
57
  function Markdown({ content, className }) {
58
58
  return (_jsx("article", { "data-slot": "markdown", className: cn("flex flex-col gap-3 text-foreground", className), children: _jsx(ReactMarkdown, { remarkPlugins: REMARK_PLUGINS, urlTransform: safeMarkdownUrl, components: markdownComponents, children: content }) }));
package/dist/tabs.d.ts CHANGED
@@ -15,8 +15,9 @@ declare function TabsContent({ className, ...props }: React.ComponentProps<typeo
15
15
  * `TabsNavLink` does this for you).
16
16
  *
17
17
  * Overflow is handled here: the row scrolls horizontally only, with padding
18
- * for active borders and focus rings, an edge fade while it overflows, and
19
- * the active link scrolled into view on mount. Do not wrap it in
18
+ * for active borders and focus rings counted in the scroller height (so the
19
+ * list cannot overflow on y), an edge fade while it overflows, and the
20
+ * active link scrolled into view on mount. Do not wrap it in
20
21
  * `overflow-x-auto`.
21
22
  */
22
23
  declare function TabsNav({ className, children, ...props }: React.ComponentProps<"nav"> & {
package/dist/tabs.js CHANGED
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import {} from "class-variance-authority";
5
5
  import { Tabs as TabsPrimitive } from "radix-ui";
6
6
  import { focusRing } from "./internal/styles.js";
7
- import { tabsListVariants, tabsTriggerVariants, } from "./internal/tabs-styles.js";
7
+ import { tabsListVariants, tabsScrollerVariants, tabsTriggerVariants, } from "./internal/tabs-styles.js";
8
8
  import { useHorizontalOverflow } from "./internal/use-horizontal-overflow.js";
9
9
  import { cn } from "./utils.js";
10
10
  function Tabs({ className, orientation = "horizontal", ...props }) {
@@ -13,9 +13,10 @@ function Tabs({ className, orientation = "horizontal", ...props }) {
13
13
  /**
14
14
  * Horizontal scroller around a tab row. `overflow-x: auto` alone would
15
15
  * compute `overflow-y` to `auto` as well (CSS overflow pairing), so the
16
- * active tab's border and focus ring grow a vertical scrollbar. Clip the
17
- * y axis, pad for those strokes, and fade the edges while the row
18
- * overflows — same cue as `Table`.
16
+ * active tab's border and focus ring grow a vertical scrollbar. Pad for
17
+ * those strokes *inside* the box (`h-13` = `h-11` list + `p-1`), clip the
18
+ * y axis as a backstop, and fade the edges while the row overflows —
19
+ * same cue as `Table`.
19
20
  */
20
21
  function TabsScroller({ variant = "default", children, }) {
21
22
  const ref = React.useRef(null);
@@ -31,7 +32,7 @@ function TabsScroller({ variant = "default", children, }) {
31
32
  behavior: "auto",
32
33
  });
33
34
  }, []);
34
- return (_jsx("div", { ref: ref, "data-slot": "tabs-scroller", "data-variant": variant, tabIndex: overflowing ? 0 : undefined, className: cn(focusRing, "relative w-full min-w-0 max-w-full overflow-x-auto overflow-y-hidden overscroll-x-contain p-1 [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden", variant === "line" && "pb-2"), children: children }));
35
+ return (_jsx("div", { ref: ref, "data-slot": "tabs-scroller", "data-variant": variant, tabIndex: overflowing ? 0 : undefined, className: cn(focusRing, tabsScrollerVariants({ variant })), children: children }));
35
36
  }
36
37
  function TabsList({ className, variant = "default", ...props }) {
37
38
  return (_jsx(TabsScroller, { variant: variant ?? "default", children: _jsx(TabsPrimitive.List, { "data-slot": "tabs-list", "data-variant": variant, className: cn(tabsListVariants({ variant }),
@@ -53,8 +54,9 @@ function TabsContent({ className, ...props }) {
53
54
  * `TabsNavLink` does this for you).
54
55
  *
55
56
  * Overflow is handled here: the row scrolls horizontally only, with padding
56
- * for active borders and focus rings, an edge fade while it overflows, and
57
- * the active link scrolled into view on mount. Do not wrap it in
57
+ * for active borders and focus rings counted in the scroller height (so the
58
+ * list cannot overflow on y), an edge fade while it overflows, and the
59
+ * active link scrolled into view on mount. Do not wrap it in
58
60
  * `overflow-x-auto`.
59
61
  */
60
62
  function TabsNav({ className, children, ...props }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atlas-react-kit",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "Shared React components and Tailwind theme for Atlas",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -255,27 +255,45 @@
255
255
  "access": "public"
256
256
  },
257
257
  "peerDependencies": {
258
+ "date-fns": "^4.4.0",
258
259
  "next": "^16.0.0",
260
+ "next-themes": "^0.4.6",
259
261
  "react": "^19.0.0",
262
+ "react-day-picker": "^10.0.1",
260
263
  "react-dom": "^19.0.0",
264
+ "react-markdown": "^10.1.0",
265
+ "remark-gfm": "^4.0.1",
266
+ "sonner": "^2.0.7",
261
267
  "tailwindcss": "^4.0.0"
262
268
  },
263
269
  "peerDependenciesMeta": {
270
+ "date-fns": {
271
+ "optional": true
272
+ },
264
273
  "next": {
265
274
  "optional": true
275
+ },
276
+ "next-themes": {
277
+ "optional": true
278
+ },
279
+ "react-day-picker": {
280
+ "optional": true
281
+ },
282
+ "react-markdown": {
283
+ "optional": true
284
+ },
285
+ "remark-gfm": {
286
+ "optional": true
287
+ },
288
+ "sonner": {
289
+ "optional": true
266
290
  }
267
291
  },
268
292
  "dependencies": {
269
293
  "class-variance-authority": "^0.7.1",
270
294
  "clsx": "^2.1.1",
271
- "date-fns": "^4.4.0",
272
295
  "lucide-react": "^1.16.0",
273
- "next-themes": "^0.4.6",
274
296
  "radix-ui": "^1.4.3",
275
- "react-day-picker": "^10.0.1",
276
- "react-markdown": "^10.1.0",
277
- "remark-gfm": "^4.0.1",
278
- "sonner": "^2.0.7",
279
297
  "tailwind-merge": "^3.6.0",
280
298
  "tw-animate-css": "^1.4.0"
281
299
  },
@@ -288,11 +306,17 @@
288
306
  "@types/react": "^19.2.14",
289
307
  "@types/react-dom": "^19.2.3",
290
308
  "@vitest/coverage-v8": "4.1.11",
309
+ "date-fns": "^4.4.0",
291
310
  "jsdom": "^29.1.1",
292
311
  "next": "16.2.6",
312
+ "next-themes": "^0.4.6",
293
313
  "prettier": "^3.8.1",
294
314
  "react": "^19.2.4",
315
+ "react-day-picker": "^10.0.1",
295
316
  "react-dom": "^19.2.4",
317
+ "react-markdown": "^10.1.0",
318
+ "remark-gfm": "^4.0.1",
319
+ "sonner": "^2.0.7",
296
320
  "tailwindcss": "^4.2.1",
297
321
  "typescript": "^6.0.3",
298
322
  "vitest": "^4.1.9"
@@ -42,7 +42,9 @@ root (or a `dark` class on an ancestor). Toasts need one `<Toaster />` from
42
42
  `atlas-react-kit/toast`; show them with `toast()` from the same module, using
43
43
  only the options it declares. Never import a toast library such as `sonner`
44
44
  directly: the kit owns the toast API, and a second copy never reaches its
45
- toaster. Fix missing setup rather than working
45
+ toaster. Markdown, dates, toasts, and `ThemeProvider` are optional peers —
46
+ install the extras listed in `COMPONENTS.md` when you import those entry
47
+ points. Fix missing setup rather than working
46
48
  around unstyled components.
47
49
 
48
50
  ## 3. Pick the kit component for the job