@actioneer/ads 0.5.7 → 0.5.9

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 (147) hide show
  1. package/bin/ads-init.mjs +6 -0
  2. package/components/accordion.js +50 -48
  3. package/components/agent-icon.d.ts +12 -0
  4. package/components/agent-icon.js +133 -120
  5. package/components/ai-elements/chain-of-thought.d.ts +1 -1
  6. package/components/ai-elements/chain-of-thought.js +108 -108
  7. package/components/ai-elements/chart.js +16 -14
  8. package/components/ai-elements/inline-citation.js +41 -41
  9. package/components/ai-elements/message.js +4 -4
  10. package/components/ai-elements/queue.js +7 -7
  11. package/components/ai-elements/research-activity.js +114 -114
  12. package/components/ai-elements/shimmer.d.ts +2 -2
  13. package/components/ai-elements/speech-input.js +28 -28
  14. package/components/ai-elements/task-progress.js +26 -16
  15. package/components/ai-elements/task.js +17 -17
  16. package/components/ai-elements/tool.js +6 -6
  17. package/components/ai-elements/transcript.js +6 -5
  18. package/components/ai-elements/voice.js +1 -1
  19. package/components/alert.js +10 -10
  20. package/components/answer-sources.js +1 -1
  21. package/components/answer.js +115 -114
  22. package/components/assistant-ui/action-bar.js +94 -48
  23. package/components/assistant-ui/attachment.js +103 -75
  24. package/components/assistant-ui/badge.d.ts +1 -1
  25. package/components/assistant-ui/badge.js +17 -17
  26. package/components/assistant-ui/chain-of-thought.d.ts +1 -1
  27. package/components/assistant-ui/composer-add-context.js +9 -9
  28. package/components/assistant-ui/composer-deep-research.js +5 -5
  29. package/components/assistant-ui/composer-harness.js +11 -9
  30. package/components/assistant-ui/composer-trigger-popover.js +45 -34
  31. package/components/assistant-ui/composer.js +59 -59
  32. package/components/assistant-ui/error.js +14 -14
  33. package/components/assistant-ui/file.d.ts +1 -1
  34. package/components/assistant-ui/image.d.ts +1 -1
  35. package/components/assistant-ui/image.js +113 -103
  36. package/components/assistant-ui/markdown-text.js +18 -18
  37. package/components/assistant-ui/message.js +46 -45
  38. package/components/assistant-ui/quote.js +1 -1
  39. package/components/assistant-ui/reasoning.d.ts +1 -1
  40. package/components/assistant-ui/reasoning.js +66 -77
  41. package/components/assistant-ui/suggestions.js +4 -4
  42. package/components/assistant-ui/thread.js +22 -22
  43. package/components/assistant-ui/tool-fallback.js +60 -63
  44. package/components/assistant-ui/tool-group.d.ts +1 -1
  45. package/components/assistant-ui/tool-group.js +36 -42
  46. package/components/audio-waveform.js +25 -24
  47. package/components/autocomplete.d.ts +1 -0
  48. package/components/autocomplete.js +45 -43
  49. package/components/avatar.d.ts +1 -0
  50. package/components/avatar.js +27 -26
  51. package/components/badge.d.ts +1 -1
  52. package/components/breadcrumbs.d.ts +2 -0
  53. package/components/breadcrumbs.js +52 -50
  54. package/components/button.d.ts +2 -2
  55. package/components/button.js +22 -20
  56. package/components/card.js +8 -8
  57. package/components/carousel.js +105 -104
  58. package/components/chart.d.ts +6 -0
  59. package/components/chart.js +743 -672
  60. package/components/checkbox.js +74 -38
  61. package/components/chip.d.ts +1 -1
  62. package/components/code-block.js +3 -3
  63. package/components/collapsible.js +67 -23
  64. package/components/connector-card.js +6 -6
  65. package/components/drawer.d.ts +18 -11
  66. package/components/drawer.js +81 -78
  67. package/components/dropdown.d.ts +2 -0
  68. package/components/dropdown.js +88 -79
  69. package/components/empty-state.d.ts +1 -1
  70. package/components/empty-state.js +7 -7
  71. package/components/field.d.ts +4 -0
  72. package/components/field.js +45 -34
  73. package/components/file-dropzone.js +12 -12
  74. package/components/index.d.ts +3 -0
  75. package/components/index.js +584 -558
  76. package/components/input-field.js +51 -46
  77. package/components/input.js +20 -20
  78. package/components/link.js +9 -9
  79. package/components/modal.d.ts +5 -1
  80. package/components/modal.js +121 -76
  81. package/components/navbar.d.ts +1 -1
  82. package/components/navbar.js +1 -1
  83. package/components/number-field.js +38 -29
  84. package/components/page-header.js +12 -12
  85. package/components/pagination.js +19 -19
  86. package/components/panel.js +2 -2
  87. package/components/pixel-blast-svg.js +3 -3
  88. package/components/pixel-icon.d.ts +4 -0
  89. package/components/pixel-icon.js +210 -164
  90. package/components/popover.d.ts +1 -1
  91. package/components/popover.js +66 -64
  92. package/components/progress-circle.js +36 -32
  93. package/components/progress.js +28 -24
  94. package/components/radio.js +59 -49
  95. package/components/resizable-panel.js +1 -1
  96. package/components/reveal.d.ts +2 -2
  97. package/components/ripple.d.ts +3 -3
  98. package/components/scroll-area.js +17 -16
  99. package/components/segmented.d.ts +1 -0
  100. package/components/segmented.js +39 -36
  101. package/components/select.d.ts +7 -0
  102. package/components/select.js +186 -137
  103. package/components/setting-row.js +45 -42
  104. package/components/sidebar.js +131 -127
  105. package/components/skeleton.js +5 -5
  106. package/components/spinner.d.ts +13 -4
  107. package/components/spinner.js +42 -42
  108. package/components/stepper.js +21 -21
  109. package/components/switch.js +41 -39
  110. package/components/table.d.ts +16 -0
  111. package/components/table.js +393 -260
  112. package/components/tabs.js +149 -137
  113. package/components/toast.js +66 -66
  114. package/components/tooltip.js +2 -2
  115. package/components/tree.js +62 -51
  116. package/components/typography.d.ts +2 -1
  117. package/components/typography.js +33 -32
  118. package/components/ui/button.d.ts +2 -2
  119. package/components/ui/button.js +19 -19
  120. package/components/ui/collapsible.d.ts +1 -5
  121. package/components/ui/dialog.d.ts +3 -3
  122. package/components/ui/dialog.js +95 -58
  123. package/components/ui/tooltip.d.ts +2 -2
  124. package/components/ui/tooltip.js +67 -33
  125. package/components/viz-charts.js +95 -95
  126. package/demo/components/add-to-artifact.js +363 -0
  127. package/demo/lib/artifact-library.js +142 -0
  128. package/demo/lib/artifact-pin-guard.js +12 -0
  129. package/fonts/aribau-grotesk-medium.woff2 +0 -0
  130. package/fonts/aribau-grotesk-regular.woff2 +0 -0
  131. package/fonts.css +11 -11
  132. package/hooks/agents-ui/use-agent-audio-visualizer-aura.js +17 -16
  133. package/hooks/agents-ui/use-agent-audio-visualizer-wave.js +21 -20
  134. package/lib/icons.d.ts +24 -0
  135. package/lib/icons.js +114 -108
  136. package/lib/motion.d.ts +42 -39
  137. package/lib/motion.js +112 -52
  138. package/lib/spinner-mark.d.ts +9 -0
  139. package/lib/spinner-mark.js +98 -0
  140. package/llms.txt +53 -19
  141. package/manifest.json +258 -36
  142. package/package.json +1 -1
  143. package/styles.css +143 -124
  144. package/theme.css +90 -93
  145. package/components/ui/collapsible.js +0 -35
  146. package/fonts/aribau-grotesk-500.otf +0 -0
  147. package/fonts/aribau-grotesk-600.woff2 +0 -0
