@crisp-ui-kit/crisp 0.31.4 → 0.31.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/authshell.css +1 -1
  2. package/dist/cjs/components/accordion/accordion.recipe.js +1 -1
  3. package/dist/cjs/components/barchart/barchart.recipe.js +1 -1
  4. package/dist/cjs/components/breadcrumb/breadcrumb.recipe.js +1 -1
  5. package/dist/cjs/components/bulkbar/bulkbar.recipe.js +1 -1
  6. package/dist/cjs/components/callout/callout.recipe.js +1 -1
  7. package/dist/cjs/components/checkbox/checkbox.recipe.js +1 -1
  8. package/dist/cjs/components/columncalc/columncalc.recipe.js +2 -2
  9. package/dist/cjs/components/datatable/datatable.recipe.js +5 -5
  10. package/dist/cjs/components/datepicker/datepicker.recipe.js +3 -3
  11. package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +2 -2
  12. package/dist/cjs/components/dialog/dialog.recipe.js +1 -1
  13. package/dist/cjs/components/donutchart/donutchart.recipe.js +1 -1
  14. package/dist/cjs/components/emptystate/emptystate.recipe.js +2 -2
  15. package/dist/cjs/components/fileupload/fileupload.recipe.js +6 -6
  16. package/dist/cjs/components/formfield/formfield.recipe.js +1 -1
  17. package/dist/cjs/components/input/input.recipe.js +1 -1
  18. package/dist/cjs/components/linechart/linechart.recipe.js +1 -1
  19. package/dist/cjs/components/menu/menu.recipe.js +2 -2
  20. package/dist/cjs/components/multiselect/multiselect.recipe.js +1 -1
  21. package/dist/cjs/components/progress/progress.recipe.js +1 -1
  22. package/dist/cjs/components/quantitypicker/quantitypicker.recipe.js +2 -2
  23. package/dist/cjs/components/radiogroup/radiogroup.recipe.js +1 -1
  24. package/dist/cjs/components/resizablepanel/resizablepanel.recipe.js +2 -2
  25. package/dist/cjs/components/segmented/segmented.recipe.js +1 -1
  26. package/dist/cjs/components/select/select.recipe.js +2 -2
  27. package/dist/cjs/components/slider/slider.recipe.js +2 -2
  28. package/dist/cjs/components/stagebar/stagebar.recipe.js +1 -1
  29. package/dist/cjs/components/statcard/statcard.recipe.js +2 -2
  30. package/dist/cjs/components/switch/switch.recipe.js +1 -1
  31. package/dist/cjs/components/table/table.recipe.js +1 -1
  32. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +2 -2
  33. package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +1 -1
  34. package/dist/cjs/components/tabs/tabs.recipe.js +1 -1
  35. package/dist/cjs/components/textarea/textarea.recipe.js +1 -1
  36. package/dist/cjs/components/tooltip/tooltip.recipe.js +1 -1
  37. package/dist/cjs/core/dialog-description.js +1 -1
  38. package/dist/cjs/index.js +1 -1
  39. package/dist/cjs/product/appshell/appshell.recipe.js +1 -1
  40. package/dist/cjs/product/authshell/authshell.recipe.js +3 -3
  41. package/dist/cjs/product/board/board.recipe.js +1 -1
  42. package/dist/cjs/product/entitycard/entitycard.recipe.js +1 -1
  43. package/dist/cjs/product/flowcanvas/flowcanvas.recipe.js +1 -1
  44. package/dist/cjs/product/inbox/inbox.recipe.js +1 -1
  45. package/dist/cjs/product/listpage/listpage.recipe.js +1 -1
  46. package/dist/cjs/product/onboarding/onboarding.recipe.js +1 -1
  47. package/dist/cjs/product/recordpage/recordpage.recipe.js +2 -2
  48. package/dist/cjs/product/recordpanel/recordpanel.recipe.js +1 -1
  49. package/dist/cjs/product/recordstable/recordstable.recipe.js +2 -2
  50. package/dist/cjs/product/recordstable/recordstable.tag.js +1 -1
  51. package/dist/cjs/product/richtext/richtext.recipe.js +1 -1
  52. package/dist/cjs/product/settingssection/settingssection.recipe.js +1 -1
  53. package/dist/cjs/product/settingsshell/settingsshell.recipe.js +2 -2
  54. package/dist/cjs/product/tasklist/tasklist.recipe.js +1 -1
  55. package/dist/cjs/product/trialbanner/trialbanner.recipe.js +2 -2
  56. package/dist/cjs/product/viewtoggle/viewtoggle.recipe.js +1 -1
  57. package/dist/cjs/tokens/elevation.js +4 -4
  58. package/dist/cjs/tokens/palette.js +2 -2
  59. package/dist/cjs/tokens/scale.js +6 -6
  60. package/dist/cjs/tokens/semantic.js +1 -1
  61. package/dist/columncalc.css +1 -1
  62. package/dist/datatable.css +5 -5
  63. package/dist/esm/components/accordion/accordion.recipe.js +1 -1
  64. package/dist/esm/components/barchart/barchart.recipe.js +1 -1
  65. package/dist/esm/components/breadcrumb/breadcrumb.recipe.js +1 -1
  66. package/dist/esm/components/bulkbar/bulkbar.recipe.js +1 -1
  67. package/dist/esm/components/callout/callout.recipe.js +1 -1
  68. package/dist/esm/components/checkbox/checkbox.recipe.js +1 -1
  69. package/dist/esm/components/columncalc/columncalc.recipe.js +2 -2
  70. package/dist/esm/components/datatable/datatable.recipe.js +5 -5
  71. package/dist/esm/components/datepicker/datepicker.recipe.js +3 -3
  72. package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +2 -2
  73. package/dist/esm/components/dialog/dialog.recipe.js +1 -1
  74. package/dist/esm/components/donutchart/donutchart.recipe.js +1 -1
  75. package/dist/esm/components/emptystate/emptystate.recipe.js +2 -2
  76. package/dist/esm/components/fileupload/fileupload.recipe.js +6 -6
  77. package/dist/esm/components/formfield/formfield.recipe.js +1 -1
  78. package/dist/esm/components/input/input.recipe.js +1 -1
  79. package/dist/esm/components/linechart/linechart.recipe.js +1 -1
  80. package/dist/esm/components/menu/menu.recipe.js +2 -2
  81. package/dist/esm/components/multiselect/multiselect.recipe.js +1 -1
  82. package/dist/esm/components/progress/progress.recipe.js +1 -1
  83. package/dist/esm/components/quantitypicker/quantitypicker.recipe.js +2 -2
  84. package/dist/esm/components/radiogroup/radiogroup.recipe.js +1 -1
  85. package/dist/esm/components/resizablepanel/resizablepanel.recipe.js +2 -2
  86. package/dist/esm/components/segmented/segmented.recipe.js +1 -1
  87. package/dist/esm/components/select/select.recipe.js +2 -2
  88. package/dist/esm/components/slider/slider.recipe.js +2 -2
  89. package/dist/esm/components/stagebar/stagebar.recipe.js +1 -1
  90. package/dist/esm/components/statcard/statcard.recipe.js +2 -2
  91. package/dist/esm/components/switch/switch.recipe.js +1 -1
  92. package/dist/esm/components/table/table.recipe.js +1 -1
  93. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +2 -2
  94. package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +1 -1
  95. package/dist/esm/components/tabs/tabs.recipe.js +1 -1
  96. package/dist/esm/components/textarea/textarea.recipe.js +1 -1
  97. package/dist/esm/components/tooltip/tooltip.recipe.js +1 -1
  98. package/dist/esm/core/dialog-description.js +1 -1
  99. package/dist/esm/index.js +1 -1
  100. package/dist/esm/product/appshell/appshell.recipe.js +1 -1
  101. package/dist/esm/product/authshell/authshell.recipe.js +3 -3
  102. package/dist/esm/product/board/board.recipe.js +1 -1
  103. package/dist/esm/product/entitycard/entitycard.recipe.js +1 -1
  104. package/dist/esm/product/flowcanvas/flowcanvas.recipe.js +1 -1
  105. package/dist/esm/product/inbox/inbox.recipe.js +1 -1
  106. package/dist/esm/product/listpage/listpage.recipe.js +1 -1
  107. package/dist/esm/product/onboarding/onboarding.recipe.js +1 -1
  108. package/dist/esm/product/recordpage/recordpage.recipe.js +2 -2
  109. package/dist/esm/product/recordpanel/recordpanel.recipe.js +1 -1
  110. package/dist/esm/product/recordstable/recordstable.recipe.js +2 -2
  111. package/dist/esm/product/recordstable/recordstable.tag.js +1 -1
  112. package/dist/esm/product/richtext/richtext.recipe.js +1 -1
  113. package/dist/esm/product/settingssection/settingssection.recipe.js +1 -1
  114. package/dist/esm/product/settingsshell/settingsshell.recipe.js +2 -2
  115. package/dist/esm/product/tasklist/tasklist.recipe.js +1 -1
  116. package/dist/esm/product/trialbanner/trialbanner.recipe.js +2 -2
  117. package/dist/esm/product/viewtoggle/viewtoggle.recipe.js +1 -1
  118. package/dist/esm/tokens/elevation.js +4 -4
  119. package/dist/esm/tokens/palette.js +2 -2
  120. package/dist/esm/tokens/scale.js +6 -6
  121. package/dist/esm/tokens/semantic.js +1 -1
  122. package/dist/fileupload.css +2 -2
  123. package/dist/recordpage.css +1 -1
  124. package/dist/recordstable.css +1 -1
  125. package/dist/settingsshell.css +1 -1
  126. package/dist/styles.css +12 -12
  127. package/dist/types/core/dialog-description.d.ts +1 -1
  128. package/dist/types/product/recordstable/recordstable.tag.d.ts +1 -1
  129. package/dist/types/tokens/elevation.d.ts +4 -4
  130. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- // Attio's adjustable-panel primitive (measured live — see
