@actioneer/ads 1.0.4 → 1.0.6

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 (59) hide show
  1. package/DESIGN.md +75 -75
  2. package/README.md +205 -0
  3. package/components/ai-elements/agent-trace.js +14 -14
  4. package/components/ai-elements/chain-of-thought.js +3 -3
  5. package/components/ai-elements/chart.js +3 -3
  6. package/components/ai-elements/inline-citation.js +2 -2
  7. package/components/ai-elements/message.js +1 -1
  8. package/components/ai-elements/research-activity.js +4 -4
  9. package/components/answer-sources.js +3 -3
  10. package/components/answer.js +3 -3
  11. package/components/assistant-ui/action-bar.js +2 -2
  12. package/components/assistant-ui/attachment.js +5 -5
  13. package/components/assistant-ui/badge.js +1 -1
  14. package/components/assistant-ui/branch-picker.js +1 -1
  15. package/components/assistant-ui/composer-add-context.js +7 -7
  16. package/components/assistant-ui/composer-deep-research.js +3 -3
  17. package/components/assistant-ui/composer-harness.js +1 -1
  18. package/components/assistant-ui/composer-trigger-popover.js +8 -8
  19. package/components/assistant-ui/composer.js +45 -45
  20. package/components/assistant-ui/file.js +9 -9
  21. package/components/assistant-ui/image.js +1 -1
  22. package/components/assistant-ui/markdown-text.js +1 -1
  23. package/components/assistant-ui/message-timing.js +1 -1
  24. package/components/assistant-ui/reasoning.js +10 -10
  25. package/components/assistant-ui/thread.js +1 -1
  26. package/components/assistant-ui/tool-fallback.js +2 -2
  27. package/components/assistant-ui/tool-group.js +3 -3
  28. package/components/autocomplete.js +28 -27
  29. package/components/brand-loader.d.ts +1 -1
  30. package/components/brand-loader.js +9 -9
  31. package/components/chart.js +5 -5
  32. package/components/checkbox.js +16 -16
  33. package/components/chip.js +33 -33
  34. package/components/collapsible.js +14 -12
  35. package/components/command-palette.js +37 -37
  36. package/components/connector-card.js +1 -1
  37. package/components/date-range-picker.js +2 -2
  38. package/components/dropdown.js +1 -1
  39. package/components/field.js +1 -1
  40. package/components/file-dropzone.js +2 -2
  41. package/components/infinite-canvas.js +1 -1
  42. package/components/modal.js +6 -6
  43. package/components/pagination.js +23 -23
  44. package/components/radio.js +1 -1
  45. package/components/segmented.js +23 -23
  46. package/components/selection-action-bar.js +13 -13
  47. package/components/sidebar.js +5 -5
  48. package/components/stepper.d.ts +1 -1
  49. package/components/stepper.js +4 -4
  50. package/components/switch.js +7 -7
  51. package/components/tooltip.js +1 -1
  52. package/components/tree.js +20 -20
  53. package/components/ui/button.js +21 -21
  54. package/components/ui/tooltip.js +3 -3
  55. package/llms.txt +6 -6
  56. package/manifest.json +13 -13
  57. package/package.json +1 -1
  58. package/styles.css +49 -56
  59. package/theme.css +49 -56
package/DESIGN.md CHANGED
@@ -8,55 +8,55 @@ colors:
8
8
  action-primary-soft: "#dfefec"
9
9
  action-primary-foreground: "#ffffff"
10
10
  field-focus: "#4c9b92"
11
- brand: "#20201e"
12
- brand-hover: "#4b4b47"
13
- brand-text: "#20201e"
11
+ brand: "#1c8379"
12
+ brand-hover: "#017369"
13
+ brand-text: "#016159"
14
14
  brand-foreground: "#ffffff"
15
- success: "#516923"
15
+ success: "#2d6b22"
16
16
  success-foreground: "#ffffff"
17
17
  warning: "#f79009"
18
- warning-foreground: "#20201e"
18
+ warning-foreground: "#21201d"
19
19
  danger: "#d92d20"
20
20
  danger-foreground: "#ffffff"
21
21
  info: "#1570ef"
22
22
  info-foreground: "#ffffff"
23
- background: "#f1f1ef"
24
- foreground: "#20201e"
25
- surface: "#ececea"
26
- surface-foreground: "#20201e"
23
+ background: "#f3f1e9"
24
+ foreground: "#21201d"
25
+ surface: "#efece3"
26
+ surface-foreground: "#21201d"
27
27
  elevated: "#ffffff"
28
28
  card: "#ffffff"