package/lib/motion.js CHANGED
@@ -1,97 +1,157 @@
1
1
  "use client";
2
- const t = [0.23, 1, 0.32, 1], s = [0.77, 0, 0.175, 1], a = [0.16, 1, 0.3, 1], i = a, r = [0.32, 0.72, 0, 1], o = {
2
+ const a = {
3
+ type: "spring",
4
+ stiffness: 200,
5
+ damping: 20
6
+ }, e = {
7
+ type: "spring",
8
+ stiffness: 200,
9
+ damping: 25
10
+ }, t = {
11
+ type: "spring",
12
+ stiffness: 300,
13
+ damping: 25
14
+ }, s = {
15
+ type: "spring",
16
+ stiffness: 150,
17
+ damping: 25
18
+ }, o = {
19
+ type: "spring",
20
+ stiffness: 150,
21
+ damping: 22
22
+ }, p = {
23
+ type: "spring",
24
+ stiffness: 300,
25
+ damping: 30,
26
+ bounce: 0,
27
+ restDelta: 0.01
28
+ }, n = {
29
+ type: "spring",
30
+ stiffness: 350,
31
+ damping: 35
32
+ }, c = {
33
+ type: "spring",
34
+ stiffness: 100,
35
+ damping: 30
36
+ }, d = {
37
+ type: "spring",
38
+ stiffness: 300,
39
+ damping: 25
40
+ }, f = {
41
+ type: "spring",
42
+ stiffness: 200,
43
+ damping: 16
44
+ }, l = {
45
+ type: "spring",
46
+ stiffness: 240,
47
+ damping: 24
48
+ }, g = {
49
+ type: "spring",
50
+ stiffness: 350,
51
+ damping: 35
52
+ }, m = {
53
+ duration: 0.2,
54
+ ease: "easeOut"
55
+ }, i = {
56
+ duration: 0.2,
57
+ ease: "easeInOut"
58
+ }, y = {
3
59
  hidden: {
4
60
  opacity: 0,
5
61
  transform: "translate3d(0, -4px, 0) scale(0.96)",
6
- transition: { duration: 0.1, ease: t }
62
+ transition: t
7
63
  },
8
64
  visible: {
9
65
  opacity: 1,
10
66
  transform: "translate3d(0, 0, 0) scale(1)",
11
- transition: { duration: 0.15, ease: t }
67
+ transition: t
12
68
  }
13
- }, e = {
69
+ }, h = {
14
70
  hidden: {
15
71
  opacity: 0,
16
72
  transform: "scale(0.96)",
17
- transition: { duration: 0.09, ease: t }
73
+ transition: t
18
74
  },
19
75
  visible: {
20
76
  opacity: 1,
21
77
  transform: "scale(1)",
22
- transition: { duration: 0.14, ease: t }
78
+ transition: t
23
79
  }
24
- }, d = {
80
+ }, b = {
81
+ hidden: {
82
+ opacity: 0,
83
+ transform: "translate3d(0, -4px, 0) scale(0.96)",
84
+ transition: n
85
+ },
86
+ visible: {
87
+ opacity: 1,
88
+ transform: "translate3d(0, 0, 0) scale(1)",
89
+ transition: n
90
+ }
91
+ }, u = {
25
92
  hidden: {
26
93
  opacity: 0,
27
94
  transform: "translate3d(0, 8px, 0) scale(0.96)",
28
- transition: { duration: 0.14, ease: t }
95
+ transition: s
29
96
  },
30
97
  visible: {
31
98
  opacity: 1,
32
99
  transform: "translate3d(0, 0, 0) scale(1)",
33
- transition: { duration: 0.22, ease: t }
100
+ transition: s
34
101
  }
35
- }, c = {
36
- hidden: { opacity: 0, transition: { duration: 0.12, ease: t } },
37
- visible: { opacity: 1, transition: { duration: 0.18, ease: t } }
38
- }, l = {
39
- hidden: { opacity: 0, transition: { duration: 0.14, ease: t } },
40
- visible: { opacity: 1, transition: { duration: 0.22, ease: t } }
41
- }, p = {
42
- duration: 0.24,
43
- ease: a
44
- }, f = {
45
- duration: 0.18,
46
- ease: a
47
- }, m = {
48
- right: { transform: "translate3d(100%, 0, 0)" },
49
- left: { transform: "translate3d(-100%, 0, 0)" },
50
- bottom: { transform: "translate3d(0, 100%, 0)" }
51
- }, y = {
102
+ }, r = {
103
+ hidden: { opacity: 0, transition: i },
104
+ visible: { opacity: 1, transition: i }
105
+ }, v = r, x = {
106
+ right: { transform: "translate3d(100%, 0, 0)", opacity: 0 },
107
+ left: { transform: "translate3d(-100%, 0, 0)", opacity: 0 },
108
+ bottom: { transform: "translate3d(0, 100%, 0)", opacity: 0 }
109
+ }, V = {
52
110
  hidden: { opacity: 0, transform: "translate3d(0, 8px, 0)" },
53
111
  visible: {
54
112
  opacity: 1,
55
113
  transform: "translate3d(0, 0, 0)",
56
- transition: { duration: 0.2, ease: t }
114
+ transition: a
57
115
  }
58
- }, n = {
59
- type: "spring",
60
- stiffness: 420,
61
- damping: 34,
62
- mass: 0.9
63
- }, u = {
116
+ }, w = {
64
117
  hidden: {
65
118
  opacity: 0,
66
119
  transform: "translate3d(0, 16px, 0) scale(0.98)",
67
- transition: n
120
+ transition: t
68
121
  },
69
122
  visible: {
70
123
  opacity: 1,
71
124
  transform: "translate3d(0, 0, 0) scale(1)",
72
- transition: n
125
+ transition: t
73
126
  },
74
127
  exit: {
75
128
  opacity: 0,
76
129
  transform: "translate3d(0, 16px, 0) scale(0.98)",
77
- transition: { duration: 0.14, ease: t }
130
+ transition: t
78
131
  }
79
132
  };
80
133
  export {
81
- r as EASE_DISCLOSURE,
82
- i as EASE_DRAWER,
83
- a as EASE_EXPO_OUT,
84
- s as EASE_IN_OUT,
85
- t as EASE_OUT,
86
- c as backdropVariants,
87
- l as drawerBackdropVariants,
88
- p as drawerEnterTransition,
89
- f as drawerExitTransition,
90
- m as drawerOffset,
91
- o as floatVariants,
92
- d as modalPanelVariants,
93
- y as screenVariants,
94
- n as toastSpring,
95
- u as toastVariants,
96
- e as tooltipVariants
134
+ r as backdropVariants,
135
+ m as checkDrawTransition,
136
+ v as drawerBackdropVariants,
137
+ x as drawerOffset,
138
+ i as fadeTransition,
139
+ y as floatVariants,
140
+ b as menuVariants,
141
+ u as modalPanelVariants,
142
+ V as screenVariants,
143
+ l as springCarousel,
144
+ e as springControl,
145
+ s as springDialog,
146
+ p as springDisclosure,
147
+ a as springEffect,
148
+ n as springHighlight,
149
+ t as springOverlay,
150
+ c as springProgress,
151
+ f as springRadio,
152
+ o as springSheet,
153
+ g as springSidebar,
154
+ d as springSwitch,
155
+ w as toastVariants,
156
+ h as tooltipVariants
97
157
  };
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ /** Shared visual vocabulary used by the public Spinner and the boot shell. */
3
+ export declare const SPINNER_VARIANTS: readonly ["action", "content", "upload", "surface"];
4
+ export type SpinnerVariant = (typeof SPINNER_VARIANTS)[number];
5
+ export interface SpinnerMarkProps extends Omit<React.SVGAttributes<SVGSVGElement>, "children"> {
6
+ variant: SpinnerVariant;
7
+ }
8
+ /** Internal dependency-light renderer; accessibility belongs to its wrapper. */
9
+ export declare function SpinnerMark({ variant, className, ...props }: SpinnerMarkProps): React.JSX.Element;
@@ -0,0 +1,98 @@
1
+ "use client";
2
+ import { jsx as s } from "react/jsx-runtime";
3
+ const A = [
4
+ "action",
5
+ "content",
6
+ "upload",
7
+ "surface"
8
+ ], e = [0, 1, 2, 5, 8, 7, 6, 3], f = Array.from({ length: 9 }, (t, r) => ({
9
+ x: 1 + r % 3 * 5,
10
+ y: 1 + Math.floor(r / 3) * 5
11
+ }));
12
+ function m(t, r) {
13
+ return (t % r + r) % r;
14
+ }
15
+ const l = Array.from(
16
+ { length: e.length },
17
+ (t, r) => {
18
+ const n = new Array(9).fill(0.12);
19
+ n[4] = 0.26;
20
+ for (const o of [r, m(r + 4, e.length)])
21
+ n[e[o]] = 1, n[e[m(o - 1, e.length)]] = 0.68, n[e[m(o + 1, e.length)]] = 0.36;
22
+ return n;
23
+ }
24
+ ), h = [0, 1, 2, 1].map(
25
+ (t) => Array.from({ length: 9 }, (r, n) => {
26
+ const o = Math.floor(n / 3), i = n % 3, a = Math.abs(i - t);
27
+ return a === 0 ? o === 1 ? 1 : 0.78 : a === 1 ? 0.34 : 0.12;
28
+ })
29
+ ), d = [2, 1, 0, 1].map(
30
+ (t) => Array.from({ length: 9 }, (r, n) => {
31
+ const o = Math.floor(n / 3), i = n % 3, a = Math.abs(o - t);
32
+ return a === 0 ? i === 1 ? 1 : 0.78 : a === 1 ? 0.34 : 0.12;
33
+ })
34
+ ), p = [
35
+ [0.14, 0.34, 0.14, 0.34, 1, 0.34, 0.14, 0.34, 0.14],
36
+ [0.4, 1, 0.4, 1, 0.54, 1, 0.4, 1, 0.4],
37
+ [1, 0.56, 1, 0.56, 0.18, 0.56, 1, 0.56, 1],
38
+ [0.4, 1, 0.4, 1, 0.54, 1, 0.4, 1, 0.4]
39
+ ], g = {
40
+ action: { frames: l, duration: 1, staticFrame: 0 },
41
+ content: { frames: h, duration: 1.2, staticFrame: 1 },
42
+ upload: { frames: d, duration: 1.2, staticFrame: 0 },
43
+ surface: { frames: p, duration: 1.4, staticFrame: 0 }
44
+ };
45
+ function u(t) {
46
+ return Number(t.toFixed(3)).toString();
47
+ }
48
+ function y(t, r) {
49
+ return [...t.map((n) => n[r]), t[0][r]].map(u).join(";");
50
+ }
51
+ function F(t) {
52
+ return Array.from(
53
+ { length: t + 1 },
54
+ (r, n) => u(n / t)
55
+ ).join(";");
56
+ }
57
+ function M({ variant: t, className: r, ...n }) {
58
+ const o = g[t], i = F(o.frames.length);
59
+ return /* @__PURE__ */ s(
60
+ "svg",
61
+ {
62
+ viewBox: "0 0 16 16",
63
+ fill: "none",
64
+ shapeRendering: "geometricPrecision",
65
+ className: r,
66
+ ...n,
67
+ children: f.map((a, c) => /* @__PURE__ */ s(
68
+ "rect",
69
+ {
70
+ x: a.x,
71
+ y: a.y,
72
+ width: "4",
73
+ height: "4",
74
+ rx: "1.28",
75
+ fill: "currentColor",
76
+ opacity: o.frames[o.staticFrame][c],
77
+ children: /* @__PURE__ */ s(
78
+ "animate",
79
+ {
80
+ className: "motion-reduce:hidden",
81
+ attributeName: "opacity",
82
+ values: y(o.frames, c),
83
+ keyTimes: i,
84
+ dur: `${o.duration}s`,
85
+ repeatCount: "indefinite",
86
+ calcMode: "linear"
87
+ }
88
+ )
89
+ },
90
+ c
91
+ ))
92
+ }
93
+ );
94
+ }
95
+ export {
96
+ A as SPINNER_VARIANTS,
97
+ M as SpinnerMark
98
+ };
package/llms.txt CHANGED
@@ -11,6 +11,7 @@
11
11
  - `ToastProvider` (from `@actioneer/ads`) — required to render toasts
12
12
  - `<MotionConfig reducedMotion="user">` (from `motion/react`) — honor the OS reduced-motion setting
13
13
  4. Import contract: `import { Button } from "@actioneer/ads";` — the exact named export, never `@actioneer/ads/button`, never an alias, never a local copy.
14
+ 5. Motion contract: every imported component keeps its built-in ADS motion. For consumer-authored semantic state motion, import the matching named preset from `@actioneer/ads`; never copy raw spring values or introduce a separate timing system. Apply principle 3 on every component import/use change.
14
15
 
15
16
  ## Tokens
16
17
 
@@ -34,16 +35,17 @@ Reference semantic roles, never raw color/dimension literals (ads-lint rejects l
34
35
  - `fill` — Quiet fill — secondary buttons, avatars, chips
35
36
  - `fill-foreground` — Quiet fill — secondary buttons, avatars, chips
36
37
  - `table-shell` — Quiet fill — secondary buttons, avatars, chips
38
+ - `artifact-canvas`
37
39
  - `accent`
38
40
  - `accent-foreground`
39
- - `success`
40
- - `success-foreground`
41
- - `warning`
42
- - `warning-foreground`
43
- - `danger`
44
- - `danger-foreground`
45
- - `info`
46
- - `info-foreground`
41
+ - `success` — success-700 on white = 5.48:1 (600 was 3.77:1, failed AA).
42
+ - `success-foreground` — success-700 on white = 5.48:1 (600 was 3.77:1, failed AA).
43
+ - `warning` — Amber-500 fill kept (it IS the caution signal); dark ink foreground
44
+ - `warning-foreground` — Amber-500 fill kept (it IS the caution signal); dark ink foreground
45
+ - `danger` — Amber-500 fill kept (it IS the caution signal); dark ink foreground
46
+ - `danger-foreground` — Amber-500 fill kept (it IS the caution signal); dark ink foreground
47
+ - `info` — Amber-500 fill kept (it IS the caution signal); dark ink foreground
48
+ - `info-foreground` — Amber-500 fill kept (it IS the caution signal); dark ink foreground
47
49
  - `border-primary`
48
50
  - `border-secondary`
49
51
  - `border-tertiary`
@@ -71,21 +73,25 @@ Delineate SURFACES (cards, panels, sidebars, page regions) with color contrast,
71
73
 
72
74
  The single shadow-elevation token is an affordance: it goes ONLY on surfaces the user can act on. Never elevate something that can't be clicked. There is no shadow scale.
73
75
 
74
- - Do: Elevate actionable surfaces: pressable/hoverable cards, primary CTAs, control thumbs (Switch, Slider, active pills), and interactive floating layers (Modal, Drawer, Popover, Dropdown, listboxes, Toast).
76
+ - Do: Elevate actionable surfaces: pressable/hoverable cards, primary CTAs, control thumbs (Switch, Slider, active tab segments), and interactive floating layers (Modal, Drawer, Popover, Dropdown, listboxes, Toast).
75
77
  - Do: Keep static surfaces flat: Panel, plain Card, Kbd, Navbar, headers, rails, docs boxes, Tooltip, InlineDrawer — they read by fill/color.
76
78
  - Do: Ask 'can the user click this surface?' — if no, it's flat.
77
79
  - Don't: Reintroduce a shadow scale (shadow-xs/sm/md/lg/xl) — there is one token only, shadow-elevation.
78
80
  - Don't: Put a shadow on a non-interactive surface for decoration.
79
81
 
80
- ### 3. Motion follows the design-engineering guide [lint: unbounded-transition, sluggish-easing, zero-scale-entrance, undersized-zoom-entrance]
82
+ ### 3. Motion follows the interaction [lint: unbounded-transition, sluggish-easing, zero-scale-entrance, undersized-zoom-entrance, raw-spring-config]
81
83
 
82
- Every easing/duration/scale flows from a token (--ease-*, --duration-*, --scale-press), mirrored for Motion in src/lib/motion.ts. UI animations stay under 300ms, exits run faster than enters, and reduced motion is respected everywhere.
84
+ Component motion follows the closest Animate UI interaction pattern, using role-specific presets defined in src/lib/motion.ts and exported from the ADS root barrel. Direct manipulation stays immediate, small CSS feedback stays local, and reduced motion is respected everywhere.
83
85
 
84
- - Do: Use strong curves only — the ease-out utility is the right default; overlays scale in origin-aware from their trigger.
85
- - Do: Give pressable elements a --scale-press on :active (text/link exempt); start entrances ≥ scale 0.95 with opacity.
86
- - Do: Respect reduced motion: keep opacity/color fades, drop movement.
87
- - Don't: Use a slow-starting (accelerating) easing on UI, an unbounded all-property transition, a scale-from-zero entrance, or a UI duration at or over 300ms.
86
+ - Do: Treat motion as part of every ADS component import: preserve the component's built-in motion, and import any composition-level preset from the ADS root barrel.
87
+ - Do: Map the component family before choosing motion: tabs/segments use control; checkbox/radio/switch use selection; menus use highlight; popovers/tooltips use overlay; modal/drawer use dialog/sheet; accordion/collapsible use disclosure; progress, carousel, and sidebar use their matching presets.
88
+ - Do: Keep sliders, drag-resize, scrolling, and other pointer-following interactions immediate; motion begins after the committed value or destination changes.
89
+ - Do: Give pressable elements local active feedback (text/link exempt); start entrances ≥ scale 0.95 with opacity.
90
+ - Do: Wrap Motion components in MotionConfig reducedMotion='user'; keep useful opacity/color feedback and drop spatial movement.
91
+ - Don't: Invent raw spring values inside a component, recreate a global duration/easing token scale, use an unbounded all-property transition, or start an entrance at scale zero.
92
+ - Don't: Override or duplicate the motion already shipped inside an imported ADS component.
88
93
  - Don't: Animate keyboard-initiated or 100×/day actions (e.g. a command-palette toggle).
94
+ - Don't: Add motion to a component only because it is visible; static structure and decorative chrome stay still.
89
95
 
90
96
  ### 4. Icons: Hugeicons, stroke only [lint: icon-package-import]
91
97
 
@@ -164,12 +170,37 @@ When tabs and a search field control the same content, they share one responsive
164
170
 
165
171
  ## Components
166
172
 
173
+ Before using any component below, preserve its built-in motion and apply the motion contract in Setup step 5.
174
+
167
175
  ### Primitives / utilities
168
176
 
169
177
  - [TooltipProvider] — component [docs](https://ads.actioneer.dev/#/tooltip)
170
178
  - [InteractiveProps] — TypeScript type
179
+ - [backdropVariants] — utility
180
+ - [checkDrawTransition] — utility
171
181
  - [cn] — utility
182
+ - [drawerBackdropVariants] — utility
183
+ - [drawerOffset] — utility
184
+ - [fadeTransition] — utility
185
+ - [floatVariants] — utility
172
186
  - [interactive] — utility
187
+ - [menuVariants] — utility
188
+ - [modalPanelVariants] — utility
189
+ - [screenVariants] — utility
190
+ - [springCarousel] — utility
191
+ - [springControl] — utility
192
+ - [springDialog] — utility
193
+ - [springDisclosure] — utility
194
+ - [springEffect] — utility
195
+ - [springHighlight] — utility
196
+ - [springOverlay] — utility
197
+ - [springProgress] — utility
198
+ - [springRadio] — utility
199
+ - [springSheet] — utility
200
+ - [springSidebar] — utility
201
+ - [springSwitch] — utility
202
+ - [toastVariants] — utility
203
+ - [tooltipVariants] — utility
173
204
 
174
205
  ### Foundations
175
206
 
@@ -193,7 +224,7 @@ When tabs and a search field control the same content, they share one responsive
193
224
  - [ScrollBar] — component [docs](https://ads.actioneer.dev/#/review/scroll-area)
194
225
  - [SettingList] — component (variants: isPressable: true|false) [docs](https://ads.actioneer.dev/#/review/setting-row)
195
226
  - [SettingRow] — component (variants: isPressable: true|false) [docs](https://ads.actioneer.dev/#/review/setting-row)
196
- - [Spinner] — Use for an indeterminate loading state (e.g. inside a Button's isLoading, or standalone while content is fetching) — not for measurable/determinate progress. (variants: size: sm|md|lg; color: current|primary|muted) [docs](https://ads.actioneer.dev/#/spinner)
227
+ - [Spinner] — Use the nine-squircle Spinner for indeterminate work; choose its variant by work scope and use Progress or ProgressCircle when completion can be measured. (variants: size: xs|sm|md|lg; color: current|primary|muted) [docs](https://ads.actioneer.dev/#/spinner)
197
228
  - [Stepper] — component (variants: status: complete|current|upcoming|error; size: sm|md) [docs](https://ads.actioneer.dev/#/review/stepper)
198
229
  - [Text] — Use Text for any body copy, caption, or inline run of prose instead of a raw p/span tag. [docs](https://ads.actioneer.dev/#/typography)
199
230
  - [Tooltip] — Use to label a single hover/focus-triggered element (icon-only buttons, avatars, truncated text) with a short informational hint — not for actions or content that needs to stay open. [docs](https://ads.actioneer.dev/#/tooltip)
@@ -215,6 +246,7 @@ When tabs and a search field control the same content, they share one responsive
215
246
  - [SettingListProps] — TypeScript type
216
247
  - [SettingRowProps] — TypeScript type
217
248
  - [SpinnerProps] — TypeScript type
249
+ - [SpinnerVariant] — TypeScript type
218
250
  - [StepperProps] — TypeScript type
219
251
  - [StepperStatus] — TypeScript type
220
252
  - [StepperStep] — TypeScript type
@@ -225,6 +257,7 @@ When tabs and a search field control the same content, they share one responsive
225
257
  - [fileDropzoneVariants] — utility
226
258
  - [inputBaseClass] — utility
227
259
  - [settingRowVariants] — utility
260
+ - [SPINNER_VARIANTS] — utility
228
261
  - [stepperMarkerVariants] — utility
229
262
 
230
263
  ### Form controls
@@ -237,7 +270,7 @@ When tabs and a search field control the same content, they share one responsive
237
270
  - [NumberField] — Use for a bounded numeric quantity (e.g. seats, width, count) that benefits from stepper buttons and min/max clamping, not free-form numeric text entry. [docs](https://ads.actioneer.dev/#/number-field)
238
271
  - [Radio] — Use for choosing exactly one option from a small, fully visible set — wrap Radio options in a RadioGroup that owns the shared name and controlled value. [docs](https://ads.actioneer.dev/#/radio)
239
272
  - [RadioGroup] — component [docs](https://ads.actioneer.dev/#/radio)
240
- - [SegmentedControl] — Use for a small set (2-4) of mutually exclusive, always-visible options — like a range or view-mode switcher — not for navigation or long lists. (variants: size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/segmented)
273
+ - [SegmentedControl] — Use for a small set (2-4) of mutually exclusive, always-visible options — like a range or view-mode switcher — not for navigation or long lists. Radius follows control size: 4px at sm and 8px at md/lg; tracks and options are never fully rounded. (variants: size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/segmented)
241
274
  - [Select] — Use for a single choice from a closed list of options in a form, especially when pairing with Field for a labeled control. (variants: size: sm|md|lg) [docs](https://ads.actioneer.dev/#/select)
242
275
  - [Slider] — Use for a single controlled numeric value picked from a bounded range (volume, brightness, threshold) — pair with Field or Label/Text for an accessible, labeled control. [docs](https://ads.actioneer.dev/#/slider)
243
276
  - [Switch] — Use for a single binary on/off preference that applies immediately, not as part of a form submitted later. [docs](https://ads.actioneer.dev/#/switch)
@@ -381,7 +414,7 @@ When tabs and a search field control the same content, they share one responsive
381
414
  - [TableRow] — component [docs](https://ads.actioneer.dev/#/table)
382
415
  - [TabList] — component (variants: variant: primary|secondary|pill; orientation: horizontal|vertical; size: sm|md|lg) [docs](https://ads.actioneer.dev/#/tabs)
383
416
  - [TabPanel] — component (variants: variant: primary|secondary|pill; orientation: horizontal|vertical; size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/tabs)
384
- - [Tabs] — Use Tabs to switch between mutually exclusive views/sections that share the same page context, not for page-level navigation. Always reach for the primary (pill) variant — it is the default; use secondary only when explicitly asked for it. When Tabs and a scoped search field coexist, compose one responsive control row with tabs leading and search trailing; do not stack search above tabs at widths where both fit. (variants: variant: primary|secondary|pill; orientation: horizontal|vertical; size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/tabs)
417
+ - [Tabs] — Use Tabs to switch between mutually exclusive views/sections that share the same page context, not for page-level navigation. Always reach for the primary recessed-track variant — it is the default; use secondary only when explicitly asked for it. Tab radius follows control size (4px sm, 8px md/lg), never rounded-full. When Tabs and a scoped search field coexist, compose one responsive control row with tabs leading and search trailing; do not stack search above tabs at widths where both fit. (variants: variant: primary|secondary|pill; orientation: horizontal|vertical; size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/tabs)
385
418
  - [TabSeparator] — component (variants: variant: primary|secondary|pill; orientation: horizontal|vertical; size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/tabs)
386
419
  - [Timeline] — Use for a vertical rail of dated events — version history, audit trails, activity/status feeds. [docs](https://ads.actioneer.dev/#/timeline)
387
420
  - [TimelineItem] — component [docs](https://ads.actioneer.dev/#/timeline)
@@ -582,6 +615,7 @@ When tabs and a search field control the same content, they share one responsive
582
615
  - [ProgressCircle] — Use for a compact circular loading/progress indicator (determinate or indeterminate) where a linear bar doesn't fit, e.g. inline with a caption or a small avatar-sized control. [docs](https://ads.actioneer.dev/#/progress-circle)
583
616
  - [Ripple] — component [docs](https://ads.actioneer.dev/#/ripple)
584
617
  - [Skeleton] — Placeholder the shape of content that's still loading — size it via className and pair with circle for avatars. [docs](https://ads.actioneer.dev/#/skeleton)
618
+ - [AgentIconColorPreset] — TypeScript type
585
619
  - [AgentIconName] — TypeScript type
586
620
  - [AgentIconProps] — TypeScript type
587
621
  - [AgentIconState] — TypeScript type
@@ -610,7 +644,7 @@ When tabs and a search field control the same content, they share one responsive
610
644
  - [NavbarItem] — component (variants: justify: start|center|end) [docs](https://ads.actioneer.dev/#/navbar)
611
645
  - [PageHeader] — Use for every page title row; supply onBack to anchor an icon-only back arrow immediately before the title, never in the trailing actions area. [docs](https://ads.actioneer.dev/#/page-header)
612
646
  - [Pagination] — Use for navigating multi-page numbered content — table footers, search results, or any list too long for one screen. [docs](https://ads.actioneer.dev/#/pagination)
613
- - [Sidebar] — Use as the app's left navigation rail. The canonical Actioneer shell composes SidebarBrand with persistent header actions, SidebarAction above grouped SidebarItems, optional attention counts and SidebarHistory, then SidebarAccount in a pinned footer. Its opt-in collapsed icon-rail mode (⌘B/Ctrl-B) is shared automatically by every sub-part. [docs](https://ads.actioneer.dev/#/sidebar)
647
+ - [Sidebar] — Use as an app's vertical navigation rail. The canonical Actioneer shell pairs one collapsible global product rail with one fixed contextual Sidebar inside the shared workspace Panel; only the global rail owns a collapse control. Compose SidebarBrand, grouped SidebarItems, optional SidebarHistory, and SidebarAccount as the area requires. [docs](https://ads.actioneer.dev/#/sidebar)
614
648
  - [SidebarAccount] — component [docs](https://ads.actioneer.dev/#/sidebar)
615
649
  - [SidebarAction] — component [docs](https://ads.actioneer.dev/#/sidebar)
616
650
  - [SidebarBrand] — component [docs](https://ads.actioneer.dev/#/sidebar)