4
- // docs/study/attio-panels.md §1-2). Two elements carry the layout: an
3
+ // The adjustable-panel primitive (measured live). Two elements carry the
4
+ // layout: an
5
5
  // invisible SPACER that reserves flow width (it alone animates `width`, a
6
6
  // cheap reflow of a leaf node) and the PANEL, taken out of flow with
7
7
  // `position: absolute` and drawn on top of the spacer. That split is what
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A segmented control — Attio's view switcher: a subtle track holding options,
3
+ // A segmented control — a view switcher: a subtle track holding options,
4
4
  // the selected one raised on a white pill.
5
5
  const config = defineRecipe({
6
6
  name: "segmented",
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- // A select / dropdown, measured from Attio's settings: a 32px combobox trigger
3
+ // A select / dropdown, measured from settings: a 32px combobox trigger
4
4
  // (radius 9, value + a 16px chevron) over a listbox — radius 12, 4px padding, a
5
5
  // layered soft shadow — of 32px options (radius 8, 6/8 padding) that show a
6
6
  // check on the selected one and highlight on hover / keyboard. The listbox is
@@ -54,7 +54,7 @@ const config = defineRecipe({
54
54
  `,
55
55
  variants: {
56
56
  // ghost: borderless at rest (transparent), reveals a subtle fill on hover —
57
- // Attio's inline selects (e.g. the sort configurator).
57
+ // inline selects (e.g. the sort configurator).
58
58
  variant: {
59
59
  default: "",
60
60
  ghost: `
@@ -2,9 +2,9 @@ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
3
  // seed-design's slider, shape for shape, in crisp's colours.
4
4
  //
5
- // Attio ships no slider anywhere — Records, Reports, Settings and the record
5
+ // No slider ships anywhere — Records, Reports, Settings and the record
6
6
  // pages contain no `input[type=range]` or `[role=slider]` — so there is nothing
7
- // of Attio's to measure. The GEOMETRY is therefore seed's own, read from
7
+ // measured to draw from. The GEOMETRY is therefore seed's own, read from
8
8
  // `@seed-design/css/recipes/slider.css`: a 26px control row, a 4px track on
9
9
  // `radius.full`, a 20px thumb whose visible disc is an `::after` that scales to
10
10
  // 1.2 while dragging, and a 2px focus ring offset 2px.
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A pipeline stage indicator — Attio's Deal-stage Highlight bar: one segment per
3
+ // A pipeline stage indicator — a Deal-stage Highlight bar: one segment per
4
4
  // stage, each tinted with its stage colour, the current stage at full strength.
5
5
  const config = defineRecipe({
6
6
  name: "stagebar",
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A single-metric KPI tile — measured from Attio's Reports "Insight" number
3
+ // A single-metric KPI tile — measured from a Reports "Insight" number
4
4
  // report: a small muted label, a large semibold value, and an optional delta
5
5
  // pill (green up / red down) with a caption. Fills its container.
6
6
  const config = defineRecipe({
@@ -18,7 +18,7 @@ const config = defineRecipe({
18
18
  & .statcard-delta[data-trend="flat"] { background: color-mix(in srgb, ${c.fgPrimary} 6%, transparent); color: ${c.fgMuted}; }`,
19
19
  variants: {
20
20
  // Opt-in chrome for consumers who want the tile self-contained instead of
21
- // hand-wrapping it in <Card><CardBody>. Not measured as part of the Attio
21
+ // hand-wrapping it in <Card><CardBody>. Not measured as part of the
22
22
  // report tile itself (the tile sits bare inside the report's own Card —
23
23
  // see the docs page) — reuses Card's exact border/radius/bg rather than
24
24
  // inventing a new value, since it is only ever an explicit opt-in.
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // Attio's settings toggle, measured from the live app: a 24×16 pill track that
3
+ // A settings toggle, measured from the live app: a 24×16 pill track that
4
4
  // flips from a muted grey to brand blue (#266df0), with a 12px white thumb
5
5
  // (2px inset) that slides 8px across. background + transform both animate .2s.
6
6
  const config = defineRecipe({
@@ -2,7 +2,7 @@ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
3
  // A general-purpose, composable data table — the lightweight primitive for
4
4
  // arbitrary tabular data (as opposed to `product/recordstable`, which is a
5
- // faithful rebuild of Attio's heavy records grid). It carries the SAME measured
5
+ // faithful rebuild of a heavy records grid). It carries the SAME measured
6
6
  // grid styling as RecordsTable — 36px rows, a 40px header, hairline vertical +
7
7
  // horizontal grid lines — so `DataTable` (built on this) matches that polish.
8
8
  const config = defineRecipe({
@@ -1,12 +1,12 @@
1
1
  import { contract as c, elevation as e } from "../../tokens/index.js";
2
- // The measured chrome of Attio's table toolbar: the Sort/Filter controls, the
2
+ // The measured chrome of the table toolbar: the Sort/Filter controls, the
3
3
  // menu/popover surface they open into, the sort-condition rows, and the filter
4
4
  // chips. It lives here, parameterised by class prefix, because TWO surfaces
5
5
  // render it — the standalone `TableToolbar` primitive and `RecordsTable`, whose
6
6
  // markup predates it and must keep its own `recordstable-` class names.
7
7
  //
8
8
  // These strings were MOVED out of `recordstable.recipe.ts` verbatim, not
9
- // retyped: every value is still the one measured from Attio. Do not "tidy" them.
9
+ // retyped: every value is still the one originally measured. Do not "tidy" them.
10
10
  //
11
11
  // It comes in two halves because RecordsTable interleaves three rules of its own
12
12
  // (the context-menu z-index and the column drop-target) into the middle of the
@@ -1,7 +1,7 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
3
  import { toolbarChromeBody, toolbarChromeHead } from "./tabletoolbar.chrome.js";
4
- // Attio's table toolbar, measured: 28px controls, the Sort/Filter buttons and
4
+ // The table toolbar, measured: 28px controls, the Sort/Filter buttons and
5
5
  // the menus they open, sort-condition rows, and the filter chips. The chrome
6
6
  // itself lives in ./tabletoolbar.chrome.ts because RecordsTable renders the
7
7
  // same measured surface under its own class prefix — one source, two prefixes,
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // Attio's record-view tabs: a row of segmented tab buttons over a 1px baseline.
3
+ // Record-view tabs: a row of segmented tab buttons over a 1px baseline.
4
4
  // The active tab is a light pill — bg #fbfbfb + inset ring borderSubtle, r8 —
5
5
  // with a 2px ink underline that slides along the baseline; inactive tabs are
6
6
  // muted and fill to a subtle pill on hover. Each tab carries a 16px leading icon
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- // A multiline text field, measured from Attio's settings "Personal context": an
3
+ // A multiline text field, measured from a settings "Personal context" field: an
4
4
  // inset 1px ring (radius 8), 14px text, 6/10 padding, and an optional character
5
5
  // counter pinned bottom-right (12px, muted). Focus rings the field brand.
6
6
  const config = defineRecipe({
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // The floating bubble for a Tooltip — Attio's dark hint chip. Applied to the
3
+ // The floating bubble for a Tooltip — a dark hint chip. Applied to the
4
4
  // portaled bubble itself (not a wrapper), so its styles survive the portal.
5
5
  const config = defineRecipe({
6
6
  name: "tooltip",
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Zag's dialog machine always advertises a description: `getContentProps()`
3
3
  * returns an `aria-describedby` pointing at the id of a description element.
4
- * crisp renders no such element — Attio's modals have a title and a body, no
4
+ * crisp renders no such element — the measured modals have a title and a body, no
5
5
  * description line — so the reference dangles, and a dangling id is not a
6
6
  * relationship a screen reader can follow.
7
7
  *
package/dist/esm/index.js CHANGED
@@ -54,7 +54,7 @@ export * from "./components/tooltip/index.js";
54
54
  export * from "./components/wheelpicker/index.js";
55
55
  export * from "./core/index.js";
56
56
  // product surfaces (product/) — faithful, pixel-measured rebuilds of specific
57
- // Attio screens (Sidebar, RecordsTable, RecordPage, Inbox, …). Use them as-is
57
+ // product screens (Sidebar, RecordsTable, RecordPage, Inbox, …). Use them as-is
58
58
  // or as composition references for your own data; `components/` above holds
59
59
  // the generic primitives (Table, DataTable, Button, …) to build your own UI from.
60
60
  export * from "./product/appshell/index.js";
@@ -1,7 +1,7 @@
1
1
  import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
3
  // App-shell layout: a collapsible + resizable sidebar pane next to a main pane,
4
- // mirroring how Attio's window works. The sidebar pane clips (never squishes)
4
+ // mirroring a familiar app-window layout. The sidebar pane clips (never squishes)
5
5
  // when collapsing, and a drag handle on its edge resizes it.
6
6
  const config = defineRecipe({
7
7
  name: "appshell",
@@ -1,11 +1,11 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // Attio's welcome/auth surface (app.attio.com/welcome/*) — measured live,
3
+ // A welcome/auth surface — measured live,
4
4
  // 2026-09-15. A centered page frame holding a two-pane card: the form on the
5
5
  // left, an optional product preview on the right, with an optional top
6
6
  // progress bar and a footer under the card. Every value below is measured
7
7
  // from the live app, EXCEPT the 1200px preview-hiding breakpoint (called out
8
- // at the container query below) — Attio drops the pane in JS somewhere between a
8
+ // at the container query below) — the pane drops out in JS somewhere between a
9
9
  // measured 954px and 1393px viewport width, so 1200px is chosen, not measured.
10
10
  const config = defineRecipe({
11
11
  name: "authshell",
@@ -48,7 +48,7 @@ const config = defineRecipe({
48
48
  & .authshell-body .button { height: 36px; padding-inline: ${c.space["3"]}; border-radius: 10px; }
49
49
  & .authshell-body .button--intent_primary { box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08); }
50
50
 
51
- /* Attio drops the preview pane in JS on narrow viewports (measured: two
51
+ /* The preview pane drops out in JS on narrow viewports (measured: two
52
52
  panes at 1393px, one at 954px), so 1200px is a chosen threshold inside
53
53
  that bracket, not a measured value. A CONTAINER query, not a media
54
54
  query: the shell is embedded in the docs inside an ~800px column, where
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A kanban board — measured from Attio's Deals pipeline: horizontally scrolling
3
+ // A kanban board — measured from a Deals pipeline: horizontally scrolling
4
4
  // columns (dot + title + count header, a "New" button, a stack of draggable
5
5
  // cards), with the hovered drop column highlighted.
6
6
  const config = defineRecipe({
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A note / entity card — measured from Attio's Notes grid: a bordered white card
3
+ // A note / entity card — measured from a Notes grid: a bordered white card
4
4
  // with an author row (avatar + name) at the top, a title, a clamped excerpt,
5
5
  // and a footer row (avatar + name … date). The whole card is clickable.
6
6
  const config = defineRecipe({
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A pannable, zoomable node canvas — measured from Attio's Workflows editor:
3
+ // A pannable, zoomable node canvas — measured from a Workflows editor:
4
4
  // a dotted-grid background, draggable node cards, and connecting edges with dots.
5
5
  const config = defineRecipe({
6
6
  name: "flowcanvas",
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A notifications inbox panel — measured from Attio's notification flyout: a
3
+ // A notifications inbox panel — measured from a notification flyout: a
4
4
  // ~380px rounded panel with a title, "Notifications / Requests" tabs (with
5
5
  // counts), then notification rows (avatar + message + time + unread dot) or a
6
6
  // centred empty state. Drop it in a Popover for the flyout, or use standalone.
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // The entity-list page shell — measured from Attio's Reports / Sequences / Tasks
3
+ // The entity-list page shell — measured from Reports / Sequences / Tasks
4
4
  // / Notes list views: a view-bar toolbar (leading Sort/Filter, trailing view
5
5
  // toggle / settings / New, and a record count), an optional dashed "Favorites"
6
6
  // region, then a list with column headers and time-grouped 52px rows.
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // An onboarding checklist card — measured from Attio's floating "Getting started"
3
+ // An onboarding checklist card — measured from a floating "Getting started"
4
4
  // widget: a title + menu/minimize header, a "N/total steps" subtitle, a
5
5
  // segmented progress bar (filled pills brand, rest 4% ink), then step rows with
6
6
  // an icon + label; completed rows strike through and show a brand check.
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- // The full-page company record view Attio opens when you click into a record —
3
+ // The full-page company record view opened when you click into a record —
4
4
  // measured from the live app. A slim top bar (breadcrumb · logo · name 16/600 ·
5
5
  // actions), then a two-column body: a 320px left "Record Details" attribute
6
6
  // column (transparent, border-right) and a flexible main area whose tab bar
@@ -50,7 +50,7 @@ const config = defineRecipe({
50
50
  & .recordpage-section { padding-top: ${c.space["2"]}; }
51
51
  & .recordpage-section-title { font-size: ${c.text.sm}; font-weight: ${c.weight.medium}; letter-spacing: -0.12px; color: color-mix(in srgb, ${c.fgPrimary} 63%, transparent); padding: ${c.space["1"]}; }
52
52
  /* main-area section headers (Highlights / Activity / Emails / Notes / Tasks)
53
- are 14px in Attio; the left column's (Record Details / Lists) stay 12px. */
53
+ are 14px; the left column's (Record Details / Lists) stay 12px. */
54
54
  & .recordpage-main .recordpage-section-title { font-size: ${c.text.lg}; }
55
55
  & .recordpage-detailhead { display: flex; align-items: center; gap: ${c.space["0.5"]}; margin-bottom: ${c.space["3"]}; padding-inline-end: ${c.space["0.5"]}; }
56
56
  & .recordpage-collapse { display: inline-flex; align-items: center; gap: 2px; flex: 1; min-width: 0; margin: 0; border: none; background: none; padding: ${c.space["1"]}; border-radius: ${c.radius.md}; font-family: inherit; font-size: ${c.text.sm}; font-weight: ${c.weight.medium}; letter-spacing: -0.12px; color: ${c.fgMuted}; cursor: pointer; text-align: start; }
@@ -2,7 +2,7 @@ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
3
  import { recordTagCss } from "../recordstable/recordstable.tag.js";
4
4
  // A right-side record peek panel — slides in over the main content to show one
5
- // record's fields, the way Attio opens a row. Positioned absolutely inside a
5
+ // record's fields, the way a row peek panel opens. Positioned absolutely inside a
6
6
  // relative container (the app main area); slides in via @starting-style.
7
7
  const config = defineRecipe({
8
8
  name: "recordpanel",
@@ -2,7 +2,7 @@ import { toolbarChromeBody, toolbarChromeHead, } from "../../components/tabletoo
2
2
  import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
3
3
  import { contract as c } from "../../tokens/index.js";
4
4
  import { recordTagCss } from "./recordstable.tag.js";
5
- // Attio's record grid, measured: 36px rows, 1px borderSubtle (#eeeff1) grid
5
+ // A record grid, measured: 36px rows, 1px borderSubtle (#eeeff1) grid
6
6
  // lines on BOTH axes, sticky checkbox + entity (first) columns, entity = 16px
7
7
  // avatar + 14px/500 name, 28px toolbar controls, a floating bulk-action bar.
8
8
  //
@@ -112,7 +112,7 @@ ${toolbarChromeBody("recordstable")}
112
112
  /* box-shadow has no logical form either: the bleed follows the scrolled
113
113
  content, which is the opposite side under RTL. */
114
114
  [dir="rtl"] & .recordstable-scroll[data-scrolled] .recordstable-col-entity { box-shadow: -6px 0 16px 4px rgba(0,0,0,0.12); }
115
- /* AI-enriched values carry a purple wash. Measured from Attio:
115
+ /* AI-enriched values carry a purple wash. Measured live:
116
116
  a full-bleed overlay at #9b69ff 4% (== bgPurple), composited OVER
117
117
  whatever row-state background the cell already has, which is why it
118
118
  is an ::after and not a background. */
@@ -1,6 +1,6 @@
1
1
  import { contract as c } from "../../tokens/index.js";
2
2
  /**
3
- * The record tag/chip, measured from Attio: 22px tall, `padding: 0 4px`,
3
+ * The record tag/chip, measured live: 22px tall, `padding: 0 4px`,
4
4
  * `border-radius: ${c.radius.chip}`, 14px/20px at weight 500, and a 1px inset ring in the
5
5
  * tone's colour.
6
6
  *
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A block rich-text editor — measured from Attio's Notes editor: a large 32/36
3
+ // A block rich-text editor — measured from a Notes editor: a large 32/36
4
4
  // title, a 14/20 prose body (headings, lists, quote, code, marks, links), and a
5
5
  // floating selection toolbar. Built on contentEditable so it stays dependency-
6
6
  // free. Placeholders show via [data-empty]::before.
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A settings section — measured from Attio's Settings pages: a 16px/600 title
3
+ // A settings section — measured from Settings pages: a 16px/600 title
4
4
  // with an optional subtitle, then a stack of rows (form fields, toggles…). Rows
5
5
  // gap evenly; an optional trailing action sits on the title row.
6
6
  const config = defineRecipe({
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // The Settings layout — measured from Attio's Settings: a 256px left nav with a
3
+ // The Settings layout — measured from a Settings screen: a 256px left nav with a
4
4
  // back header, a search field, and grouped nav items (active row raised), beside
5
5
  // a scrolling content pane. Sits inside whatever height its container gives it.
6
6
  const config = defineRecipe({
@@ -15,7 +15,7 @@ const config = defineRecipe({
15
15
 
16
16
  & .settingsshell-search { display: flex; align-items: center; gap: ${c.space["2"]}; height: 32px; margin-bottom: ${c.space["2"]}; padding: 0 ${c.space["2.5"]}; border-radius: ${c.radius.md}; background: ${c.bgSurface}; box-shadow: inset 0 0 0 1px ${c.borderDefault}; color: ${c.fgMuted}; }
17
17
  /* The field box owns the ring, so focus has to move it -- the inner
18
- input kills its own outline. Measured on Attio: a focused field's
18
+ input kills its own outline. Measured live: a focused field's
19
19
  input carries box-shadow: none while its wrapper carries
20
20
  inset 0 0 0 1px #266df0. */
21
21
  & .settingsshell-search:focus-within { box-shadow: inset 0 0 0 1px ${c.bgBrandSolid}; }
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A task list — measured from Attio's Tasks page: optional group headers, then
3
+ // A task list — measured from a Tasks page: optional group headers, then
4
4
  // rows of a round complete-checkbox + title + trailing meta (due date, record,
5
5
  // assignee). Completed rows strike through; overdue due-dates go red.
6
6
  const config = defineRecipe({
@@ -1,8 +1,8 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- // A compact trial / upgrade banner — measured from Attio's sidebar footer: an
3
+ // A compact trial / upgrade banner — measured from a sidebar footer: an
4
4
  // icon + a message on the left and a small action pill on the right, in a 28px
5
- // row. The action uses Attio's soft-glow outlined-button shadow.
5
+ // row. The action uses the measured soft-glow outlined-button shadow.
6
6
  const config = defineRecipe({
7
7
  name: "trialbanner",
8
8
  base: `display: flex; align-items: center; gap: ${c.space["1.5"]}; box-sizing: border-box; min-height: 28px;
@@ -1,6 +1,6 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- // A compact icon toggle — measured from Attio's list/grid switch: a 28px track
3
+ // A compact icon toggle — measured from a list/grid switch: a 28px track
4
4
  // (radius 10, ~5% ink) padded 2px, holding 24px icon tiles (radius 8). The
5
5
  // selected tile gets a raised surface with a soft shadow.
6
6
  const config = defineRecipe({
@@ -1,9 +1,9 @@
1
1
  import { contract as c } from "./contract.js";
2
2
  /**
3
- * Attio's measured elevation recipes, written **once**.
3
+ * The measured elevation recipes, written **once**.
4
4
  *
5
5
  * The whole product runs on two elevation tiers plus one control shadow
6
- * (measured live — see `docs/study/attio-panels.md` §4). Before this module each
6
+ * (measured live — see the panels study §4). Before this module each
7
7
  * surface carried its own copy of the string: the tier-1 stack appeared in 9
8
8
  * places, the control shadow in 12. Copies drift, and every drift was a real
9
9
  * bug — `Drawer`/`RecordPanel` grew invented directional shadows, `BulkBar`'s
@@ -20,14 +20,14 @@ export const elevation = {
20
20
  /**
21
21
  * Tier 2 — the modal frosted bezel (Dialog, Command). Sits on the
22
22
  * `bgOverlayFrost` 60% + `blur(15px)` surface at radius 16, wrapping an inner
23
- * card at radius 12. Attio dims nothing behind it; the blur does the work.
23
+ * card at radius 12. Nothing is dimmed behind it; the blur does the work.
24
24
  */
25
25
  modal: `0 8px 28px -6px ${c.shadowOverlay1}, 0 18px 88px -4px ${c.shadowOverlay2}, 0 0 1px ${c.shadowOverlay3}`,
26
26
  /**
27
27
  * The neutral/outlined control shadow — buttons, inputs, textareas, the
28
28
  * sidebar search, record-page actions.
29
29
  *
30
- * The two raw values **are** the measured Attio value (Lessons 22 and 29) and
30
+ * The two raw values **are** the measured value (Lessons 22 and 29) and
31
31
  * must stay raw. `rgba(0,0,0,0.04)` equals `tileActiveShadow`'s light value by
32
32
  * coincidence, not by meaning; tokenizing it would delete a measured layer in
33
33
  * dark mode. Only the ring is theme-aware, via `ringNeutral`.
@@ -2,7 +2,7 @@ export const palette = {
2
2
  gray00: { light: "#ffffff", dark: "#0a0a0a" },
3
3
  white: { light: "#ffffff", dark: "#ffffff" },
4
4
  // the counterpart to `white`: ink that does NOT flip with the theme, for text
5
- // on a bright tone fill. Same value as gray900's light side (Attio's measured
5
+ // on a bright tone fill. Same value as gray900's light side (the measured
6
6
  // near-black), named separately because its job is not "primary foreground".
7
7
  ink: { light: "#101112", dark: "#101112" },
8
8
  gray50: { light: "#f4f4f5", dark: "#101112" },
@@ -28,7 +28,7 @@ export const palette = {
28
28
  // A red dark enough to carry white text. red600 cannot: white on it is
29
29
  // 3.91:1 light / 3.05:1 dark, and the solid button's hover DARKENS the fill
30
30
  // (filter: brightness), so dark ink fails there instead (4.49 at hover).
31
- // Measured from Attio's own stylesheet, which ships this red alongside the
31
+ // Measured from the reference stylesheet, which ships this red alongside the
32
32
  // #EB3B3B it uses for destructive menu TEXT. Does not flip: a filled
33
33
  // destructive control needs the same white-bearing fill in both themes.
34
34
  red700: { light: "#ba2525", dark: "#ba2525" },
@@ -2,7 +2,7 @@
2
2
  // component sizing. Theme-invariant (identical in light/dark), so it is emitted
3
3
  // once into :root, unlike the color tokens which flip per theme.
4
4
  //
5
- // Derived by measuring the live Attio app (not taste): its spacing is a
5
+ // Derived by measuring a live production app (not taste): its spacing is a
6
6
  // 2px-granular / 4px-base scale — the values 1,2,4,6,8,10,12,16 account for
7
7
  // nearly every gap/pad/margin in the sidebar. Radii cluster at 6/8/9 + a pill.
8
8
  // Recipes MUST reference these through the contract (`c.space[...]`), never a
@@ -22,10 +22,10 @@ export const space = {
22
22
  "6": "24px",
23
23
  "8": "32px", // overlay / empty-state padding
24
24
  };
25
- // Corner radius. sm/md/lg are the three Attio uses on stacked surfaces
25
+ // Corner radius. sm/md/lg are the three used on stacked surfaces
26
26
  // (inputs, rows, tiles); full is the pill.
27
27
  export const radius = {
28
- chip: "7px", // tag / chip corner — the single most used radius in Attio
28
+ chip: "7px", // tag / chip corner — the single most used radius
29
29
  sm: "6px", // chips, badges
30
30
  md: "8px", // inputs, search box
31
31
  lg: "9px", // rows, tiles, list items
@@ -37,20 +37,20 @@ export const radius = {
37
37
  // radius (row height, header height, the nav icon box).
38
38
  export const size = {
39
39
  icon: "16px", // nav / control glyph box
40
- chip: "22px", // tag / chip height — Attio's most repeated small control
40
+ chip: "22px", // tag / chip height — the most repeated small control
41
41
  row: "28px", // nav item · search · control height
42
42
  menuRow: "32px", // overlay row: menu item, select option, bulk-bar button
43
43
  tableRow: "36px", // data-grid row height
44
44
  tableHeader: "40px", // data-grid header row height
45
45
  header: "48px", // workspace-switcher header height
46
- // Attio's date picker, measured: a 32px day with a 2px gap on both axes, so
46
+ // The measured date picker: a 32px day with a 2px gap on both axes, so
47
47
  // the pitch is 34. The gap is expressed as the cell being 2px taller than the
48
48
  // highlight rather than as a grid gap, because crisp's range bridge spans
49
49
  // whole cells and a column gap would cut it.
50
50
  calendarCell: "34px", // calendar day pitch (32px day + 2px gap)
51
51
  calendarPill: "32px", // the day highlight itself
52
52
  };
53
- // Typography — Attio's UI runs entirely on Inter. Sizes measured in the sidebar
53
+ // Typography — the measured UI runs entirely on Inter. Sizes measured in the sidebar
54
54
  // collapse onto 11/12/13/14/16 (lg = 14px is the default body/label size);
55
55
  // weights are 400/500/600 with 500 the UI default.
56
56
  export const font = {
@@ -48,7 +48,7 @@ export const semantic = {
48
48
  bgCyan: "cyan600",
49
49
  bgPurple: "purple600",
50
50
  bgSidebar: "graySidebar",
51
- // #fbfbfb — Attio's subtle raised fill; the active tab pill uses the same
51
+ // #fbfbfb — the subtle raised fill; the active tab pill uses the same
52
52
  // value as the sidebar, so it shares the palette entry under a neutral name.
53
53
  bgSubtle: "graySidebar",
54
54
  };
@@ -23,12 +23,12 @@
23
23
  & .fileupload-zone[data-disabled] { opacity: .5; cursor: not-allowed; }
24
24
  & .fileupload-zone[data-invalid] { border-color: var(--bg-danger); }
25
25
 
26
- /* Attio: "No files" 16/20 weight 600 */
26
+ /* "No files" 16/20 weight 600 */
27
27
  & .fileupload-title {
28
28
  color: var(--fg-primary); font-size: var(--text-xl); line-height: 20px;
29
29
  font-weight: var(--weight-semibold);
30
30
  }
31
- /* Attio: the hint line, 14/20 weight 500 at 63% of the foreground */
31
+ /* The hint line, 14/20 weight 500 at 63% of the foreground */
32
32
  & .fileupload-hint {
33
33
  color: color-mix(in srgb, var(--fg-primary) 63%, transparent);
34
34
  font-size: var(--text-lg); line-height: 20px;
@@ -41,7 +41,7 @@
41
41
  & .recordpage-section { padding-top: var(--space-2); }
42
42
  & .recordpage-section-title { font-size: var(--text-sm); font-weight: var(--weight-medium); letter-spacing: -0.12px; color: color-mix(in srgb, var(--fg-primary) 63%, transparent); padding: var(--space-1); }
43
43
  /* main-area section headers (Highlights / Activity / Emails / Notes / Tasks)
44
- are 14px in Attio; the left column's (Record Details / Lists) stay 12px. */
44
+ are 14px; the left column's (Record Details / Lists) stay 12px. */
45
45
  & .recordpage-main .recordpage-section-title { font-size: var(--text-lg); }
46
46
  & .recordpage-detailhead { display: flex; align-items: center; gap: var(--space-0-5); margin-bottom: var(--space-3); padding-inline-end: var(--space-0-5); }
47
47
  & .recordpage-collapse { display: inline-flex; align-items: center; gap: 2px; flex: 1; min-width: 0; margin: 0; border: none; background: none; padding: var(--space-1); border-radius: var(--radius-md); font-family: inherit; font-size: var(--text-sm); font-weight: var(--weight-medium); letter-spacing: -0.12px; color: var(--fg-muted); cursor: pointer; text-align: start; }
@@ -167,7 +167,7 @@
167
167
  /* box-shadow has no logical form either: the bleed follows the scrolled
168
168
  content, which is the opposite side under RTL. */
169
169
  [dir="rtl"] & .recordstable-scroll[data-scrolled] .recordstable-col-entity { box-shadow: -6px 0 16px 4px rgba(0,0,0,0.12); }
170
- /* AI-enriched values carry a purple wash. Measured from Attio:
170
+ /* AI-enriched values carry a purple wash. Measured live:
171
171
  a full-bleed overlay at #9b69ff 4% (== bgPurple), composited OVER
172
172
  whatever row-state background the cell already has, which is why it
173
173
  is an ::after and not a background. */
@@ -9,7 +9,7 @@
9
9
 
10
10
  & .settingsshell-search { display: flex; align-items: center; gap: var(--space-2); height: 32px; margin-bottom: var(--space-2); padding: 0 var(--space-2-5); border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--border-default); color: var(--fg-muted); }
11
11
  /* The field box owns the ring, so focus has to move it -- the inner
12
- input kills its own outline. Measured on Attio: a focused field's
12
+ input kills its own outline. Measured live: a focused field's
13
13
  input carries box-shadow: none while its wrapper carries
14
14
  inset 0 0 0 1px #266df0. */
15
15
  & .settingsshell-search:focus-within { box-shadow: inset 0 0 0 1px var(--bg-brand-solid); }