@actioneer/ads 1.0.9 → 1.0.10

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 (51) hide show
  1. package/DESIGN.md +98 -57
  2. package/README.md +19 -7
  3. package/components/answer.js +1 -1
  4. package/components/assistant-ui/composer-harness.js +13 -10
  5. package/components/body-page-header.d.ts +9 -4
  6. package/components/body-page-header.js +10 -10
  7. package/components/breadcrumbs.js +22 -22
  8. package/components/card.js +18 -18
  9. package/components/chart.d.ts +9 -0
  10. package/components/chart.js +738 -717
  11. package/components/chip.js +12 -12
  12. package/components/collection-header.js +4 -4
  13. package/components/connector-card.js +30 -30
  14. package/components/date-range-picker.js +1 -1
  15. package/components/detail-list.d.ts +28 -0
  16. package/components/detail-list.js +52 -0
  17. package/components/drawer.d.ts +38 -15
  18. package/components/drawer.js +150 -86
  19. package/components/empty-state.d.ts +3 -2
  20. package/components/empty-state.js +22 -22
  21. package/components/field.d.ts +16 -0
  22. package/components/field.js +63 -42
  23. package/components/file-dropzone.d.ts +15 -4
  24. package/components/file-dropzone.js +100 -64
  25. package/components/filter-bar.d.ts +44 -0
  26. package/components/filter-bar.js +89 -0
  27. package/components/index.d.ts +3 -0
  28. package/components/index.js +526 -513
  29. package/components/input-field.d.ts +1 -1
  30. package/components/input-field.js +24 -22
  31. package/components/modal.js +56 -53
  32. package/components/panel.js +26 -27
  33. package/components/sidebar.js +54 -54
  34. package/components/sparkline.d.ts +30 -0
  35. package/components/sparkline.js +69 -0
  36. package/demo/components/add-to-artifact.js +5 -2
  37. package/examples/README.md +4 -2
  38. package/examples/call-logs-screen.tsx +381 -0
  39. package/examples/campaign-analysis-screen.tsx +114 -72
  40. package/examples/campaigns-screen.tsx +218 -160
  41. package/examples/guardrails-settings-screen.tsx +123 -0
  42. package/fonts/geist-variable.woff2 +0 -0
  43. package/fonts.css +12 -17
  44. package/lib/icons.js +3 -3
  45. package/llms.txt +107 -39
  46. package/manifest.json +3100 -892
  47. package/package.json +1 -1
  48. package/styles.css +102 -59
  49. package/theme.css +81 -37
  50. package/fonts/aribau-grotesk-medium.woff2 +0 -0
  51. package/fonts/aribau-grotesk-regular.woff2 +0 -0
package/fonts.css CHANGED
@@ -1,24 +1,19 @@
1
1
  /* @actioneer/ads — generated by scripts/build-lib-styles.mjs. Do not edit. */
2
2
  @import "@fontsource-variable/jetbrains-mono/wght.css";
3
3
 
4
- /* Aribau Grotesk — ADS UI typeface.
5
- TWO physical faces, both served compressed (woff2):
6
- • Regular → `font-normal` (weight 100–499)
7
- • Medium → `font-medium` (weight 500)
8
- There is NO semibold or bold face. The broad face range keeps legacy
9
- consumers on the real Medium file, while ADS source uses only 400 and 500.
10
- `font-synthesis-weight: none` (index.css) blocks faux bolding. */
11
- @font-face {
12
- font-family: "Aribau Grotesk";
13
- src: url("./fonts/aribau-grotesk-regular.woff2") format("woff2");
14
- font-weight: 100 499;
15
- font-style: normal;
16
- font-display: swap;
17
- }
4
+ /* Geist — ADS body and UI typeface (SIL Open Font License, bundled).
5
+ One variable face covers every weight; ADS source uses only Regular (400)
6
+ and Medium (500). `font-synthesis-weight: none` (index.css) blocks faux
7
+ bolding.
8
+
9
+ Season Mix — ADS heading typeface (`--font-heading`). It is a licensed
10
+ font, so ADS does NOT bundle or redistribute it: each product declares its
11
+ own `@font-face { font-family: "Season Mix"; … }` from its licensed file.
12
+ Without it, headings fall back to the platform serif. */
18
13
  @font-face {
19
- font-family: "Aribau Grotesk";
20
- src: url("./fonts/aribau-grotesk-medium.woff2") format("woff2");
21
- font-weight: 500 900;
14
+ font-family: "Geist";
15
+ src: url("./fonts/geist-variable.woff2") format("woff2");
16
+ font-weight: 100 900;
22
17
  font-style: normal;
23
18
  font-display: swap;
24
19
  }
package/lib/icons.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsxs as p, Fragment as d, jsx as a } from "react/jsx-runtime";
3
3
  import * as r from "react";
4
- import { Code as $, Check as k, Copy as S, FileText as f, UploadSimple as P, X as T, EyeSlash as w, Eye as L, MagnifyingGlass as A, Minus as m, Plus as x, CaretDown as B, FunnelSimple as I, Info as y, WarningCircle as U, Warning as F, CheckCircle as M, CaretRight as D, CaretUp as O, ArrowsDownUp as b, ChatCircle as R, ArrowUpRight as v, Clock as H, Database as E, ArrowSquareOut as G, Table as W, CaretLeft as z, CornersOut as V, Magnet as N, Tray as j, ArrowLeft as X, DotsThree as Q, User as q, XCircle as _, CircleDashed as J, ArrowsClockwise as K, Paperclip as Y, Quotes as Z, At as ee, Lightning as oe, Sparkle as te, File as ne, DownloadSimple as se, Image as C, BracketsCurly as ae, MusicNotes as re, VideoCamera as ce, ImageBroken as ie, Pulse as le, Archive as he, ArrowDown as Ce, ArrowRight as ge, ArrowUp as ue, Scroll as pe, Bell as de, Stack as $e, BookOpen as ke, Brain as Se, CalendarBlank as fe, Phone as Pe, ListChecks as Te, Cube as we, DotsNine as Le, Folder as Ae, FolderOpen as me, Gauge as xe, GitBranch as Be, Hash as Ie, ClockCounterClockwise as ye, House as Ue, SquaresFour as Fe, Leaf as Me, Lightbulb as De, Link as Oe, CircleNotch as be, SignOut as Re, Envelope as ve, Microphone as He, MicrophoneSlash as Ee, DotsThreeVertical as Ge, Palette as We, SidebarSimple as ze, Pause as Ve, PencilSimple as Ne, PhoneIncoming as je, PhoneSlash as Xe, ChartPie as Qe, Play as qe, Plug as _e, Presentation as Je, Rocket as Ke, Gear as Ye, Shapes as Ze, ShareNetwork as eo, Star as oo, Stop as to, ArrowsLeftRight as no, Target as so, Binoculars as ao, TextB as ro, TextT as co, TextItalic as io, TextStrikethrough as lo, TextUnderline as ho, ToggleRight as Co, Trash as go, Users as uo, Wrench as po } from "@phosphor-icons/react";
4
+ import { Info as $, Code as k, Check as S, Copy as f, FileText as P, UploadSimple as T, X as w, EyeSlash as L, Eye as A, MagnifyingGlass as m, Minus as x, Plus as B, CaretDown as I, FunnelSimple as y, WarningCircle as U, Warning as F, CheckCircle as M, CaretRight as D, CaretUp as O, ArrowsDownUp as b, ChatCircle as R, ArrowUpRight as v, Clock as H, Database as E, ArrowSquareOut as G, Table as W, CaretLeft as z, CornersOut as V, Magnet as N, Tray as j, ArrowLeft as X, DotsThree as Q, User as q, XCircle as _, CircleDashed as J, ArrowsClockwise as K, Paperclip as Y, Quotes as Z, At as ee, Lightning as oe, Sparkle as te, File as ne, DownloadSimple as se, Image as C, BracketsCurly as ae, MusicNotes as re, VideoCamera as ce, ImageBroken as ie, Pulse as le, Archive as he, ArrowDown as Ce, ArrowRight as ge, ArrowUp as ue, Scroll as pe, Bell as de, Stack as $e, BookOpen as ke, Brain as Se, CalendarBlank as fe, Phone as Pe, ListChecks as Te, Cube as we, DotsNine as Le, Folder as Ae, FolderOpen as me, Gauge as xe, GitBranch as Be, Hash as Ie, ClockCounterClockwise as ye, House as Ue, SquaresFour as Fe, Leaf as Me, Lightbulb as De, Link as Oe, CircleNotch as be, SignOut as Re, Envelope as ve, Microphone as He, MicrophoneSlash as Ee, DotsThreeVertical as Ge, Palette as We, SidebarSimple as ze, Pause as Ve, PencilSimple as Ne, PhoneIncoming as je, PhoneSlash as Xe, ChartPie as Qe, Play as qe, Plug as _e, Presentation as Je, Rocket as Ke, Gear as Ye, Shapes as Ze, ShareNetwork as eo, Star as oo, Stop as to, ArrowsLeftRight as no, Target as so, Binoculars as ao, TextB as ro, TextT as co, TextItalic as io, TextStrikethrough as lo, TextUnderline as ho, ToggleRight as Co, Trash as go, Users as uo, Wrench as po } from "@phosphor-icons/react";
5
5
  const $o = r.createContext(!1), ko = /* @__PURE__ */ new Set(["Info"]), So = new Set(
6
6
  [
7
7
  "FunnelSimple",
@@ -58,10 +58,10 @@ function e(o, c) {
58
58
  });
59
59
  return i.displayName = c, i;
60
60
  }