29
- card-foreground: "#20201e"
30
- muted: "#e5e5e2"
31
- muted-foreground: "#4b4b47"
32
- fill: "#ececea"
33
- fill-foreground: "#20201e"
34
- accent: "#dcdcd8"
35
- accent-foreground: "#20201e"
36
- on-white-primary: "#20201e"
37
- on-white-secondary: "#4b4b47"
38
- on-white-tertiary: "#777771"
39
- on-warm-grey-primary: "#20201e"
40
- on-warm-grey-secondary: "#4b4b47"
41
- on-warm-grey-tertiary: "#777771"
42
- primary: "#20201e"
43
- secondary: "#4b4b47"
29
+ card-foreground: "#21201d"
30
+ muted: "#e8e5db"
31
+ muted-foreground: "#4d4b44"
32
+ fill: "#efece3"
33
+ fill-foreground: "#21201d"
34
+ accent: "#dfdcd0"
35
+ accent-foreground: "#21201d"
36
+ on-white-primary: "#21201d"
37
+ on-white-secondary: "#4d4b44"
38
+ on-white-tertiary: "#79766a"
39
+ on-warm-grey-primary: "#21201d"
40
+ on-warm-grey-secondary: "#4d4b44"
41
+ on-warm-grey-tertiary: "#79766a"
42
+ primary: "#21201d"
43
+ secondary: "#4d4b44"
44
44
  tertiary: "color-mix(in srgb, var(--color-wg10) 80%, var(--color-wg11))"
45
- border: "#e5e5e2"
46
- border-primary: "#dcdcd8"
47
- border-secondary: "#e5e5e2"
48
- border-tertiary: "#ececea"
49
- border-strong: "#dcdcd8"
50
- input: "#e5e5e2"
51
- menu-stroke: "#e5e5e2"
52
- toast-stroke: "#e5e5e2"
53
- tree-stroke: "#e5e5e2"
54
- specimen-stroke: "#ececea"
45
+ border: "#e8e5db"
46
+ border-primary: "#dfdcd0"
47
+ border-secondary: "#e8e5db"
48
+ border-tertiary: "#efece3"
49
+ border-strong: "#dfdcd0"
50
+ input: "#e8e5db"
51
+ menu-stroke: "#e8e5db"
52
+ toast-stroke: "#e8e5db"
53
+ tree-stroke: "#e8e5db"
54
+ specimen-stroke: "#efece3"
55
55
  table-shell: "#ffffff"
56
- table-stroke: "#ececea"
56
+ table-stroke: "#efece3"
57
57
  table-header-foreground: "color-mix(in srgb, var(--color-wg10) 80%, var(--color-wg11))"
58
58
  artifact-canvas: "color-mix(in srgb, var(--color-brand-mark) 7%, var(--color-white))"
59
- ring: "color-mix(in srgb, var(--color-wg12) 50%, transparent)"
59
+ ring: "#1c8379"
60
60
  overlay: "color-mix(in srgb, var(--color-wg12) 50%, transparent)"
61
61
  typography:
62
62
  display:
@@ -179,7 +179,7 @@ components:
179
179
 
180
180
  TASTE.md puts it in one line: On a quiet, neutral ground, colour and motion are spent like money — rarely, deliberately, and only where the eye should go.
181
181
 
182
- ADS 1.0.4 is a library first and a look second. 323 components across 10 families (Primitives / utilities, Foundations, Form controls, Overlays, Data display, Feedback, Navigation, Layout, AI Elements, Chat) ship from one barrel, and every product that consumes them inherits the judgment encoded in 56 semantic tokens and 11 principles rather than re-deciding it per screen.
182
+ ADS 1.0.6 is a library first and a look second. 323 components across 10 families (Primitives / utilities, Foundations, Form controls, Overlays, Data display, Feedback, Navigation, Layout, AI Elements, Chat) ship from one barrel, and every product that consumes them inherits the judgment encoded in 56 semantic tokens and 11 principles rather than re-deciding it per screen.
183
183
 
184
184
  The ground is warm grey and the ink is warm near-black. One hue is spent by default, the Studio teal CTA family, and four more carry semantic status. Everything else stays neutral. A consumer product may narrow that further, and one already does: Baby Sentinel drops the teal and runs every action on ink.
185
185
 
@@ -211,26 +211,26 @@ The one place a hue is spent by default: the Studio teal CTA family.
211
211
 
212
212
  The neutral-ink action role kept as a compatibility API.
213
213
 
214
- **Compatibility action role — neutral ink, never a colored primary hue.**
214
+ **Shared brand roles for control states, primary accents, and marks.**
215
215
 
216
- - **brand** (`--color-brand`, #20201e) `bg-brand`
217
- - **brand-hover** (`--color-brand-hover`, #4b4b47) `bg-brand-hover`
218
- - **brand-text** (`--color-brand-text`, #20201e) `text-brand-text`
216
+ - **brand** (`--color-brand`, #1c8379) `bg-brand`
217
+ - **brand-hover** (`--color-brand-hover`, #017369) `bg-brand-hover`
218
+ - **brand-text** (`--color-brand-text`, #016159) `text-brand-text`
219
219
  - **brand-foreground** (`--color-brand-foreground`, #ffffff) `text-brand-foreground`
220
220
 
221
221
  ### Tertiary
222
222
 
223
223
  Semantic status. These four carry meaning and are never identity.
224
224
 
225
- **Lichen success-700 clears AA on White and both success soft fills; success-600 is reserved for non-text marks because its 3.73:1 contrast on White does not clear body-text AA.**
225
+ **Grass green 700 clears AA on White and both success soft fills.**
226
226
 
227
- - **success** (`--color-success`, #516923) `bg-success`
227
+ - **success** (`--color-success`, #2d6b22) `bg-success`
228
228
  - **success-foreground** (`--color-success-foreground`, #ffffff) `text-success-foreground`
229
229
 
230
230
  **Amber-500 fill kept (it IS the caution signal); dark ink foreground instead of white = 6.94:1 (white on amber was 2.35:1, failed even 3:1).**
231
231
 
232
232
  - **warning** (`--color-warning`, #f79009) `bg-warning`
233
- - **warning-foreground** (`--color-warning-foreground`, #20201e) `text-warning-foreground`
233
+ - **warning-foreground** (`--color-warning-foreground`, #21201d) `text-warning-foreground`
234
234
 
235
235
  **Danger and info: solid semantic fills carrying white foregrounds.**
236
236
 
@@ -245,70 +245,70 @@ The warm-grey ground everything else stands on.
245
245
 
246
246
  **The shell canvas and its ink: the ground between top-level panels.**
247
247
 
248
- - **background** (`--color-background`, #f1f1ef) `bg-background`
249
- - **foreground** (`--color-foreground`, #20201e) `text-foreground`
248
+ - **background** (`--color-background`, #f3f1e9) `bg-background`
249
+ - **foreground** (`--color-foreground`, #21201d) `text-foreground`
250
250
 
251
251
  **One continuous recess inside a white surface, never a screen-level ground.**
252
252
 
253
- - **surface** (`--color-surface`, #ececea) `bg-surface`
254
- - **surface-foreground** (`--color-surface-foreground`, #20201e) `text-surface-foreground`
253
+ - **surface** (`--color-surface`, #efece3) `bg-surface`
254
+ - **surface-foreground** (`--color-surface-foreground`, #21201d) `text-surface-foreground`
255
255
  - **elevated** (`--color-elevated`, #ffffff) `bg-elevated`
256
256
 
257
257
  **The white working plane that sits on the canvas, and the specimen hairline.**
258
258
 
259
259
  - **card** (`--color-card`, #ffffff) `bg-card`
260
- - **card-foreground** (`--color-card-foreground`, #20201e) `text-card-foreground`
260
+ - **card-foreground** (`--color-card-foreground`, #21201d) `text-card-foreground`
261
261
 
262
262
  **The hover and row-state wash: interaction, not a default item background.**
263
263
 
264
- - **muted** (`--color-muted`, #e5e5e2) `bg-muted`
265
- - **muted-foreground** (`--color-muted-foreground`, #4b4b47) `text-muted-foreground`
264
+ - **muted** (`--color-muted`, #e8e5db) `bg-muted`
265
+ - **muted-foreground** (`--color-muted-foreground`, #4d4b44) `text-muted-foreground`
266
266
 
267
267
  **Quiet fill — avatars, chips, and disabled controls.**
268
268
 
269
- - **fill** (`--color-fill`, #ececea) `bg-fill`
270
- - **fill-foreground** (`--color-fill-foreground`, #20201e) `text-fill-foreground`
269
+ - **fill** (`--color-fill`, #efece3) `bg-fill`
270
+ - **fill-foreground** (`--color-fill-foreground`, #21201d) `text-fill-foreground`
271
271
 
272
272
  **The active and selected wash, one step above hover.**
273
273
 
274
- - **accent** (`--color-accent`, #dcdcd8) `bg-accent`
275
- - **accent-foreground** (`--color-accent-foreground`, #20201e) `text-accent-foreground`
274
+ - **accent** (`--color-accent`, #dfdcd0) `bg-accent`
275
+ - **accent-foreground** (`--color-accent-foreground`, #21201d) `text-accent-foreground`
276
276
 
277
277
  **Contextual text hierarchies — three accessible levels per surface.**
278
278
 
279
- - **on-white-primary** (`--color-on-white-primary`, #20201e) `bg-on-white-primary`
280
- - **on-white-secondary** (`--color-on-white-secondary`, #4b4b47) `bg-on-white-secondary`
281
- - **on-white-tertiary** (`--color-on-white-tertiary`, #777771) `bg-on-white-tertiary`
282
- - **on-warm-grey-primary** (`--color-on-warm-grey-primary`, #20201e) `bg-on-warm-grey-primary`
283
- - **on-warm-grey-secondary** (`--color-on-warm-grey-secondary`, #4b4b47) `bg-on-warm-grey-secondary`
284
- - **on-warm-grey-tertiary** (`--color-on-warm-grey-tertiary`, #777771) `bg-on-warm-grey-tertiary`
279
+ - **on-white-primary** (`--color-on-white-primary`, #21201d) `bg-on-white-primary`
280
+ - **on-white-secondary** (`--color-on-white-secondary`, #4d4b44) `bg-on-white-secondary`
281
+ - **on-white-tertiary** (`--color-on-white-tertiary`, #79766a) `bg-on-white-tertiary`
282
+ - **on-warm-grey-primary** (`--color-on-warm-grey-primary`, #21201d) `bg-on-warm-grey-primary`
283
+ - **on-warm-grey-secondary** (`--color-on-warm-grey-secondary`, #4d4b44) `bg-on-warm-grey-secondary`
284
+ - **on-warm-grey-tertiary** (`--color-on-warm-grey-tertiary`, #79766a) `bg-on-warm-grey-tertiary`
285
285
 
286
286
  **Context-free compatibility aliases remain conservative.**
287
287
 
288
- - **primary** (`--color-primary`, #20201e) `bg-primary`
289
- - **secondary** (`--color-secondary`, #4b4b47) `bg-secondary`
288
+ - **primary** (`--color-primary`, #21201d) `bg-primary`
289
+ - **secondary** (`--color-secondary`, #4d4b44) `bg-secondary`
290
290
  - **tertiary** (`--color-tertiary`, color-mix(in srgb, var(--color-wg10) 80%, var(--color-wg11))) `bg-tertiary`
291
291
 
292
292
  **The neutral stroke ladder: every 1px UI border stays within WG3 to WG5.**
293
293
 
294
- - **border** (`--color-border`, #e5e5e2) `bg-border`
295
- - **border-primary** (`--color-border-primary`, #dcdcd8) `bg-border-primary`
296
- - **border-secondary** (`--color-border-secondary`, #e5e5e2) `bg-border-secondary`
297
- - **border-tertiary** (`--color-border-tertiary`, #ececea) `bg-border-tertiary`
298
- - **border-strong** (`--color-border-strong`, #dcdcd8) `bg-border-strong`
299
- - **input** (`--color-input`, #e5e5e2) `bg-input`
300
- - **menu-stroke** (`--color-menu-stroke`, #e5e5e2) `bg-menu-stroke`
301
- - **toast-stroke** (`--color-toast-stroke`, #e5e5e2) `bg-toast-stroke`
302
- - **tree-stroke** (`--color-tree-stroke`, #e5e5e2) `bg-tree-stroke`
294
+ - **border** (`--color-border`, #e8e5db) `bg-border`
295
+ - **border-primary** (`--color-border-primary`, #dfdcd0) `bg-border-primary`
296
+ - **border-secondary** (`--color-border-secondary`, #e8e5db) `bg-border-secondary`
297
+ - **border-tertiary** (`--color-border-tertiary`, #efece3) `bg-border-tertiary`
298
+ - **border-strong** (`--color-border-strong`, #dfdcd0) `bg-border-strong`
299
+ - **input** (`--color-input`, #e8e5db) `bg-input`
300
+ - **menu-stroke** (`--color-menu-stroke`, #e8e5db) `bg-menu-stroke`
301
+ - **toast-stroke** (`--color-toast-stroke`, #e8e5db) `bg-toast-stroke`
302
+ - **tree-stroke** (`--color-tree-stroke`, #e8e5db) `bg-tree-stroke`
303
303
 
304
304
  **The white working plane that sits on the canvas, and the specimen hairline.**
305
305
 
306
- - **specimen-stroke** (`--color-specimen-stroke`, #ececea) `bg-specimen-stroke`
306
+ - **specimen-stroke** (`--color-specimen-stroke`, #efece3) `bg-specimen-stroke`
307
307
 
308
308
  **Table surfaces: the white tray, its hairlines, and header ink.**
309
309
 
310
310
  - **table-shell** (`--color-table-shell`, #ffffff) `bg-table-shell`
311
- - **table-stroke** (`--color-table-stroke`, #ececea) `bg-table-stroke`
311
+ - **table-stroke** (`--color-table-stroke`, #efece3) `bg-table-stroke`
312
312
  - **table-header-foreground** (`--color-table-header-foreground`, color-mix(in srgb, var(--color-wg10) 80%, var(--color-wg11))) `text-table-header-foreground`
313
313
 
314
314
  **The artifact sheet: white warmed by a trace of the brand mark.**
@@ -317,7 +317,7 @@ The warm-grey ground everything else stands on.
317
317
 
318
318
  **Focus ring and scrim, both translucent warm ink.**
319
319
 
320
- - **ring** (`--color-ring`, color-mix(in srgb, var(--color-wg12) 50%, transparent)) `ring-ring`
320
+ - **ring** (`--color-ring`, #1c8379) `ring-ring`
321
321
  - **overlay** (`--color-overlay`, color-mix(in srgb, var(--color-wg12) 50%, transparent)) `bg-overlay`
322
322
 
323
323
  ### Named rules
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # @actioneer/ads
2
+
3
+ The **Actioneer Design System**: React 19 components, Tailwind CSS v4 tokens,
4
+ bundled Aribau Grotesk fonts, and accessible interactions with built-in motion.
5
+
6
+ [Browse components in Storybook](https://actioneer-ads-storybook.himanshu-563.workers.dev).
7
+
8
+ > **The one rule:** build UI **only** from the exact named exports of
9
+ > `@actioneer/ads`, and reference tokens — never raw color/dimension literals.
10
+ > Never fork, alias, deep-import, or hand-roll a copy of a component.
11
+ > `@actioneer/ads-lint` enforces this.
12
+
13
+ ---
14
+
15
+ ## 1. Install
16
+
17
+ ```bash
18
+ npm install @actioneer/ads motion
19
+ ```
20
+
21
+ Use an existing **React 19 + Tailwind CSS v4** application with an ESM-capable
22
+ bundler. `react` and `react-dom` are peer dependencies; the application owns the
23
+ React instance. The setup below uses Next.js App Router paths.
24
+
25
+ The bootstrap configures styles and providers and creates the lint config:
26
+
27
+ ```bash
28
+ npx @actioneer/ads init
29
+ ```
30
+
31
+ `init` adds the CSS import, creates `ads-providers.tsx` (or `.jsx`), and writes a
32
+ consumer `ads-lint.config.mjs`. It wraps detected Next.js layouts and reports any
33
+ manual setup still needed. Run it from your application directory after setting
34
+ up Tailwind v4. The manual setup follows.
35
+
36
+ ## 2. Tailwind v4 + `styles.css` (import order matters)
37
+
38
+ In your global stylesheet, import ADS's stylesheet **immediately after**
39
+ Tailwind:
40
+
41
+ ```css
42
+ /* app/globals.css */
43
+ @import "tailwindcss";
44
+ @import "@actioneer/ads/styles.css";
45
+ ```
46
+
47
+ `styles.css` carries three things that must live in the **same CSS graph** as
48
+ `tailwindcss`:
49
+
50
+ - the `@theme` **design tokens** (colors, typography, spacing, and radii),
51
+ - the **Aribau Grotesk** `@font-face` rules (served package-relative — no
52
+ `/public` copy needed), and
53
+ - a baked `@source "./**/*.{js,mjs}"` so Tailwind scans ADS's own class usage and
54
+ generates its utilities in your build.
55
+
56
+ > ⚠️ Import order is load-bearing. If you `@import "@actioneer/ads/styles.css"`
57
+ > **before** `@import "tailwindcss"` — or import it into a stylesheet that isn't
58
+ > part of the Tailwind graph — its `@theme` is an unknown at-rule and **no tokens
59
+ > emit** (you'll get an unstyled, "blank" render).
60
+
61
+ Granular entries are also exported if you need them: `@actioneer/ads/theme.css`
62
+ (tokens only) and `@actioneer/ads/fonts.css` (`@font-face` only).
63
+
64
+ ## 3. Required providers
65
+
66
+ Wrap your app root **once** with all three providers. `npx @actioneer/ads init`
67
+ generates this as `app/ads-providers.tsx` (beside the layout when using `src/app`):
68
+
69
+ ```tsx
70
+ // app/ads-providers.tsx
71
+ "use client";
72
+
73
+ import type { ReactNode } from "react";
74
+ import { TooltipProvider, ToastProvider } from "@actioneer/ads";
75
+ import { MotionConfig } from "motion/react";
76
+
77
+ export function Providers({ children }: { children: ReactNode }) {
78
+ return (
79
+ <MotionConfig reducedMotion="user">
80
+ <ToastProvider>
81
+ <TooltipProvider>{children}</TooltipProvider>
82
+ </ToastProvider>
83
+ </MotionConfig>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ```tsx
89
+ // app/layout.tsx
90
+ import type { ReactNode } from "react";
91
+ import { Providers } from "./ads-providers";
92
+ import "./globals.css";
93
+
94
+ export default function RootLayout({ children }: { children: ReactNode }) {
95
+ return (
96
+ <html lang="en">
97
+ <body><Providers>{children}</Providers></body>
98
+ </html>
99
+ );
100
+ }
101
+ ```
102
+
103
+ - **`TooltipProvider`** — required. The vendored tooltip/attachment chips crash
104
+ the tree without an ancestor provider.
105
+ - **`ToastProvider`** — required to render toasts.
106
+ - **`<MotionConfig reducedMotion="user">`** — honors the OS reduced-motion
107
+ setting across every ADS animation.
108
+
109
+ For other React frameworks, import the global stylesheet and wrap the application
110
+ root with `Providers` in the framework's entry point.
111
+
112
+ ## 4. Usage
113
+
114
+ Import the **exact named export** from the package barrel:
115
+
116
+ ```tsx
117
+ // app/page.tsx
118
+ "use client";
119
+
120
+ import { Button, InputField } from "@actioneer/ads";
121
+
122
+ export default function Example() {
123
+ return (
124
+ <main className="mx-auto flex max-w-sm flex-col gap-4 p-6">
125
+ <InputField label="Workspace name" defaultValue="Actioneer" />
126
+ <div className="flex gap-2">
127
+ <Button variant="solid" size="md">Save</Button>
128
+ <Button variant="secondary">Cancel</Button>
129
+ </div>
130
+ </main>
131
+ );
132
+ }
133
+ ```
134
+
135
+ Do **not**:
136
+
137
+ | ❌ Anti-pattern | ✅ Instead |
138
+ |----------------|-----------|
139
+ | `import { Button } from "@actioneer/ads/button"` (deep import) | `import { Button } from "@actioneer/ads"` |
140
+ | `import { Card as Panel } from "@actioneer/ads"` (alias) | use the export's real name, `Card` |
141
+ | `import Button from "@actioneer/ads"` (default) / `import * as ADS` (namespace) | named imports only |
142
+ | copy a component's source into your repo and edit it (fork) | import it; request an ADS change upstream |
143
+ | `class="bg-[#0a0a0b]"` / `"#0a0a0b"` (literal) | a semantic token, e.g. `bg-brand` |
144
+ | `import { Dialog } from "@radix-ui/react-dialog"` (external UI) | the ADS primitive (`Modal`, `Popover`, …) |
145
+
146
+ **Why:** ADS is a single source of truth. A token or motion fix ships to the
147
+ whole fleet with one version bump — but only if every consumer imports the
148
+ canonical export instead of a divergent fork.
149
+
150
+ **Discover exact names:** the machine-readable catalog ships in the package —
151
+ `@actioneer/ads/manifest.json` (every export → name, family, kind, variants,
152
+ props, showcase URL) and `@actioneer/ads/llms.txt` (the LLM-facing index). Point
153
+ your coding agent at those, or use the ADS MCP server.
154
+
155
+ Reference the semantic tokens (e.g. `bg-brand`, `text-muted-foreground`,
156
+ `border-input`, `ring-ring`) rather than raw values; the full token list is in
157
+ `manifest.json` under `tokens`.
158
+
159
+ Shared motion presets are named exports from `@actioneer/ads`. Components already
160
+ include their own interaction motion; use the exported presets for additional
161
+ application state changes.
162
+
163
+ ## 5. Wire up `ads-lint`
164
+
165
+ `@actioneer/ads-lint` enforces the contract above on your changed files.
166
+
167
+ ```bash
168
+ npm install -D @actioneer/ads-lint typescript
169
+ ```
170
+
171
+ Drop a **consumer-mode** config at your repo root (`init` writes this for you):
172
+
173
+ ```js
174
+ // ads-lint.config.mjs
175
+ export default {
176
+ imports: {
177
+ libraryPackage: "@actioneer/ads",
178
+ libraryRoot: null, // consumer mode: every file is a consumer
179
+ },
180
+ };
181
+ ```
182
+
183
+ Run it:
184
+
185
+ ```bash
186
+ # lint everything
187
+ npx ads-lint --all
188
+ # or just what changed (pre-commit / CI)
189
+ npx ads-lint --staged
190
+ npx ads-lint --diff origin/main
191
+ ```
192
+
193
+ It flags deep imports, aliased/default/namespace barrel imports, external-UI
194
+ imports, hardcoded color/dimension literals, and banned/weak motion — the same
195
+ rules ADS holds itself to. A CI job that runs `npx ads-lint --diff <base>` keeps
196
+ every consuming repo honest.
197
+
198
+ ## Documentation and license
199
+
200
+ - [Storybook: components and recipes](https://actioneer-ads-storybook.himanshu-563.workers.dev)
201
+ - [ADS MCP: component discovery for coding agents](https://www.npmjs.com/package/@actioneer/ads-mcp)
202
+ - Bundled references: `@actioneer/ads/manifest.json`, `@actioneer/ads/llms.txt`,
203
+ and `@actioneer/ads/DESIGN.md`.
204
+
205
+ MIT licensed.
@@ -12,7 +12,7 @@ import { Text as ce } from "../typography.js";
12
12
  import { ChainOfThoughtStep as de, ChainOfThoughtTrigger as ue, ChainOfThoughtContent as he, ChainOfThoughtItem as me, ChainOfThoughtSearchResults as pe, ChainOfThoughtSearchResult as fe, ChainOfThought as ge } from "./chain-of-thought.js";
13
13
  import { TraceStateIcon as C } from "./chain-of-thought-icon.js";
14
14
  import { ResearchActivity as L } from "./research-activity.js";
15
- import { Tool as ve, ToolHeader as be, ToolContent as xe, ToolInput as Ne, ToolOutput as Ce } from "./tool.js";
15
+ import { Tool as ve, ToolHeader as be, ToolContent as Ne, ToolInput as xe, ToolOutput as Ce } from "./tool.js";
16
16
  const Te = "Main Agent", we = 60, _ = J(!0);
17
17
  function ye({
18
18
  title: e,
@@ -39,7 +39,7 @@ function ye({
39
39
  ),
40
40
  /* @__PURE__ */ t("span", { className: "text-base", children: e }),
41
41
  /* @__PURE__ */ i("span", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
42
- a != null && /* @__PURE__ */ t("span", { className: "text-xs text-tertiary tabular-nums", children: a }),
42
+ a != null && /* @__PURE__ */ t("span", { className: "text-s text-tertiary tabular-nums", children: a }),
43
43
  /* @__PURE__ */ t(
44
44
  ee,
45
45
  {
@@ -79,7 +79,7 @@ function k(e) {
79
79
  if (e.elapsed != null) return e.elapsed;
80
80
  if (e.seconds != null) return T(e.seconds);
81
81
  }
82
- function N(e) {
82
+ function x(e) {
83
83
  const r = [];
84
84
  for (const a of e) r.includes(a.group) || r.push(a.group);
85
85
  return r;
@@ -102,8 +102,8 @@ function Oe(e) {
102
102
  }
103
103
  const F = P(({ call: e }) => /* @__PURE__ */ i(ve, { children: [
104
104
  /* @__PURE__ */ t(be, { title: e.name, type: `tool-${e.name}`, state: e.state }),
105
- /* @__PURE__ */ i(xe, { children: [
106
- e.input !== void 0 && /* @__PURE__ */ t(Ne, { input: e.input }),
105
+ /* @__PURE__ */ i(Ne, { children: [
106
+ e.input !== void 0 && /* @__PURE__ */ t(xe, { input: e.input }),
107
107
  /* @__PURE__ */ t(
108
108
  Ce,
109
109
  {
@@ -132,7 +132,7 @@ const G = P(
132
132
  return /* @__PURE__ */ i(de, { status: e.status === "error" ? "error" : "complete", children: [
133
133
  /* @__PURE__ */ i(ue, { leftIcon: s, endContent: l, children: [
134
134
  /* @__PURE__ */ t("span", { children: e.label }),
135
- e.agent && e.agent !== r && /* @__PURE__ */ t("span", { className: "ml-2 text-xs font-normal text-tertiary", children: e.agent })
135
+ e.agent && e.agent !== r && /* @__PURE__ */ t("span", { className: "ml-2 text-s font-normal text-tertiary", children: e.agent })
136
136
  ] }),
137
137
  /* @__PURE__ */ t(he, { rail: !1, children: /* @__PURE__ */ i("div", { className: "-ml-5", style: { "--tree-rail-lead": "18px" }, children: [
138
138
  e.detail != null && /* @__PURE__ */ t("div", { className: "ads-tree-rail pb-3", children: /* @__PURE__ */ t(me, { children: e.detail }) }),
@@ -163,17 +163,17 @@ const $e = ({
163
163
  ...w
164
164
  }) => {
165
165
  var D, E;
166
- const n = e.find((o) => o.status === "active") ?? null, p = e.filter((o) => o.status === "complete" || o.status === "error"), y = new Set(l ?? []), g = e.length > 0 && e.every((o) => o.status === "complete" || o.status === "error"), [H, S] = Q(() => new Set(N(e))), A = j(null);
166
+ const n = e.find((o) => o.status === "active") ?? null, p = e.filter((o) => o.status === "complete" || o.status === "error"), y = new Set(l ?? []), g = e.length > 0 && e.every((o) => o.status === "complete" || o.status === "error"), [H, S] = Q(() => new Set(x(e))), A = j(null);
167
167
  R(() => {
168
168
  const o = (n == null ? void 0 : n.group) ?? null;
169
- o == null || o === A.current || (A.current = o, S(new Set(N(e).filter((u) => u !== o))));
169
+ o == null || o === A.current || (A.current = o, S(new Set(x(e).filter((u) => u !== o))));
170
170
  }, [n == null ? void 0 : n.group, e]);
171
171
  const M = j(g);
172
172
  R(() => {
173
- g && !M.current && (S(new Set(N(e))), A.current = null), M.current = g;
173
+ g && !M.current && (S(new Set(x(e))), A.current = null), M.current = g;
174
174
  }, [g, e]);
175
- const v = N(p).map((o) => {
176
- var f, x;
175
+ const v = x(p).map((o) => {
176
+ var f, N;
177
177
  const u = p.filter((b) => b.group === o), c = u[0];
178
178
  return {
179
179
  group: o,
@@ -181,7 +181,7 @@ const $e = ({
181
181
  C,
182
182
  {
183
183
  stage: c == null ? void 0 : c.state,
184
- toolName: (x = (f = c == null ? void 0 : c.calls) == null ? void 0 : f[0]) == null ? void 0 : x.name,
184
+ toolName: (N = (f = c == null ? void 0 : c.calls) == null ? void 0 : f[0]) == null ? void 0 : N.name,
185
185
  status: "complete"
186
186
  }
187
187
  ),
@@ -211,8 +211,8 @@ const $e = ({
211
211
  icon: u,
212
212
  summary: Ae(c),
213
213
  open: !H.has(o),
214
- onOpenChange: (f) => S((x) => {
215
- const b = new Set(x);
214
+ onOpenChange: (f) => S((N) => {
215
+ const b = new Set(N);
216
216
  return f ? b.delete(o) : b.add(o), b;
217
217
  }),
218
218
  children: /* @__PURE__ */ t(ge, { children: c.map((f) => /* @__PURE__ */ t(
@@ -153,7 +153,7 @@ const k = O(!1), S = O("tree"), I = c(
153
153
  ),
154
154
  /* @__PURE__ */ e("span", { className: "min-w-0 flex-1", children: o }),
155
155
  /* @__PURE__ */ l("span", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
156
- r != null && /* @__PURE__ */ e("span", { className: "text-xs text-tertiary tabular-nums", children: r }),
156
+ r != null && /* @__PURE__ */ e("span", { className: "text-s text-tertiary tabular-nums", children: r }),
157
157
  t && /* @__PURE__ */ e(
158
158
  w,
159
159
  {
@@ -300,7 +300,7 @@ const k = O(!1), S = O("tree"), I = c(
300
300
  children: a
301
301
  }
302
302
  ),
303
- r != null && /* @__PURE__ */ e("span", { className: "shrink-0 text-xs text-tertiary tabular-nums", children: r }),
303
+ r != null && /* @__PURE__ */ e("span", { className: "shrink-0 text-s text-tertiary tabular-nums", children: r }),
304
304
  /* @__PURE__ */ e(
305
305
  w,
306
306
  {
@@ -380,7 +380,7 @@ const k = O(!1), S = O("tree"), I = c(
380
380
  )) }, p);
381
381
  }) })
382
382
  ] }) }),
383
- h && /* @__PURE__ */ l("p", { className: "px-2.5 py-1.5 text-xs text-tertiary tabular-nums", children: [
383
+ h && /* @__PURE__ */ l("p", { className: "px-2.5 py-1.5 text-s text-tertiary tabular-nums", children: [
384
384
  a.length,
385
385
  " of ",
386
386
  r,
@@ -217,7 +217,7 @@ const ee = g.forwardRef(
217
217
  children: /* @__PURE__ */ e(O, { "data-slot": "ai-chart-icon", className: "size-4" })
218
218
  }
219
219
  ),
220
- /* @__PURE__ */ e("span", { className: "min-w-0 truncate text-xs font-normal text-foreground", children: i }),
220
+ /* @__PURE__ */ e("span", { className: "min-w-0 truncate text-m font-normal text-foreground", children: i }),
221
221
  o != null && /* @__PURE__ */ e(
222
222
  Q,
223
223
  {
@@ -231,7 +231,7 @@ const ee = g.forwardRef(
231
231
  "span",
232
232
  {
233
233
  "data-slot": "ai-chart-meta",
234
- className: "ml-auto shrink-0 text-xs tabular-nums",
234
+ className: "ml-auto shrink-0 text-s tabular-nums",
235
235
  children: m
236
236
  }
237
237
  ),
@@ -279,7 +279,7 @@ const ee = g.forwardRef(
279
279
  "button",
280
280
  {
281
281
  type: "button",
282
- className: "rounded-sm text-left outline-none transition-colors duration-150 ease-out hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring motion-reduce:transition-none",
282
+ className: "rounded-sm text-left text-s outline-none transition-colors duration-150 ease-out hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring motion-reduce:transition-none",
283
283
  "aria-label": `Open source ${s}`,
284
284
  onClick: () => h(s),
285
285
  children: [
@@ -223,7 +223,7 @@ const G = ({
223
223
  "div",
224
224
  {
225
225
  className: c(
226
- "flex flex-1 items-center justify-end px-3 py-1 text-xs text-tertiary tabular-nums",
226
+ "flex flex-1 items-center justify-end px-3 py-1 text-s text-tertiary tabular-nums",
227
227
  t
228
228
  ),
229
229
  ...s,
@@ -278,7 +278,7 @@ const G = ({
278
278
  ...a
279
279
  }) => /* @__PURE__ */ k("div", { className: c("space-y-1", n), ...a, children: [
280
280
  e && /* @__PURE__ */ i("p", { className: "truncate font-normal text-base leading-tight text-primary", children: e }),
281
- t && /* @__PURE__ */ i("p", { className: "truncate break-all text-xs text-tertiary", children: t }),
281
+ t && /* @__PURE__ */ i("p", { className: "truncate break-all text-s text-tertiary", children: t }),
282
282
  s && /* @__PURE__ */ i("p", { className: "line-clamp-3 text-base leading-relaxed text-secondary", children: s }),
283
283
  r
284
284
  ] }), ee = ({
@@ -253,7 +253,7 @@ const H = o.forwardRef(({ className: e, ...t }, a) => {
253
253
  {
254
254
  ref: a,
255
255
  className: i(
256
- "px-1.5 text-xs tabular-nums text-tertiary select-none",
256
+ "px-1.5 text-s tabular-nums text-tertiary select-none",
257
257
  e
258
258
  ),
259
259
  ...t,
@@ -53,10 +53,10 @@ function $({
53
53
  m === 1 ? "source" : "sources"
54
54
  ] }),
55
55
  /* @__PURE__ */ e("span", { "aria-hidden": !0, className: "text-tertiary", children: "·" }),
56
- /* @__PURE__ */ e("span", { className: "text-xs text-tertiary tabular-nums", children: t }),
56
+ /* @__PURE__ */ e("span", { className: "text-s text-tertiary tabular-nums", children: t }),
57
57
  n != null && /* @__PURE__ */ r(q, { children: [
58
58
  /* @__PURE__ */ e("span", { "aria-hidden": !0, className: "text-tertiary", children: "·" }),
59
- /* @__PURE__ */ r("span", { className: "text-xs text-tertiary", children: [
59
+ /* @__PURE__ */ r("span", { className: "text-s text-tertiary", children: [
60
60
  "first insight",
61
61
  " ",
62
62
  /* @__PURE__ */ e("span", { className: "tabular-nums", children: n })
@@ -169,7 +169,7 @@ const oe = s.forwardRef(
169
169
  O
170
170
  ) }) }) }),
171
171
  l && /* @__PURE__ */ r("span", { className: o(
172
- "shrink-0 text-xs text-tertiary tabular-nums",
172
+ "shrink-0 text-s text-tertiary tabular-nums",
173
173
  // Reserve the caret slot (size-4 + gap-2) so trailing metadata
174
174
  // keeps the same right edge as sibling rows that show a caret.
175
175
  !x && "pe-6"
@@ -205,7 +205,7 @@ const oe = s.forwardRef(
205
205
  /* @__PURE__ */ e("span", { "aria-hidden": !0, className: "flex size-4 shrink-0 items-center justify-center", children: v ?? R }),
206
206
  /* @__PURE__ */ e(K, { as: "span", className: "text-base", children: "Researching…" }),
207
207
  /* @__PURE__ */ r("span", { className: o(
208
- "ml-auto shrink-0 text-xs text-tertiary tabular-nums",
208
+ "ml-auto shrink-0 text-s text-tertiary tabular-nums",
209
209
  !x && "pe-6"
210
210
  ), children: [
211
211
  /* @__PURE__ */ e("span", { className: "sr-only", children: "Elapsed " }),