61
- const wo = e(Ce, "ArrowDown"), Lo = e(X, "ArrowLeft"), Ao = e(ge, "ArrowRight"), mo = e(ue, "ArrowUp"), xo = e(v, "ArrowUpRight"), Bo = e(B, "ChevronDown"), Io = e(z, "ChevronLeft"), yo = e(D, "ChevronRight"), Uo = e(O, "ChevronUp"), Fo = e(b, "SortIcon"), Mo = e(no, "SwapHorizontal"), Do = e(G, "ExternalLink"), Oo = e(ze, "PanelLeft"), bo = e(ee, "At"), Ro = e(Pe, "Call"), vo = e(je, "PhoneIncoming"), Ho = e(T, "Close"), Eo = e(_, "CloseCircle"), Go = e(S, "Copy"), Wo = e(se, "Download"), zo = e(Re, "LogOut"), Vo = e(He, "Mic"), No = e(Ee, "MicOff"), jo = e(Xe, "PhoneOff"), Xo = e(Ne, "Pencil"), Qo = e(Z, "Quote"), qo = e(L, "Eye"), _o = e(w, "EyeOff"), Jo = e(Ie, "Hash"), Ko = e(C, "ImageUpload"), Yo = e(P, "Upload"), Zo = e(co, "TextFont"), et = e(ro, "TextBold"), ot = e(io, "TextItalicStyle"), tt = e(lo, "TextStrike"), nt = e(
61
+ const wo = e(Ce, "ArrowDown"), Lo = e(X, "ArrowLeft"), Ao = e(ge, "ArrowRight"), mo = e(ue, "ArrowUp"), xo = e(v, "ArrowUpRight"), Bo = e(I, "ChevronDown"), Io = e(z, "ChevronLeft"), yo = e(D, "ChevronRight"), Uo = e(O, "ChevronUp"), Fo = e(b, "SortIcon"), Mo = e(no, "SwapHorizontal"), Do = e(G, "ExternalLink"), Oo = e(ze, "PanelLeft"), bo = e(ee, "At"), Ro = e(Pe, "Call"), vo = e(je, "PhoneIncoming"), Ho = e(w, "Close"), Eo = e(_, "CloseCircle"), Go = e(f, "Copy"), Wo = e(se, "Download"), zo = e(Re, "LogOut"), Vo = e(He, "Mic"), No = e(Ee, "MicOff"), jo = e(Xe, "PhoneOff"), Xo = e(Ne, "Pencil"), Qo = e(Z, "Quote"), qo = e(A, "Eye"), _o = e(L, "EyeOff"), Jo = e(Ie, "Hash"), Ko = e(C, "ImageUpload"), Yo = e(T, "Upload"), Zo = e(co, "TextFont"), et = e(ro, "TextBold"), ot = e(io, "TextItalicStyle"), tt = e(lo, "TextStrike"), nt = e(
62
62
  ho,
63
63
  "TextUnderlineStyle"
64
- ), st = e(Co, "ToggleOn"), at = e(fe, "Calendar"), rt = e(H, "Clock"), ct = e($, "Code"), it = e(to, "Stop"), lt = e(N, "Magnet"), ht = e(V, "Maximize"), Ct = e(m, "Minus"), gt = e(Q, "MoreHorizontal"), ut = e(Ge, "MoreVertical"), pt = e(Le, "DragHandle"), dt = e(Oe, "Link"), $t = e(x, "Plus"), kt = e(K, "Refresh"), St = e(pe, "AuditTrail"), ft = e(A, "Search"), Pt = e(eo, "Share"), Tt = e(go, "Trash"), wt = e(k, "Check"), Lt = e(be, "Loader"), At = e(M, "CheckCircle"), mt = e(y, "Info"), xt = e(F, "Warning"), Bt = e(de, "Bell"), It = e(U, "WarningCircle"), yt = e(le, "Activity"), Ut = e(R, "AgentChat"), Ft = e(oe, "Bolt"), Mt = e(ke, "BookOpen"), Dt = e(Se, "Brain"), Ot = e(Te, "CheckList"), bt = e(we, "Component"), Rt = e(E, "Database"), vt = e(W, "Table"), Ht = e(I, "Filter"), Et = e(he, "Archive"), Gt = e(ne, "File"), Wt = e(f, "FileText"), zt = e(Ae, "Folder"), Vt = e(C, "Image"), Nt = e(ie, "ImageOff"), jt = e(re, "Music"), Xt = e(ce, "Video"), Qt = e(ae, "Braces"), qt = e(me, "FolderOpen"), _t = e(xe, "Gauge"), Jt = e(Be, "GitBranch"), Kt = e(ye, "HistoryClock"), Yt = e(Ue, "Home"), Zt = e($e, "Blocks"), en = e(j, "Inbox"), on = e(De, "Lightbulb"), tn = e(Me, "Leaf"), nn = e(Fe, "LayoutGrid"), sn = e(ve, "Mail"), an = e(We, "Palette"), rn = e(Qe, "PieChart"), cn = e(_e, "Plug"), ln = e(Ke, "Rocket"), hn = e(Ye, "Settings"), Cn = e(Ze, "Shapes"), gn = e(te, "Sparkles"), un = e(oo, "Star"), pn = e(ao, "Telescope"), dn = e(so, "Target"), $n = e(q, "User"), kn = e(uo, "Users"), Sn = e(qe, "Play"), fn = e(Je, "Presentation"), Pn = e(Ve, "Pause"), Tn = e(Y, "Paperclip"), wn = e(J, "CircleDashed"), Ln = e(po, "Wrench");
64
+ ), st = e(Co, "ToggleOn"), at = e(fe, "Calendar"), rt = e(H, "Clock"), ct = e(k, "Code"), it = e(to, "Stop"), lt = e(N, "Magnet"), ht = e(V, "Maximize"), Ct = e(x, "Minus"), gt = e(Q, "MoreHorizontal"), ut = e(Ge, "MoreVertical"), pt = e(Le, "DragHandle"), dt = e(Oe, "Link"), $t = e(B, "Plus"), kt = e(K, "Refresh"), St = e(pe, "AuditTrail"), ft = e(m, "Search"), Pt = e(eo, "Share"), Tt = e(go, "Trash"), wt = e(S, "Check"), Lt = e(be, "Loader"), At = e(M, "CheckCircle"), mt = e($, "Info"), xt = e(F, "Warning"), Bt = e(de, "Bell"), It = e(U, "WarningCircle"), yt = e(le, "Activity"), Ut = e(R, "AgentChat"), Ft = e(oe, "Bolt"), Mt = e(ke, "BookOpen"), Dt = e(Se, "Brain"), Ot = e(Te, "CheckList"), bt = e(we, "Component"), Rt = e(E, "Database"), vt = e(W, "Table"), Ht = e(y, "Filter"), Et = e(he, "Archive"), Gt = e(ne, "File"), Wt = e(P, "FileText"), zt = e(Ae, "Folder"), Vt = e(C, "Image"), Nt = e(ie, "ImageOff"), jt = e(re, "Music"), Xt = e(ce, "Video"), Qt = e(ae, "Braces"), qt = e(me, "FolderOpen"), _t = e(xe, "Gauge"), Jt = e(Be, "GitBranch"), Kt = e(ye, "HistoryClock"), Yt = e(Ue, "Home"), Zt = e($e, "Blocks"), en = e(j, "Inbox"), on = e(De, "Lightbulb"), tn = e(Me, "Leaf"), nn = e(Fe, "LayoutGrid"), sn = e(ve, "Mail"), an = e(We, "Palette"), rn = e(Qe, "PieChart"), cn = e(_e, "Plug"), ln = e(Ke, "Rocket"), hn = e(Ye, "Settings"), Cn = e(Ze, "Shapes"), gn = e(te, "Sparkles"), un = e(oo, "Star"), pn = e(ao, "Telescope"), dn = e(so, "Target"), $n = e(q, "User"), kn = e(uo, "Users"), Sn = e(qe, "Play"), fn = e(Je, "Presentation"), Pn = e(Ve, "Pause"), Tn = e(Y, "Paperclip"), wn = e(J, "CircleDashed"), Ln = e(po, "Wrench");
65
65
  export {
66
66
  yt as Activity,
67
67
  Ut as AgentChat,
package/llms.txt CHANGED
@@ -5,7 +5,7 @@
5
5
  ## Setup
6
6
 
7
7
  1. Install: `npm install @actioneer/ads` (or run `npx @actioneer/ads init`).
8
- 2. In your global stylesheet, after `@import "tailwindcss";`, add `@import "@actioneer/ads/styles.css";` — it carries the `@theme` tokens, the Aribau `@font-face`, and the `@source` that makes Tailwind scan ADS classes. Imported standalone (not into the tailwindcss graph) its `@theme` is inert and no tokens emit.
8
+ 2. In your global stylesheet, after `@import "tailwindcss";`, add `@import "@actioneer/ads/styles.css";` — it carries the `@theme` tokens, the Geist `@font-face`, and the `@source` that makes Tailwind scan ADS classes. Imported standalone (not into the tailwindcss graph) its `@theme` is inert and no tokens emit.
9
9
  3. Wrap the app root with the required providers:
10
10
  - `TooltipProvider` (from `@actioneer/ads`) — wrap the app; the vendored tooltip/attachment chips crash without an ancestor provider
11
11
  - `ToastProvider` (from `@actioneer/ads`) — required to render toasts
@@ -79,26 +79,32 @@ The house rules for every ADS UI. `[lint]` = `@actioneer/ads-lint` auto-checks i
79
79
 
80
80
  ### 1. Prefer fills & elevation over strokes — but keep a balance (~75/25) [judgment]
81
81
 
82
- Delineate SURFACES (cards, panels, sidebars, page regions) with color contrast, elevation, and spacing — not borders. Keep no more than two persistent neutral layers in one composition: panels establish hierarchy; embedded items express state. Aim for ~75% shadow/fill, 25% strokes: form controls and floating menus keep a subtle border so they read as interactive; surfaces do not.
82
+ Delineate SURFACES (cards, panels, sidebars, page regions) with color contrast, elevation, and spacing — not decorative borders. Keep no more than two persistent neutral layers in one composition: panels establish hierarchy; embedded items express state. Aim for ~75% shadow/fill, 25% strokes: form controls and floating menus keep a subtle border so they read as interactive. Two kinds of 1px WG4 line follow opposite rules (the window panel style, user-mandated 2026-11-12): STRUCTURAL hairlines that split the page into its parts — under a header bar, under a DrawerHeader and above a DrawerFooter, between the page and an attached Drawer, between the sidebar and the page — run full width, wall to wall; ROW dividers between items inside one region stay inset to the content.
83
83
 
84
84
  - Do: Establish hierarchy with at most two persistent layers: bg-background for the screen ground and bg-card/bg-elevated for the primary surface.
85
85
  - Do: Inside a white Panel or Card, keep rows and items transparent at rest; group them with spacing or inset dividers, use bg-muted for hover/selection, and reserve bg-surface for one continuous semantic recess such as an editor or table tray.
86
86
  - Do: Use border-border for outline buttons and lightweight action rows; reserve border-input for form controls (input, select, textarea, checkbox, radio, segmented-control track) and floating menus (dropdown, popover, listboxes).
87
- - Do: Keep strokes on focus rings, the outline Button/Badge/Chip variants, Kbd, Divider, the Tree connector rail, and functional color swatches.
87
+ - Do: Keep strokes on focus rings, the outline Button/Badge/Chip variants, Kbd, Divider, the Tree connector rail, functional color swatches, the WG4 edge of resting cards and the app window, and the structural hairlines.
88
+ - Do: Run structural hairlines edge to edge: the 64px header bar's bottom line, the DrawerHeader/DrawerFooter lines, the full-height line on an attached Drawer's leading edge, the sidebar's edge inside the app window.
89
+ - Do: Inset row dividers: put the padding on the container and border-b on each row, so the line stops at the content edge.
88
90
  - Don't: Add a border to a surface to separate or group it — use fill/elevation/spacing instead.
89
91
  - Don't: Alternate persistent neutral fills inside one panel (for example white Panel → grey item → white child); flatten the item or promote the recess to the container.
90
92
  - Don't: Give a filled control no stroke on the tinted canvas — it disappears; it needs a crisp edge.
93
+ - Don't: Stop a structural hairline short of the walls, or run a row divider full-bleed (divide-y on a container whose rows carry their own px-*).
91
94
 
92
- ### 2. Five shadows, floating layers only [judgment]
95
+ ### 2. Eight shadows: floating layers, resting cards, the app window, the active nav item [judgment]
93
96
 
94
- ADS has five shadow tokens: shadow-0 (flat, the default), shadow-float, shadow-overlay, and the two table scroll-hint smudges. Only a layer that floats above the page may carry float or overlay; everything in the page is flat.
97
+ ADS has eight shadow tokens: shadow-0 (flat, the default), shadow-float, shadow-overlay, the two table scroll-hint smudges, the two resting-surface lifts shadow-card and shadow-window, and shadow-nav-active for the active sidebar item (user-mandated 2026-11-12). Only a layer that floats above the page may carry float or overlay; resting cards (Card, stat/chart cards, ConnectorCard) carry shadow-card with rounded-card (14px) and a 1px WG4 edge; the app window carries shadow-window with rounded-window (18px); everything else in the page is flat.
95
98
 
96
- - Do: Keep cards, panels, chips, buttons, tabs, fields, thumbs, and other in-page surfaces at shadow-0; separate them with fill, border, or spacing.
99
+ - Do: Keep panels, rows, chips, buttons, tabs, fields, thumbs, the attached Drawer and other in-page surfaces at shadow-0; separate them with fill, hairlines, or spacing.
100
+ - Do: Give resting cards rounded-card + border border-border + shadow-card, and the app window rounded-window + border border-border + shadow-window.
101
+ - Do: Lift the active sidebar item (its White fill) with shadow-nav-active; keep hover flat.
97
102
  - Do: Use shadow-float for floating layers that sit over content: toasts, toolbars, the chat composer dock, and any menu or popover that needs lift beyond its border.
98
103
  - Do: Use shadow-overlay for modals, dialogs, and overlay drawers, so a dialog always reads above a menu.
99
104
  - Don't: Put a shadow on an in-page surface for decoration or to signal that it is clickable.
100
105
  - Don't: Use raw shadow values, inset glows, or the removed numbered levels and elevation hook.
101
106
  - Don't: Invent a third floating level; stack order comes from float vs overlay.
107
+ - Don't: Put shadow-card on a panel, a row, a detail-panel stat tile or the attached Drawer; put shadow-window on anything but the app window.
102
108
 
103
109
  ### 3. Motion follows the interaction [lint: unbounded-transition, sluggish-easing, zero-scale-entrance, undersized-zoom-entrance, raw-spring-config]
104
110
 
@@ -123,14 +129,18 @@ All icons come from Phosphor Icons at the regular weight — the stroke-led icon
123
129
  - Do: Render weight='fill' for the active or selected state, and weight='bold' for the rare heavier stroke.
124
130
  - Don't: Import from an icon package directly, or install a second icon set.
125
131
  - Don't: Leave an active nav item's icon at the regular stroke weight.
132
+ - Don't: Set a glyph on a background tile, circle, or outlined square — icons sit bare in muted grey (avatars and brand logos keep their frames).
126
133
 
127
- ### 5. Demo screens: the shell owns the frame [judgment]
134
+ ### 5. Demo screens: the shell owns the app window [judgment]
128
135
 
129
- The demo shell applies the screen frame (inset on top/right/bottom, flush-left against the sidebar). Screens never add their own outer padding — a screen's root is flex h-full flex-col and fills the frame with Panel(s).
136
+ The shell renders one app window (user-mandated 2026-11-12): a rounded-window (18px) surface with a 1px WG4 edge and shadow-window, inset 12px on the bg-surface (WG3) backdrop. The sidebar (bg-background) and the White PageBody sit inside it, split by one full-height WG4 hairline. Page headers are BodyPageHeader bars — 64px, 20px (text-xl) Medium title, actions trailing, full-width hairline below. A record's detail panel is an inline Drawer attached to the page: flush beside the content, one full-height hairline, no gap, radius or shadow. Screens never add their own outer padding, radius, card or shadow — a screen's root is flex h-full flex-col and fills the page.
130
137
 
131
- - Do: Make a screen root flex h-full flex-col and fill the frame with Panel(s).
132
- - Do: Let one place (the shell) own the inset so every screen aligns to the rail.
133
- - Don't: Add outer padding on a screen, leaving a tinted-canvas gap on the left.
138
+ - Do: Make a screen root flex h-full flex-col and fill the page with Panel(s); the shell renders them flush.
139
+ - Do: Let one place (the shell) own the window, its radius, edge and shadow.
140
+ - Do: Open record details in an attached Drawer beside the list, inside the same white page.
141
+ - Don't: Add outer padding, a radius or a shadow on a screen, or wrap a screen in its own card.
142
+ - Don't: Float a detail panel as a separate card with a strip of canvas between it and the list.
143
+ - Don't: Put the sidebar outside the window, directly on the backdrop.
134
144
 
135
145
  ### 6. Status dots are square [judgment]
136
146
 
@@ -160,7 +170,7 @@ A screen carries ONLY what the user needs to move forward: one title, the inputs
160
170
  - Do: Prefer more, smaller steps over dense ones; ask one thing at a time.
161
171
  - Do: Derive instead of asking whenever possible (a name from a work email, the company from its domain).
162
172
  - Do: Prefer clear text-only buttons; add an icon only when it communicates essential meaning the label cannot carry alone, or for a compact conventional icon-only control.
163
- - Do: Open a multi-step create task launched from a collection (New campaign) as a Modal over that list: title-only header, one scrolling form (for New campaign: Campaign name, Caller numbers, Audience), and Cancel + Create together in the footer — the user never loses their place. Add a Stepper only when the task truly has separate steps. Form modals use a fixed height (Modal height="fixed", 640px) so the frame never resizes: the header and footer stay put and ModalBody scrolls. Standalone onboarding flows render full-screen with a single content container holding the inputs and its own Back/Continue.
173
+ - Do: Open a multi-step create task launched from a collection (New campaign) as a Modal over that list: title-only header, one scrolling form (for New campaign: Campaign name, Caller numbers, Audience), and Cancel + Create together in the footer — the user never loses their place. Add a Stepper only when the task truly has separate steps. Every modal is fixed-height (sm 320px, md/lg/xl 640px — the Modal default) so the frame never resizes: the header and footer stay put and ModalBody scrolls; see principle create-modals. Standalone onboarding flows render full-screen with a single content container holding the inputs and its own Back/Continue.
164
174
  - Don't: Add section eyebrows above a title that already names the screen, or helper text that restates the obvious / duplicates a disabled button's meaning.
165
175
  - Don't: Add any header description unless the user explicitly requested supporting copy for that page, section, panel, modal, dialog, drawer, or popover.
166
176
  - Don't: Decorate a labeled button with a redundant leading or trailing icon.
@@ -178,9 +188,9 @@ ADS targets landscape tablet (1024) → laptop (1440) → wide display (1920+);
178
188
 
179
189
  ### 10. Back navigation is leading; drill-downs use the breadcrumb [judgment]
180
190
 
181
- A record or drill-down page (a campaign inside Voice campaigns, a connector inside Data Integrations) is titled by its Breadcrumbs trail — parent / record at 16px — with no back arrow and no repeated H1; the page's one primary action sits at the right end of the same row. A standalone page-level Back control, when one is needed outside a hierarchy, sits immediately before the title and never on the right.
191
+ A record or drill-down page (a campaign inside Voice campaigns, a connector inside Data Integrations) is titled by its Breadcrumbs trail — parent / record at 18px, the header-bar title size, in the 64px header bar — with no back arrow and no repeated H1; the page's one primary action sits at the right end of the same row. A standalone page-level Back control, when one is needed outside a hierarchy, sits immediately before the title and never on the right.
182
192
 
183
- - Do: Title a drill-down with Breadcrumbs (16px trail: muted parent links, Medium current item) and put its primary action (e.g. Pause campaign) right-aligned on the same row.
193
+ - Do: Title a drill-down with Breadcrumbs (20px trail, the same size as the header-bar title: muted parent links, Medium current item) and put its primary action (e.g. Pause campaign) right-aligned on the same row.
184
194
  - Do: Use PageHeader with onBack only for a standalone page that has no parent hierarchy to show.
185
195
  - Do: Reserve the trailing header area for forward or page-level actions such as Add, Save, Pause, or Share.
186
196
  - Don't: Stack a back arrow and a large H1 above a page whose parent is already known — the breadcrumb says both.
@@ -189,7 +199,7 @@ A record or drill-down page (a campaign inside Voice campaigns, a connector insi
189
199
 
190
200
  ### 11. Tabs lead; scoped search trails [judgment]
191
201
 
192
- When tabs and a search field control the same content, they share one responsive control row: the tab list leads with its triggers left-aligned at their natural width over a baseline that fades from WG3 to transparent, and search sits at the trailing edge. On collection screens the trailing controls are icon triggers — SearchDisclosure (expands into the field) then Filters — and tab labels are 14px with a quieter count after each label.
202
+ When tabs and a search field control the same content, they share one responsive control row: the tab list leads with its triggers left-aligned at their natural width over a baseline that fades from WG3 to transparent, and search sits at the trailing edge. On collection screens the trailing controls are icon triggers — SearchDisclosure (expands into the field) then Filters — and tab labels are 16px with a quieter count after each label.
193
203
 
194
204
  - Do: Keep tab triggers left-aligned at their natural width, then place the scoped search opposite them in the same toolbar.
195
205
  - Do: On collection screens use SearchDisclosure followed by Filters as 32px icon triggers at the trailing edge; keep the page header for the title and one primary action only.
@@ -202,37 +212,46 @@ When tabs and a search field control the same content, they share one responsive
202
212
 
203
213
  ### 12. Collection screens fill the panel [judgment]
204
214
 
205
- A collection screen (campaigns, call logs, leads) is one white panel: BodyPageHeader (title + one primary action), the tab/search/filter row, then a Table whose rows fill the panel's height with Pagination pinned to its bottom edge. Rows open details in a shell-level side panel; the list stays visible.
215
+ A collection screen (campaigns, call logs, leads) is one white page in the app window: BodyPageHeader (the 64px header bar — title + one primary action, full-width hairline), the tab/search/filter row, then a Table whose rows fill the panel's height with Pagination pinned to its bottom edge. Rows open details in a Drawer attached beside the list by one full-height hairline; the list stays visible.
206
216
 
207
217
  - Do: Size the page so the rows fill the panel to its 24px bottom inset and Pagination sits at the bottom; let only the rows scroll.
208
218
  - Do: Show row checkboxes only on hover/focus (and while checked or mixed); keep the header select-all checkbox always visible.
209
219
  - Do: When a row's details are open, mark it with TableRow isActive (the soft-teal fade) — no radio and no selection column for that purpose.
210
220
  - Do: Put status in a Chip using business language (see status-language) and keep cell values at text-m.
221
+ - Do: Give a rate column a small Progress meter (size sm, ~48px) before the right-aligned percentage, and give a record with a recent trend a "Last 7 days" column holding a dotless Sparkline (height 28, dot={false}); a record with no calls yet shows an em dash and "No calls yet" in secondary text.
222
+ - Do: Show the owner as plain text — no avatar in the cell.
211
223
  - Do: Show the customer's workspace logo in the Sidebar brand slot (SidebarWorkspace) when the product runs inside a customer workspace.
212
224
  - Don't: Leave an empty band under a short table, or float Pagination mid-panel.
213
225
  - Don't: Use single-selection radios to mean 'this row is open'.
214
226
  - Don't: Show a checkbox on every resting row of a multi-select table.
227
+ - Don't: Put a profile image beside every owner name, or draw an empty meter or a flat sparkline for a record with no data.
215
228
  - Don't: Open record details in a modal over the list you are scanning.
216
229
 
217
230
  ### 13. Record detail panels are grouped by question [judgment]
218
231
 
219
- A selection-driven detail panel reads top-down as: kicker (the KIND of record), title, then the record's status Chip and its one-line context directly under the title; then titled sections 32px apart — Performance (stat cards + chart card) and Details (label–value rows with inset dividers); then footer actions (secondary outline + one solid primary).
232
+ A selection-driven detail panel (a campaign, a call) has three regions. DrawerHeader never scrolls: DrawerKicker (the KIND of record), DrawerTitle, then DrawerMeta — the status Chip and its one-line 16px context ("12 Sep, 3:41 PM · 4s") 8px under the title — closed by a full-width WG4 hairline. DrawerBody is the only scrolling region: DrawerSections 32px apart, each a 16px Medium title (with an optional Regular secondary count — "Transcript · 1 turn", "Captured fields · 0 of 10"). Attributes are a DetailList. A DrawerFooter exists only when an action leads somewhere real, and opens with a full-width hairline. The panel is attached to the page: one full-height WG4 hairline on its leading edge, no gap, radius or shadow.
220
233
 
221
- - Do: Put the status Chip and its context ("Finished Oct 21") in the header, 4px under the title, so status never floats on its own.
222
- - Do: Group numbers in small outlined stat cards (WG3 edge, radius-l, 12px padding, 8px apart) and the trend in its own chart card.
223
- - Do: List attributes (owner, started, calling windows) as label–value rows: label secondary left, value primary right, inset WG3 dividers.
224
- - Do: Separate sections with 32px and keep items inside a section ≤16px apart; give each section a 14px Medium title.
234
+ - Do: Compose DrawerHeader → DrawerKicker + DrawerTitle + DrawerMeta so status never floats on its own; the header's full-width hairline grounds it.
235
+ - Do: Let DrawerBody scroll (it is overflow-y-auto) — never clip the panel with overflow hidden.
236
+ - Do: Group numbers in small flat stat tiles (WG1 fill + 1px WG4 edge, rounded-card, 12px padding, no shadow, 8px apart) and a trend in its own chart tile.
237
+ - Do: List attributes as a DetailList: sentence-case labels ("Type of loan", never type_of_loan), values right-aligned and wrapping, Not stated in secondary grey when empty (tertiary fails AA at 16px).
238
+ - Do: Count what a section holds in its title ("0 of 10") instead of a separate summary line.
239
+ - Do: Put rarely-needed data (call metadata) in a Collapsible at the end of the body, collapsed.
240
+ - Do: Add a DrawerFooter only when its action exists — Open full view only when the dedicated page exists.
225
241
  - Don't: Mix attributes (owner) into the metric grid.
226
- - Don't: Leave a lone chip or line of metadata between the title and the first section.
227
- - Don't: Repeat the same fact (finish date) in the header and in Details.
242
+ - Don't: Repeat a fact: what the header says (status, time, length) never appears again in stat cards or write-back rows.
243
+ - Don't: Add placeholder footer buttons (Open full view, Call again) for a record that has no page or action behind them.
244
+ - Don't: Show raw field keys, monospace labels, or a dash pattern like "— not stated" for empty values.
228
245
 
229
246
  ### 14. Stats and charts sit in their own containers, values visible [judgment]
230
247
 
231
- On analytics/record pages every stat and every chart is its own outlined container (1px WG3 border, radius-l, 20px padding, white, flat) on the white panel, 16px apart. Values are printed on the chart by default — never hover-only — and the legend sits at the right end of the chart's title row.
248
+ On analytics/record pages every stat and every chart is its own resting card (1px WG4 border, rounded-card 14px, shadow-card, 20px padding, white) on the white page, 16px apart. Values are printed on the chart by default — never hover-only — and the legend sits at the right end of the chart's title row.
232
249
 
233
- - Do: Stat card: label (14px secondary) → number (32px) with its scope ("of 4,800 calls") 4px apart, then a Progress bar 12px below that fills the card width.
234
- - Do: Chart card: title (16px Medium) + scope subtitle (12px secondary) on the left, the legend right-aligned on the same row, ~40px from the title block to the plot.
250
+ - Do: Spell out the scope under the tabs with a FilterBar: joined 32px segments showing their current values — period preset + resolved dates leading, a second filter (cohort) trailing.
251
+ - Do: Stat card: label (16px secondary) → number (text-4xl, 35px, tightened tracking) with its scope ("of 4,800 calls", 14px secondary) 4px apart, a Sparkline of its recent trend beside the number (right ~third of the card), then a Progress bar 12px below that fills the card width.
252
+ - Do: Chart card: title (18px Medium) + scope subtitle (14px secondary) on the left, the legend right-aligned on the same row, ~40px from the title block to the plot.
235
253
  - Do: Bar charts print each bar's value; stacked bars print each segment that fits plus the stack total. Line charts print every point's value in the series colour (secondary grey for light amber/grey series).
254
+ - Do: Keep LineChart's default gradientFill: a wash under each observed line fading top-to-bottom from 20% of the series colour to nothing (forecasts stay unfilled).
236
255
  - Do: Size charts so the cards end on the panel's 24px bottom inset.
237
256
  - Don't: Separate stats with vertical hairlines while their bars run into the next stat — proximity breaks.
238
257
  - Don't: Hide numbers behind a hover tooltip.
@@ -241,14 +260,41 @@ On analytics/record pages every stat and every chart is its own outlined contain
241
260
 
242
261
  ### 15. Status speaks the business, with one tone per meaning [judgment]
243
262
 
244
- Status labels name the business state, not the machine's activity, and tabs use the same words. Campaign statuses: Active and Scheduled (info blue), Paused (warning amber), Completed (success green), Draft (default grey), Failed (danger red). Teal is reserved for actions and selection, not for a status.
263
+ Status labels name the business state, not the machine's activity, and tabs use the same words. Campaign statuses: Active and Scheduled (info blue), Paused (warning amber), Completed (success green), Draft (default grey), Failed (danger red). Call statuses: Completed (success), No answer and Busy (warning), Failed (danger); a call's outcome ("Customer did not speak") is a separate column that exists only once the call connected — show an em dash otherwise. Teal is reserved for actions and selection, not for a status.
245
264
 
246
265
  - Do: Say Active, not Dialing; name the tab Active too (All · Draft · Active · Paused · Completed).
247
266
  - Do: Use Chip tones consistently for the same status everywhere (table cell, detail header, filters).
248
- - Do: Use the plain Chip appearance (square dot + 14px text) where a column of filled chips would shout louder than the record names.
267
+ - Do: Use the plain Chip appearance (square dot + 16px text) where a column of filled chips would shout louder than the record names.
268
+ - Do: Keep Chip labels Regular weight — 14px (text-s) in solid and outline chips, 16px (text-m) in plain ones.
269
+ - Don't: Set a Chip label in Medium; the tone, dot and edge already carry the emphasis.
249
270
  - Don't: Colour a status with the primary teal — it competes with the primary action and the selected-row fade.
250
271
  - Don't: Use different words for the same state in the tab, the chip and the filter.
251
272
 
273
+ ### 16. Create modals: fixed frame, quiet guidance, compact inputs [judgment]
274
+
275
+ Every Modal has a fixed height — sm confirmations 320px (--modal-height-sm), md/lg/xl dialogs 640px (--modal-height) — and never grows or shrinks with its content: the header and footer stay put and ModalBody scrolls. Inside a create form, each field is a Field: optional guidance sits behind a bare info icon after the label (Field info), a control that picks the field's source sits at the right end of the label row (Field actions), an upload is the 64px inline FileDropzone, and choosing one saved record is a single-select Table with a search above it. Icons sit bare: no tile, circle, or fill behind a glyph.
276
+
277
+ - Do: Use the Modal default height; pick size by width only (sm confirmation, md form, lg/xl dense content).
278
+ - Do: Put 'optional / you can change this later' notes in Field info, not in a helper line under the control.
279
+ - Do: Put a source switch (SegmentedControl size=sm, e.g. CSV upload | Empty audience) in Field actions on the label row.
280
+ - Do: Use FileDropzone layout='inline' (bare icon · label + hint · Browse) when the upload shares the form with other fields.
281
+ - Do: Let the user pick one saved record from a Table with selectionMode='single' (radio + soft-teal fade) under a search field, with the unit named once in the column header.
282
+ - Do: Render icons bare in muted grey: in upload strips, empty states, labels and list rows.
283
+ - Don't: Pass height='content' or let a modal resize as sections appear or disappear.
284
+ - Don't: Stack a tall drop target, a search, and an unlabeled list one after another inside a fixed-height form.
285
+ - Don't: Hand-roll a pick-one list with justify-between rows or an 'or' divider between alternatives.
286
+ - Don't: Put an icon on a grey tile, a circle, or an outlined square that adds nothing but a background.
287
+
288
+ ### 17. Settings screens fill the panel [judgment]
289
+
290
+ A settings screen is one white page: BodyPageHeader (the header bar — title + the one save action), then setting groups 32px apart. Every group fills the panel's width between its 24px side insets — no fixed reading-width column — so each row's control lines up on the panel's right edge under the save action. A group is an 18px Medium title over a SettingList of SettingRows: bare glyph, label + one-line description, and the control that changes it.
291
+
292
+ - Do: Give each group w-full; let SettingRow stretch to the panel width.
293
+ - Do: Use the control that matches the setting: Switch for on/off, an outline Button showing the current value for pickers ("10:00 – 19:00"), a Badge for a fixed threshold.
294
+ - Do: Keep the leading glyph bare and muted; rows separate with inset hairlines.
295
+ - Don't: Cap a settings group at a fixed width (720px) and leave the right half of the panel empty.
296
+ - Don't: Put a save button per group, or icons on tiles.
297
+
252
298
  ## UI grammar
253
299
 
254
300
  Before composing a screen, match its intent to one production below, preserve the named JSX tree, then query the design graph for required component states. State axes are independent; render only the representative combinations named by the graph instead of a Cartesian product.
@@ -258,8 +304,11 @@ Before composing a screen, match its intent to one production below, preserve th
258
304
  - `data-table` — Structured data table: Semantic table anatomy with matching header and body rows. (intents: table, records, comparison, sorting, selection; Storybook: ADS/Components/Data display/Table)
259
305
  - `tabbed-results` — Tabbed results with scoped search: Tabs lead and a scoped search trails in one responsive control row. (intents: tabs, filter, search, results, segmented views; Storybook: ADS/Components/Data display/Tabs)
260
306
  - `collection-screen` — Collection screen with record detail: BodyPageHeader (title + one primary action), a control row with counted Tabs leading and SearchDisclosure + Filters trailing, a Table whose rows fill the panel with Pagination at its bottom edge, a shell-level Drawer for the open record, and a fixed-height Modal for the create task. (intents: campaigns, call logs, leads, records list, collection, list page, new campaign; Storybook: ADS/Components/Table)
261
- - `record-analytics` — Record analytics page: A drill-down page titled by its Breadcrumbs (parent / record) with the primary action on the same row, record Tabs, then outlined stat cards and outlined chart cards whose legends sit in their title row and whose values are printed. (intents: analysis, analytics tab, record page, campaign analysis, metrics, dashboard tab; Storybook: ADS/Components/Chart)
307
+ - `record-analytics` — Record analytics page: A drill-down page titled by its Breadcrumbs (parent / record) with the primary action on the same row, record Tabs, a FilterBar scope row, then resting stat cards and chart cards whose legends sit in their title row and whose values are printed. (intents: analysis, analytics tab, record page, campaign analysis, metrics, dashboard tab; Storybook: ADS/Components/Chart)
262
308
  - `modal-task` — Blocking modal task: A focused interruption with one title, body, and decisive footer. (intents: modal, confirmation, short form, blocking task, destructive action; Storybook: ADS/Components/Overlays/Modal)
309
+ - `create-modal` — Create modal over a collection: A fixed-height Modal opened from a collection's primary action: title-only header, one scrolling form of Fields (optional guidance in an info icon, a source switch in the label row, an inline upload strip, a single-select Table to reuse a saved record), and Cancel + Create in the footer. (intents: new campaign, create, new record, create form, setup modal, add audience, upload list; Storybook: ADS/Components/Modal)
310
+ - `record-call-logs` — Record call logs with a call panel: A record tab (Call logs) titled by Breadcrumbs with the record status beside it and the record actions on the right, a Table of calls (Number · Status · Outcome · Duration) filling the panel, and a shell-level call panel: grounded header, scrolling sections, no footer. (intents: call logs, call review, calls, call detail, call panel, recordings, transcript, crm write-back, captured fields; Storybook: ADS/Components/Drawer)
311
+ - `settings-screen` — Settings screen: One white page: the BodyPageHeader bar with the save action, then full-width setting groups (18px title over a SettingList) 32px apart. (intents: settings, guardrails, preferences, configuration page, compliance settings; Storybook: ADS/Components/SettingRow)
263
312
  - `settings-card` — Settings card: A compact settings surface with grouped SettingRows and one save action. (intents: settings, preferences, configuration, toggles; Storybook: ADS/Components/Under review/SettingList / SettingRow)
264
313
  - `research-trace` — Inspectable research trace: ResearchActivity owns the run summary and contains the canonical ChainOfThought tree. (intents: agent trace, research, tool activity, sources, long-running task; Storybook: ADS/Components/AI Elements/Research Activity)
265
314
  - `typed-answer` — Typed research answer: A request/answer turn where structured output flows through AnswerRenderer. (intents: answer, research result, citations, follow-up, assistant response; Storybook: ADS/Components/AI Elements/Message)
@@ -309,7 +358,8 @@ Before using any component below, preserve its built-in motion and apply the mot
309
358
  - [Field] — Wrap any form control (Input, Select, NumberField, Textarea, etc.) with a label plus optional description or error footer. [docs](https://ads.actioneer.dev/#/field)
310
359
  - [FieldDescription] — component [docs](https://ads.actioneer.dev/#/field)
311
360
  - [FieldError] — component [docs](https://ads.actioneer.dev/#/field)
312
- - [FileDropzone] — component (variants: hasFiles: true|false; isDragging: true|false; isDisabled: true|false) [docs](https://ads.actioneer.dev/#/review/file-dropzone)
361
+ - [FieldInfo] — component [docs](https://ads.actioneer.dev/#/field)
362
+ - [FileDropzone] — component (variants: hasFiles: true|false; layout: stacked|inline; isDragging: true|false; isDisabled: true|false) [docs](https://ads.actioneer.dev/#/review/file-dropzone)
313
363
  - [Heading] — Use Heading for semantic h1–h4 titles above a page, section, or card, sized by document level via `level` (never a `size` prop). [docs](https://ads.actioneer.dev/#/typography)
314
364
  - [Kbd] — Use to display a keyboard shortcut or key name, inline in text or trailing a label in a shortcut list. [docs](https://ads.actioneer.dev/#/kbd)
315
365
  - [Label] — component [docs](https://ads.actioneer.dev/#/field)
@@ -363,6 +413,9 @@ Before using any component below, preserve its built-in motion and apply the mot
363
413
  - [Checkbox] — Use for a standalone boolean toggle or a multi-select list item — including a tri-state "select all" via `indeterminate`. [docs](https://ads.actioneer.dev/#/checkbox)
364
414
  - [CheckboxGroup] — component [docs](https://ads.actioneer.dev/#/checkbox)
365
415
  - [DateRangePicker] — component [docs](https://ads.actioneer.dev/#/date-range-picker)
416
+ - [FilterBar] — component [docs](https://ads.actioneer.dev/#/filter-bar)
417
+ - [FilterBarSelect] — component [docs](https://ads.actioneer.dev/#/filter-bar)
418
+ - [FilterBarValue] — component [docs](https://ads.actioneer.dev/#/filter-bar)
366
419
  - [Filters] — component [docs](https://ads.actioneer.dev/#/filters)
367
420
  - [Input] — Use for any single-line text value, wrapped in `Field` for label/description/error and `startContent`/`endContent` for icons or inline actions. [docs](https://ads.actioneer.dev/#/input)
368
421
  - [InputField] — component [docs](https://ads.actioneer.dev/#/input-field)
@@ -382,6 +435,10 @@ Before using any component below, preserve its built-in motion and apply the mot
382
435
  - [DateRangePickerProps] — TypeScript type
383
436
  - [DateRangeValue] — TypeScript type
384
437
  - [DropdownOptionsProps] — TypeScript type
438
+ - [FilterBarOption] — TypeScript type
439
+ - [FilterBarProps] — TypeScript type
440
+ - [FilterBarSelectProps] — TypeScript type
441
+ - [FilterBarValueProps] — TypeScript type
385
442
  - [FilterGroup] — TypeScript type
386
443
  - [FilterOption] — TypeScript type
387
444
  - [FiltersProps] — TypeScript type
@@ -403,10 +460,13 @@ Before using any component below, preserve its built-in motion and apply the mot
403
460
  ### Overlays
404
461
 
405
462
  - [CommandPalette] — component [docs](https://ads.actioneer.dev/#/command-palette)
406
- - [Drawer] — Use the portaled Drawer for a focused, blocking task (form, details, settings) that slides in over the page with a backdrop and focus trap; use InlineDrawer instead for a contextual panel that must stay in-flow beside content the user still needs. The inline Drawer is a flat white panel (bg-card, no shadow, no border) that reads ONLY by fill contrast, so it MUST sit as a sibling of its content inside a bg-surface flex row — on a white (bg-background) parent it is invisible. If it doesn't read, tint the ground; never add a border or shadow to force it. SELECTION-DRIVEN DETAIL RAILS (inspector/detail panels tied to a selected row, node, or category) are CLOSED BY DEFAULT: the slot mounts only while a selection exists and unmounts on deselect. Never render a placeholder rail ('Select a row to see details') — an empty rail is chrome that claims space and implies a selection the user hasn't made. Header anatomy when open: uppercase kicker (what kind of thing is selected) + title + close affordance, then a scrollable body. Never hand-roll the panel with translate-x + backdrop — that's this component. (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
463
+ - [Drawer] — Use the portaled Drawer for a focused, blocking task (form, details, settings) that slides in over the page with a backdrop and focus trap; use InlineDrawer instead for a contextual panel that must stay in-flow beside content the user still needs. The inline Drawer is attached to the page: a flat white panel (bg-card, no radius, no shadow) that sits flush beside its content inside the white page and draws one full-height WG4 hairline on its leading edge; its header and footer close with full-width hairlines. Never float it as a separate card with a strip of canvas between, and never give it a shadow. SELECTION-DRIVEN DETAIL RAILS (inspector/detail panels tied to a selected row, node, or category) are CLOSED BY DEFAULT: the slot mounts only while a selection exists and unmounts on deselect. Never render a placeholder rail ('Select a row to see details') — an empty rail is chrome that claims space and implies a selection the user hasn't made. Header anatomy when open: uppercase kicker (what kind of thing is selected) + title + close affordance, then a scrollable body. Never hand-roll the panel with translate-x + backdrop — that's this component. (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
407
464
  - [DrawerBody] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
408
465
  - [DrawerFooter] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
409
466
  - [DrawerHeader] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
467
+ - [DrawerKicker] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
468
+ - [DrawerMeta] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
469
+ - [DrawerSection] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
410
470
  - [DrawerTitle] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
411
471
  - [Dropdown] — Use a portaled, keyboard-navigable menu anchored to a trigger for row actions, account menus, or any list of commands revealed by a click. [docs](https://ads.actioneer.dev/#/dropdown)
412
472
  - [DropdownContent] — component [docs](https://ads.actioneer.dev/#/dropdown)
@@ -415,15 +475,15 @@ Before using any component below, preserve its built-in motion and apply the mot
415
475
  - [DropdownSeparator] — component [docs](https://ads.actioneer.dev/#/dropdown)
416
476
  - [DropdownTrigger] — component [docs](https://ads.actioneer.dev/#/dropdown)
417
477
  - [InlineDrawer] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
418
- - [Modal] — Use for a blocking, focused task or confirmation that must interrupt the page until resolved (portaled, focus-trapped, Escape/backdrop dismissible). (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
419
- - [ModalBody] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
420
- - [ModalClose] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
421
- - [ModalDescription] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
478
+ - [Modal] — Use for a blocking, focused task or confirmation that must interrupt the page until resolved (portaled, focus-trapped, Escape/backdrop dismissible). (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
479
+ - [ModalBody] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
480
+ - [ModalClose] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
481
+ - [ModalDescription] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
422
482
  - [ModalDrawer] — component (variants: side: right|left|bottom; size: sm|md|lg|xl) [docs](https://ads.actioneer.dev/#/drawer)
423
- - [ModalFooter] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
424
- - [ModalHeader] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
425
- - [ModalSection] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
426
- - [ModalTitle] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: content|fixed) [docs](https://ads.actioneer.dev/#/modal)
483
+ - [ModalFooter] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
484
+ - [ModalHeader] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
485
+ - [ModalSection] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
486
+ - [ModalTitle] — component (variants: size: sm|md|lg|xl|full; position: center|top; height: fixed|content) [docs](https://ads.actioneer.dev/#/modal)
427
487
  - [Popover] — Use Popover for a portaled, dismissible panel anchored to a trigger — quick settings, a profile card, or a short inline form — that closes on outside click or Escape. [docs](https://ads.actioneer.dev/#/popover)
428
488
  - [PopoverContent] — component [docs](https://ads.actioneer.dev/#/popover)
429
489
  - [PopoverTrigger] — component [docs](https://ads.actioneer.dev/#/popover)
@@ -431,6 +491,7 @@ Before using any component below, preserve its built-in motion and apply the mot
431
491
  - [CommandPaletteItem] — TypeScript type
432
492
  - [CommandPaletteProps] — TypeScript type
433
493
  - [DrawerProps] — TypeScript type
494
+ - [DrawerSectionProps] — TypeScript type
434
495
  - [DropdownContentProps] — TypeScript type
435
496
  - [DropdownItemProps] — TypeScript type
436
497
  - [DropdownProps] — TypeScript type
@@ -488,6 +549,8 @@ Before using any component below, preserve its built-in motion and apply the mot
488
549
  - [ConnectionStatus] — component [docs](https://ads.actioneer.dev/#/connector-card)
489
550
  - [ConnectorCard] — Use ConnectorCard to represent one data source/destination on an integrations screen — identity, connection status, health strip, and a usage/action footer. [docs](https://ads.actioneer.dev/#/connector-card)
490
551
  - [DecisionAnswer] — component (variants: tone: default|primary|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/ai/answer)
552
+ - [DetailItem] — component [docs](https://ads.actioneer.dev/#/detail-list)
553
+ - [DetailList] — component [docs](https://ads.actioneer.dev/#/detail-list)
491
554
  - [EdgeLabelRenderer] — component [docs](https://ads.actioneer.dev/#/infinite-canvas)
492
555
  - [EmptyAnswer] — component (variants: tone: default|primary|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/ai/answer)
493
556
  - [ErrorAnswer] — component (variants: tone: default|primary|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/ai/answer)
@@ -515,6 +578,7 @@ Before using any component below, preserve its built-in motion and apply the mot
515
578
  - [RetentionGrid] — component [docs](https://ads.actioneer.dev/#/viz-charts)
516
579
  - [ScatterChart] — component [docs](https://ads.actioneer.dev/#/ai/chart)
517
580
  - [SeriesChart] — component [docs](https://ads.actioneer.dev/#/viz-charts)
581
+ - [Sparkline] — component [docs](https://ads.actioneer.dev/#/sparkline)
518
582
  - [StatusAnswer] — component (variants: tone: default|primary|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/ai/answer)
519
583
  - [Tab] — component (variants: orientation: horizontal|vertical; selected: true|false) [docs](https://ads.actioneer.dev/#/tabs)
520
584
  - [Table] — Use Table for structured tabular data that may need row selection, column sorting, sticky columns, or a paginated footer — not for simple key-value lists. Every primary body-cell value defaults to text-m (14px / 20px); only clearly secondary metadata inside a cell may opt down to text-s. Give a whole-row action an onClick and aria-label: TableRow then adds hover/focus feedback, a pointer cursor, and Enter/Space activation. The consumer decides whether that action navigates or opens a panel; TableRow owns neither destination. Display-only rows stay static. Single selection uses grouped radio buttons and keeps the chosen row selected; multiple selection uses checkboxes. Selecting or clearing a parent cascades through all descendants, including collapsed rows; partial groups show a mixed checkbox. Selection callbacks include the complete selected key set. Selected row fills fade from full soft-teal tint at the visible left edge to no tint at the right edge, including pinned cells. Use TableRow.childRows for collapsible hierarchies, expanded/defaultExpanded and onExpandedChange for disclosure, and stable rowKey values. Child rows open below their parent without shifting columns; the caret and parent label share one transparent disclosure button, separate from selection, and both turn the primary-action text color on hover. Sorting keeps child rows with their parent. Keep normal row geometry without a brand tint or hover-only corner rounding. Nested controls keep their own actions. Primary record links stay text-only in every state: never reveal an arrow, chevron, or other directional icon only on hover. Persistent row actions use a final sticky-right column plus elevatedActionColumn so one body-column shadow lifts the action surface instead of repeating on individual cells. The empty matching header cell remains transparent and non-sticky. [docs](https://ads.actioneer.dev/#/table)
@@ -597,6 +661,8 @@ Before using any component below, preserve its built-in motion and apply the mot
597
661
  - [ConnectorTint] — TypeScript type
598
662
  - [DecisionAnswerProps] — TypeScript type
599
663
  - [DecisionAnswerSpec] — TypeScript type
664
+ - [DetailItemProps] — TypeScript type
665
+ - [DetailListProps] — TypeScript type
600
666
  - [Edge] — TypeScript type
601
667
  - [EdgeProps] — TypeScript type
602
668
  - [EdgeTypes] — TypeScript type
@@ -646,6 +712,8 @@ Before using any component below, preserve its built-in motion and apply the mot
646
712
  - [SeriesChartProps] — TypeScript type
647
713
  - [SortDescriptor] — TypeScript type
648
714
  - [SortDirection] — TypeScript type
715
+ - [SparklineColor] — TypeScript type
716
+ - [SparklineProps] — TypeScript type
649
717
  - [StatusAnswerProps] — TypeScript type
650
718
  - [StatusAnswerSpec] — TypeScript type
651
719
  - [TableAnswerProps] — TypeScript type