@crisp-ui-kit/crisp 0.54.1 → 0.54.2

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 (106) hide show
  1. package/dist/cjs/components/datatable/datatable.js +2 -1
  2. package/dist/cjs/components/datatable/datatable.recipe.js +4 -0
  3. package/dist/cjs/components/mentionchip/index.js +7 -0
  4. package/dist/cjs/components/mentionchip/mentionchip.js +57 -0
  5. package/dist/cjs/components/mentionchip/mentionchip.recipe.js +38 -0
  6. package/dist/cjs/components/table/table.recipe.js +15 -3
  7. package/dist/cjs/core/floating-stack.js +18 -0
  8. package/dist/cjs/core/index.js +2 -1
  9. package/dist/cjs/index.js +6 -0
  10. package/dist/cjs/product/formdialog/formdialog.js +171 -0
  11. package/dist/cjs/product/formdialog/formdialog.recipe.js +26 -0
  12. package/dist/cjs/product/formdialog/index.js +8 -0
  13. package/dist/cjs/product/importdialog/importdialog.js +134 -0
  14. package/dist/cjs/product/importdialog/importdialog.recipe.js +92 -0
  15. package/dist/cjs/product/importdialog/index.js +18 -0
  16. package/dist/cjs/product/savedviews/index.js +7 -0
  17. package/dist/cjs/product/savedviews/savedviews.js +207 -0
  18. package/dist/cjs/product/savedviews/savedviews.recipe.js +103 -0
  19. package/dist/cjs/product/taskstable/index.js +7 -0
  20. package/dist/cjs/product/taskstable/taskstable.js +27 -0
  21. package/dist/cjs/product/taskstable/taskstable.recipe.js +47 -0
  22. package/dist/cjs/product/themepicker/index.js +17 -0
  23. package/dist/cjs/product/themepicker/themepicker.js +32 -0
  24. package/dist/cjs/product/themepicker/themepicker.recipe.js +98 -0
  25. package/dist/cjs/tokens/palette.js +30 -13
  26. package/dist/cjs/tokens/semantic.js +6 -0
  27. package/dist/datatable.css +20 -21
  28. package/dist/datatable.layered.css +20 -21
  29. package/dist/esm/components/datatable/datatable.js +2 -1
  30. package/dist/esm/components/datatable/datatable.recipe.js +4 -0
  31. package/dist/esm/components/mentionchip/index.js +2 -0
  32. package/dist/esm/components/mentionchip/mentionchip.js +21 -0
  33. package/dist/esm/components/mentionchip/mentionchip.recipe.js +35 -0
  34. package/dist/esm/components/table/table.recipe.js +15 -3
  35. package/dist/esm/core/floating-stack.js +17 -0
  36. package/dist/esm/core/index.js +1 -1
  37. package/dist/esm/index.js +6 -0
  38. package/dist/esm/product/formdialog/formdialog.js +134 -0
  39. package/dist/esm/product/formdialog/formdialog.recipe.js +23 -0
  40. package/dist/esm/product/formdialog/index.js +2 -0
  41. package/dist/esm/product/importdialog/importdialog.js +97 -0
  42. package/dist/esm/product/importdialog/importdialog.recipe.js +89 -0
  43. package/dist/esm/product/importdialog/index.js +2 -0
  44. package/dist/esm/product/savedviews/index.js +2 -0
  45. package/dist/esm/product/savedviews/savedviews.js +171 -0
  46. package/dist/esm/product/savedviews/savedviews.recipe.js +100 -0
  47. package/dist/esm/product/taskstable/index.js +2 -0
  48. package/dist/esm/product/taskstable/taskstable.js +24 -0
  49. package/dist/esm/product/taskstable/taskstable.recipe.js +44 -0
  50. package/dist/esm/product/themepicker/index.js +1 -0
  51. package/dist/esm/product/themepicker/themepicker.js +29 -0
  52. package/dist/esm/product/themepicker/themepicker.recipe.js +95 -0
  53. package/dist/esm/tokens/palette.js +30 -13
  54. package/dist/esm/tokens/semantic.js +6 -0
  55. package/dist/formdialog.css +6 -0
  56. package/dist/formdialog.d.ts +7 -0
  57. package/dist/formdialog.layered.css +8 -0
  58. package/dist/importdialog.css +38 -0
  59. package/dist/importdialog.d.ts +7 -0
  60. package/dist/importdialog.layered.css +40 -0
  61. package/dist/mentionchip.css +3 -0
  62. package/dist/mentionchip.d.ts +7 -0
  63. package/dist/mentionchip.layered.css +5 -0
  64. package/dist/native/tokens.d.ts +1 -1
  65. package/dist/native/tokens.js +14 -6
  66. package/dist/savedviews.css +78 -0
  67. package/dist/savedviews.d.ts +7 -0
  68. package/dist/savedviews.layered.css +80 -0
  69. package/dist/styles.css +223 -30
  70. package/dist/styles.layered.css +223 -30
  71. package/dist/table.css +15 -6
  72. package/dist/table.layered.css +15 -6
  73. package/dist/taskstable.css +23 -0
  74. package/dist/taskstable.d.ts +7 -0
  75. package/dist/taskstable.layered.css +25 -0
  76. package/dist/themepicker.css +27 -0
  77. package/dist/themepicker.d.ts +7 -0
  78. package/dist/themepicker.layered.css +29 -0
  79. package/dist/tokens.css +7 -3
  80. package/dist/tokens.json +14 -6
  81. package/dist/types/components/datatable/datatable.d.ts +12 -1
  82. package/dist/types/components/mentionchip/index.d.ts +2 -0
  83. package/dist/types/components/mentionchip/mentionchip.d.ts +20 -0
  84. package/dist/types/components/mentionchip/mentionchip.recipe.d.ts +18 -0
  85. package/dist/types/core/floating-stack.d.ts +14 -0
  86. package/dist/types/core/index.d.ts +1 -1
  87. package/dist/types/index.d.ts +6 -0
  88. package/dist/types/product/formdialog/formdialog.d.ts +57 -0
  89. package/dist/types/product/formdialog/formdialog.recipe.d.ts +3 -0
  90. package/dist/types/product/formdialog/index.d.ts +2 -0
  91. package/dist/types/product/importdialog/importdialog.d.ts +86 -0
  92. package/dist/types/product/importdialog/importdialog.recipe.d.ts +3 -0
  93. package/dist/types/product/importdialog/index.d.ts +2 -0
  94. package/dist/types/product/savedviews/index.d.ts +2 -0
  95. package/dist/types/product/savedviews/savedviews.d.ts +55 -0
  96. package/dist/types/product/savedviews/savedviews.recipe.d.ts +3 -0
  97. package/dist/types/product/taskstable/index.d.ts +2 -0
  98. package/dist/types/product/taskstable/taskstable.d.ts +54 -0
  99. package/dist/types/product/taskstable/taskstable.recipe.d.ts +3 -0
  100. package/dist/types/product/themepicker/index.d.ts +1 -0
  101. package/dist/types/product/themepicker/themepicker.d.ts +21 -0
  102. package/dist/types/product/themepicker/themepicker.recipe.d.ts +3 -0
  103. package/dist/types/tokens/contract.d.ts +2 -0
  104. package/dist/types/tokens/palette.d.ts +11 -3
  105. package/dist/types/tokens/semantic.d.ts +6 -0
  106. package/package.json +31 -1
@@ -0,0 +1,2 @@
1
+ export { TasksTable, } from "./taskstable.js";
2
+ export { taskstableRecipe } from "./taskstable.recipe.js";
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cx, useCrispMessage, useCrispMessages } from "../../core/index.js";
3
+ import { ListRow, listpageRecipe } from "../listpage/index.js";
4
+ import { taskstableRecipe } from "./taskstable.recipe.js";
5
+ function Cell({ flex, className, children, }) {
6
+ return (_jsx("span", { className: cx("crisp-taskstable-cell", className), style: { flex }, children: children }));
7
+ }
8
+ /**
9
+ * A grouped due-date table pattern — Attio's Tasks page. Composes
10
+ * `ListPage`'s toolbar and group-row chrome (both class-compatible; see
11
+ * taskstable.recipe.ts) with a typed column/cell layer: a title+checkbox
12
+ * row grouped into due-date sections, a due-date cell that goes red past
13
+ * due, and consumer-supplied record/assignee chip slots.
14
+ */
15
+ export function TasksTable({ columns, groups, leading, trailing, emptyLabel: emptyLabelProp, completeLabel: completeLabelProp, incompleteLabel: incompleteLabelProp, className, ...rest }) {
16
+ const crispMessages = useCrispMessages();
17
+ const emptyLabel = emptyLabelProp ?? crispMessages["No tasks"] ?? "No tasks";
18
+ const completeLabel = useCrispMessage(completeLabelProp, "Mark complete");
19
+ const incompleteLabel = useCrispMessage(incompleteLabelProp, "Mark incomplete");
20
+ const flexOf = (key) => columns.find((col) => col.key === key)?.flex ?? 1;
21
+ const total = groups.reduce((s, g) => s + g.rows.length, 0);
22
+ return (_jsxs("div", { className: cx(taskstableRecipe({ className }), listpageRecipe()), ...rest, children: [_jsxs("div", { className: "crisp-listpage-toolbar", children: [_jsx("div", { className: "crisp-listpage-toolbar-lead", children: leading }), trailing != null && (_jsx("div", { className: "crisp-listpage-toolbar-trail", children: trailing }))] }), _jsxs("div", { className: "crisp-listpage-body", children: [_jsx("div", { className: "crisp-taskstable-colhead", children: columns.map((col) => (_jsxs("span", { className: "crisp-taskstable-colhead-cell", style: { flex: col.flex ?? 1 }, children: [col.icon, col.label] }, col.key))) }), total === 0 ? (_jsx("div", { className: "crisp-taskstable-empty", children: emptyLabel })) : (groups.map((g) => (_jsxs("div", { children: [_jsxs("div", { className: "crisp-listpage-group", children: [g.label, _jsx("span", { className: "crisp-listpage-group-count", children: g.count })] }), g.rows.map((row) => (_jsx(ListRow, { children: _jsxs("div", { className: "crisp-taskstable-row", style: { flex: 1 }, children: [_jsxs(Cell, { flex: flexOf("title"), children: [_jsx("input", { type: "checkbox", className: "crisp-taskstable-check", checked: !!row.done, "aria-label": row.done ? incompleteLabel : completeLabel, onChange: () => row.onToggle?.(!row.done) }), _jsx("span", { className: "crisp-taskstable-title", children: row.title })] }), _jsx(Cell, { flex: flexOf("due"), children: row.due != null && (_jsx("span", { className: "crisp-taskstable-due", "data-overdue": row.due.overdue ? "" : undefined, children: row.due.label })) }), _jsx(Cell, { flex: flexOf("record"), children: row.record }), _jsx(Cell, { flex: flexOf("assignee"), children: row.assignee })] }) }, row.id)))] }, g.id))))] })] }));
23
+ }
24
+ TasksTable.displayName = "TasksTable";
@@ -0,0 +1,44 @@
1
+ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
+ import { contract as c } from "../../tokens/index.js";
3
+ // A grouped due-date table — Attio's Tasks page (app.attio.com/<ws>/tasks),
4
+ // measured live and recorded on crisp#462. Composes ListPage's own toolbar
5
+ // (`.crisp-listpage-toolbar`) and group-row (`.crisp-listpage-group`) chrome
6
+ // by carrying BOTH this recipe's root class and `listpageRecipe`'s root class
7
+ // on the same element (see taskstable.tsx) -- both recipes' descendant rules
8
+ // nest under their own root class, so this is a safe, ordinary composition,
9
+ // the same way `<ListRow>` already lets a caller compose into `ListPage`'s
10
+ // group bodies. Real deviation: ListPage's own `columns` colhead slot is
11
+ // pinned to `c.size.menuRow` (32px, correct for its Reports/Sequences
12
+ // reference surfaces per #479) but Tasks/Notes independently measure a 49px
13
+ // column-header row (#462) -- ListPage's colhead can't be asked to render at
14
+ // a different height per consumer today, so this component renders its own
15
+ // colhead instead of using that slot. Flagged in the PR, not fixed here (out
16
+ // of scope: don't change ListPage for this component).
17
+ const config = defineRecipe({
18
+ name: "taskstable",
19
+ base: `display: flex; flex-direction: column; min-height: 0; box-sizing: border-box; font-family: ${c.font.sans}; color: ${c.fgPrimary};
20
+ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
21
+
22
+ & .crisp-taskstable-colhead { display: flex; align-items: center; gap: ${c.space["1.5"]}; min-height: 49px; max-height: 49px; padding: ${c.space["2.5"]} ${c.space["3"]}; box-shadow: inset 0 -1px 0 ${c.borderSubtle}; font-size: ${c.text.sm}; color: ${c.fgMuted}; }
23
+ & .crisp-taskstable-colhead-cell { display: inline-flex; align-items: center; gap: ${c.space["1.5"]}; min-width: 0; }
24
+
25
+ & .crisp-taskstable-row { display: flex; align-items: center; gap: ${c.space["1.5"]}; }
26
+ & .crisp-taskstable-cell { display: flex; align-items: center; min-width: 0; }
27
+
28
+ & .crisp-taskstable-check { appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: ${c.radius.full}; background: ${c.bgSurface}; box-shadow: inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s; }
29
+ & .crisp-taskstable-check:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 30%, transparent); }
30
+ & .crisp-taskstable-check:checked { background: ${c.bgBrandSolid} center / 10px no-repeat; box-shadow: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
31
+ & .crisp-taskstable-check:focus-visible { outline: 2px solid ${c.bgBrandSolid}; outline-offset: 1px; }
32
+
33
+ & .crisp-taskstable-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: ${c.text.lg}; font-weight: ${c.weight.medium}; color: ${c.fgPrimary}; }
34
+
35
+ & .crisp-taskstable-due { font-size: ${c.text.lg}; color: ${c.fgMuted}; white-space: nowrap; }
36
+ & .crisp-taskstable-due[data-overdue] { color: ${c.fgDanger}; }
37
+
38
+ & .crisp-taskstable-empty { padding: ${c.space["8"]} ${c.space["4"]}; text-align: center; font-size: ${c.text.md}; color: ${c.fgMuted}; }`,
39
+ variants: {},
40
+ defaultVariants: {},
41
+ compoundVariants: [],
42
+ });
43
+ export const taskstableRecipe = resolveRecipe(config);
44
+ export default config;
@@ -0,0 +1 @@
1
+ export * from "./themepicker.js";
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRadioGroupKeyboard } from "../../components/radiogroup/index.js";
3
+ import { useCrispMessage } from "../../core/index.js";
4
+ import { themepickerRecipe } from "./themepicker.recipe.js";
5
+ const OPTIONS = ["light", "dark", "system"];
6
+ function PreviewSwatch({ swatch }) {
7
+ return (_jsxs("div", { className: "crisp-themepicker-preview", "data-swatch": swatch, children: [_jsxs("div", { className: "crisp-themepicker-preview-side", children: [_jsx("div", { className: "crisp-themepicker-preview-bar" }), _jsx("div", { className: "crisp-themepicker-preview-bar" }), _jsx("div", { className: "crisp-themepicker-preview-bar" })] }), _jsxs("div", { className: "crisp-themepicker-preview-main", children: [_jsx("div", { className: "crisp-themepicker-preview-bar" }), _jsx("div", { className: "crisp-themepicker-preview-bar" }), _jsx("div", { className: "crisp-themepicker-preview-bar" })] })] }));
8
+ }
9
+ /**
10
+ * A light/dark/system theme picker — three cards, each a small preview of
11
+ * what that option looks like, radio-selectable. See the recipe's own doc
12
+ * comment for the live Attio measurement (crisp#462 gap 4) and for why the
13
+ * preview swatch colours are literal rather than `var(--crisp-*)` tokens.
14
+ */
15
+ export function ThemePicker({ value, onChange, labels, className, ...rest }) {
16
+ const lightLabel = useCrispMessage(labels?.light, "Light");
17
+ const darkLabel = useCrispMessage(labels?.dark, "Dark");
18
+ const systemLabel = useCrispMessage(labels?.system, "System");
19
+ const labelFor = {
20
+ light: lightLabel,
21
+ dark: darkLabel,
22
+ system: systemLabel,
23
+ };
24
+ const { onKeyDown, groupRef } = useRadioGroupKeyboard({
25
+ select: (v) => onChange(v),
26
+ });
27
+ return (_jsx("div", { ref: groupRef, className: themepickerRecipe({ className }), role: "radiogroup", onKeyDown: onKeyDown, ...rest, children: OPTIONS.map((option) => (_jsxs("button", { type: "button", role: "radio", "aria-checked": value === option, "data-value": option, className: "crisp-themepicker-option", "data-selected": value === option ? "" : undefined, onClick: () => onChange(option), children: [_jsx(PreviewSwatch, { swatch: option }), _jsxs("span", { className: "crisp-themepicker-label", children: [_jsx("span", { className: "crisp-themepicker-radio", "aria-hidden": "true" }), labelFor[option]] })] }, option))) }));
28
+ }
29
+ ThemePicker.displayName = "ThemePicker";
@@ -0,0 +1,95 @@
1
+ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
+ import { contract as c } from "../../tokens/index.js";
3
+ // A theme picker (crisp#571) — measured live at
4
+ // app.attio.com/<ws>/settings/appearance (Settings -> Appearance -> Theme,
5
+ // its "Light" / "Dark" / "System" tiles):
6
+ // each option is a 224x152 card, 16px radius, on a flex row with an 8px
7
+ // gap. Selected carries a 1px solid brand-blue border (theme-constant
8
+ // #266df0, matches `bgBrandSolid`); unselected carries the ordinary
9
+ // hairline (`borderSubtle`). Inside, a ~214x114 mock-UI preview card sits
10
+ // on the same 12px radius / 1px hairline chrome the real Sidebar itself
11
+ // uses, with a label row below (a radio dot + 14px/500 text, `fgPrimary`
12
+ // when selected, muted when not).
13
+ //
14
+ // The preview card's OWN colours are deliberately literal, not `var(--crisp-*)`
15
+ // tokens: they must show what "Light"/"Dark" look like regardless of the
16
+ // picker's own ambient theme (a dark-mode app still needs its "Light" tile
17
+ // to render light), and crisp's token system only has one live value per
18
+ // custom property at a time -- there's no way to force a light subtree
19
+ // inside a dark ancestor without one. This is also how Attio's own tiles
20
+ // behave: their preview is a fixed illustration asset, not theme-reactive
21
+ // markup (confirmed by reading the SVG's own baked-in fills while the app
22
+ // itself was in light mode: the "Dark" tile's fills were already dark).
23
+ // The literals below are simply the EXISTING dual-theme tokens' own two
24
+ // values, spelled out per swatch rather than invented fresh: bgSidebar
25
+ // (#fbfbfb / #0e0f10), gray00/bgSurface (#ffffff / #0a0a0a), borderSubtle
26
+ // (#eeeff1 / #1c1d1f) -- each matches what Attio's own SVG measured
27
+ // (#0B0C0D-#101112 range for backgrounds, #1B1C1F for dividers) closely
28
+ // enough to treat as the same token rather than a fresh, barely-different
29
+ // one. `bgBrandSolid` (#266df0) IS referenced live since it's already
30
+ // theme-constant.
31
+ //
32
+ // "System" mirrors the OS's own effective scheme via `prefers-color-scheme`,
33
+ // not a guessed split illustration: this session's own System tile
34
+ // rendered with the SAME fills as the Light tile while the OS/browser
35
+ // reported light -- reads as "follows the OS", not a fixed half-and-half
36
+ // image there's no other evidence for.
37
+ //
38
+ // The mock-UI content inside each preview card (Attio's own hand-drawn
39
+ // sidebar/content wireframe SVG) is NOT reproduced pixel-for-pixel here --
40
+ // that illustration is decorative, not a measured design value, so this
41
+ // recipe draws a simplified schematic (a sidebar block + a few content
42
+ // bars) instead of a bespoke SVG asset.
43
+ //
44
+ // Attio's unselected label reads a black-alpha `rgba(0,0,0,0.63)`, the
45
+ // same pattern SettingsSection's own subtitle measured (crisp#522) and
46
+ // left unresolved for the same reason: no confirmed dark-mode value yet.
47
+ // `fgMuted` is used here as the closest existing (and already dual-theme)
48
+ // token rather than repeating an unmeasured-in-dark literal.
49
+ const config = defineRecipe({
50
+ name: "themepicker",
51
+ base: `display: flex; gap: ${c.space["2"]}; font-family: ${c.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
52
+ & .crisp-themepicker-option { box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: ${c.space["1.5"]}; width: 224px; padding: ${c.space["1"]}; border: 1px solid ${c.borderSubtle}; border-radius: 16px; background: ${c.bgSurface}; cursor: pointer; font-family: inherit; }
53
+ & .crisp-themepicker-option[data-selected] { border-color: ${c.bgBrandSolid}; }
54
+
55
+ & .crisp-themepicker-preview { box-sizing: border-box; display: flex; width: 100%; height: 114px; padding: ${c.space["2"]}; gap: ${c.space["1.5"]}; border-radius: ${c.radius.xl}; overflow: hidden; }
56
+ & .crisp-themepicker-preview-side { flex-shrink: 0; width: 28%; display: flex; flex-direction: column; gap: ${c.space["1"]}; }
57
+ & .crisp-themepicker-preview-bar { height: 4px; border-radius: ${c.radius.full}; }
58
+ & .crisp-themepicker-preview-bar:nth-child(1) { width: 70%; background: ${c.bgBrandSolid}; }
59
+ & .crisp-themepicker-preview-bar:nth-child(2) { width: 90%; }
60
+ & .crisp-themepicker-preview-bar:nth-child(3) { width: 60%; }
61
+ & .crisp-themepicker-preview-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: ${c.space["1.5"]}; padding: ${c.space["1.5"]}; border-radius: ${c.radius.md}; }
62
+
63
+ /* Light / System (default) swatch colours. */
64
+ & .crisp-themepicker-preview[data-swatch="light"],
65
+ & .crisp-themepicker-preview[data-swatch="system"] { border: 1px solid #eeeff1; background: #fbfbfb; }
66
+ & [data-swatch="light"] .crisp-themepicker-preview-bar:not(:nth-child(1)),
67
+ & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #eeeff1; }
68
+ & [data-swatch="light"] .crisp-themepicker-preview-main,
69
+ & [data-swatch="system"] .crisp-themepicker-preview-main { background: #ffffff; }
70
+ & [data-swatch="light"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar,
71
+ & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #eeeff1; }
72
+
73
+ /* Dark swatch colours -- always for "dark", and for "system" only
74
+ when the OS itself reports dark. */
75
+ & .crisp-themepicker-preview[data-swatch="dark"] { border: 1px solid #1c1d1f; background: #0e0f10; }
76
+ & [data-swatch="dark"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; }
77
+ & [data-swatch="dark"] .crisp-themepicker-preview-main { background: #0a0a0a; }
78
+ & [data-swatch="dark"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #1c1d1f; }
79
+ @media (prefers-color-scheme: dark) {
80
+ & .crisp-themepicker-preview[data-swatch="system"] { border: 1px solid #1c1d1f; background: #0e0f10; }
81
+ & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; }
82
+ & [data-swatch="system"] .crisp-themepicker-preview-main { background: #0a0a0a; }
83
+ & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #1c1d1f; }
84
+ }
85
+
86
+ & .crisp-themepicker-label { display: flex; align-items: center; gap: ${c.space["1"]}; font-size: ${c.text.lg}; font-weight: ${c.weight.medium}; color: ${c.fgMuted}; }
87
+ & .crisp-themepicker-option[data-selected] .crisp-themepicker-label { color: ${c.fgPrimary}; }
88
+ & .crisp-themepicker-radio { flex-shrink: 0; width: 14px; height: 14px; border-radius: ${c.radius.full}; border: 1px solid ${c.borderDefault}; box-sizing: border-box; }
89
+ & .crisp-themepicker-option[data-selected] .crisp-themepicker-radio { border: 4px solid ${c.bgBrandSolid}; }`,
90
+ variants: {},
91
+ defaultVariants: {},
92
+ compoundVariants: [],
93
+ });
94
+ export const themepickerRecipe = resolveRecipe(config);
95
+ export default config;
@@ -9,6 +9,14 @@ export const palette = {
9
9
  gray900: { light: "#101112", dark: "#f5f5f5" },
10
10
  line200: { light: "#e4e4e7", dark: "#212224" },
11
11
  line100: { light: "#eeeff1", dark: "#1c1d1f" },
12
+ // ImportDialog's dropzone border — measured live from Attio's Import CSV
13
+ // flow (`rgb(230,231,234)`), distinct from `line200`/`line100` (#e4e4e7 /
14
+ // #eeeff1 are close but not equal, and AUTHORING's dimensional-scale rule
15
+ // against rounding a measurement to fit an existing token applies to color
16
+ // too). Dark value not independently re-measured (Attio's dark theme is
17
+ // off-limits to toggle, same restriction as `ringField`/`ringSwitch`) —
18
+ // reuses `line200`'s dark line colour rather than inventing a new one.
19
+ line150: { light: "#e6e7ea", dark: "#212224" },
12
20
  ringNeutral: { light: "transparent", dark: "#212224" },
13
21
  // Text-entry fields (Input, Textarea) — measured live on app.attio.com's
14
22
  // Settings page, a real typed field: `inset 0 0 0 1px rgba(0,0,0,.06)`,
@@ -49,6 +57,15 @@ export const palette = {
49
57
  // #EB3B3B it uses for destructive menu TEXT. Does not flip: a filled
50
58
  // destructive control needs the same white-bearing fill in both themes.
51
59
  red700: { light: "#ba2525", dark: "#ba2525" },
60
+ // The #EB3B3B named in red700's own comment above (destructive menu text) —
61
+ // it had never actually been given a token. Independently re-measured live
62
+ // on `app.attio.com/.../tasks`, `rgb(235,59,59)`, as the overdue due-date
63
+ // text colour on the Tasks page (crisp#462) — same hex, second surface.
64
+ // Dark not independently re-measured (Attio's theme toggle is off-limits,
65
+ // same restriction noted throughout this file); reuses red600's dark value,
66
+ // the same "brightens for legibility on a dark surface" tone this red
67
+ // already sits next to, rather than inventing a third red.
68
+ red500: { light: "#eb3b3b", dark: "#ff5a5f" },
52
69
  // seed-design's field focus ring (stroke-neutral-contrast = gray-1000),
53
70
  // measured from @seed-design/css. A high-contrast neutral rather than a brand
54
71
  // hue: the ring reads as "this field has focus", not as a state colour.
@@ -98,17 +115,17 @@ export const palette = {
98
115
  // Badge's soft-neutral text, so darkening it doesn't move any other surface.
99
116
  softNeutralText: { light: "#686870", dark: "#9a9aa2" },
100
117
  // Badge's purple/role-pill tone (crisp#506) -- measured live off Attio's
101
- // own role pill ("Admin", app.attio.com/<ws>/settings/workspace/members):
102
- // background rgb(245,240,255), text rgb(98,56,181). The ring re-uses a
103
- // second, independent measurement from the same session (a company's
104
- // Categories tag pill sharing the identical background, "Broadcasting",
105
- // app.attio.com/<ws>/companies) at rgb(232,221,254) -- same hue family,
106
- // cross-validated rather than guessed. Dark mode was NOT measured (no
107
- // live Attio session was reachable when this tone was added) -- these
108
- // three light values are reused as-is for dark rather than an invented
109
- // "brightened" guess (Lesson: don't add unmeasured "robustness"). Needs a
110
- // real dark-mode measurement before this note can be removed.
111
- purpleTint: { light: "#f5f0ff", dark: "#f5f0ff" },
112
- softPurpleText: { light: "#6238b5", dark: "#6238b5" },
113
- purpleRing: { light: "#e8ddfe", dark: "#e8ddfe" },
118
+ // own role pill ("Admin", app.attio.com/<ws>/settings/members-and-teams):
119
+ // background rgb(245,240,255), text rgb(98,56,181), ring rgb(232,221,254)
120
+ // (cross-validated against a second, independent pill sharing the
121
+ // identical background, a company's "Broadcasting" Categories tag).
122
+ // Dark mode (crisp#566) measured the same way, after switching Attio's
123
+ // own Appearance setting to Dark, reading the pill, then switching back
124
+ // to Light to restore the original state: background rgb(47,30,90),
125
+ // text rgb(216,196,255), ring rgb(69,41,125) -- verify-the-right-element
126
+ // note: the pill's own wrapper span inherits an unstyled rgb(241,242,243)
127
+ // text colour; the real styled colour sits on its nested leaf text node.
128
+ purpleTint: { light: "#f5f0ff", dark: "#2f1e5a" },
129
+ softPurpleText: { light: "#6238b5", dark: "#d8c4ff" },
130
+ purpleRing: { light: "#e8ddfe", dark: "#45297d" },
114
131
  };
@@ -10,6 +10,8 @@ export const semantic = {
10
10
  bgRaised: "gray50",
11
11
  borderDefault: "line200",
12
12
  borderSubtle: "line100",
13
+ /** ImportDialog's dashed dropzone border — see palette.ts's `line150`. */
14
+ borderDropzone: "line150",
13
15
  ringNeutral: "ringNeutral",
14
16
  ringField: "ringField",
15
17
  ringSwitch: "ringSwitch",
@@ -29,6 +31,10 @@ export const semantic = {
29
31
  bgDanger: "red600",
30
32
  /** Fill for a SOLID destructive control that carries white text. */
31
33
  bgDangerSolid: "red700",
34
+ /** Solid critical/destructive TEXT (not a fill) — an overdue due-date, a
35
+ * destructive menu item's label. Distinct from `bgDanger` (a fill colour)
36
+ * and `fgDangerSoft` (a soft badge pill's text, a different measured hex). */
37
+ fgDanger: "red500",
32
38
  /** The 2px ring a text field shows while focused. */
33
39
  strokeFieldFocus: "fieldFocus",
34
40
  /** Unavailable/disabled content: unselected wheel rows, unpickable dates. */
@@ -0,0 +1,6 @@
1
+ .crisp-formdialog {
2
+ & .crisp-formdialog-createfoot { display: flex; align-items: center; gap: var(--crisp-space-4); }
3
+ & .crisp-formdialog-more-label { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); cursor: pointer; }
4
+ & .crisp-formdialog-error { font-size: var(--crisp-text-md); color: var(--crisp-fg-danger); margin: 0; }
5
+ & .crisp-formdialog-form { display: grid; gap: var(--crisp-space-3); }
6
+ }
@@ -0,0 +1,7 @@
1
+ import type { RecipeFn } from "../core/types";
2
+
3
+ export interface FormdialogVariants {
4
+
5
+ }
6
+
7
+ export declare const formdialogRecipe: RecipeFn<{ }>;
@@ -0,0 +1,8 @@
1
+ @layer crisp-components {
2
+ .crisp-formdialog {
3
+ & .crisp-formdialog-createfoot { display: flex; align-items: center; gap: var(--crisp-space-4); }
4
+ & .crisp-formdialog-more-label { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); cursor: pointer; }
5
+ & .crisp-formdialog-error { font-size: var(--crisp-text-md); color: var(--crisp-fg-danger); margin: 0; }
6
+ & .crisp-formdialog-form { display: grid; gap: var(--crisp-space-3); }
7
+ }
8
+ }
@@ -0,0 +1,38 @@
1
+ .crisp-importdialog {
2
+ display: contents; font-family: var(--crisp-font-sans);
3
+ & .crisp-importdialog-backdrop { position: fixed; inset: 0; z-index: 60; background: transparent; }
4
+ & .crisp-importdialog-positioner { position: fixed; inset: 0; z-index: 61; display: flex; }
5
+ & .crisp-importdialog-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 100%; height: 100%; border-radius: 0; background: var(--crisp-bg-surface); box-shadow: none; transform: none; opacity: 1; transition: opacity 0.2s ease; @starting-style { opacity: 0; } }
6
+ & .crisp-importdialog-header { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; height: 52px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-6); border-bottom: 1px solid var(--crisp-border-subtle); }
7
+ & .crisp-importdialog-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); margin: 0; }
8
+ & .crisp-importdialog-close { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; }
9
+ & .crisp-importdialog-close:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
10
+ & .crisp-importdialog-steps { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; padding: var(--crisp-space-4) var(--crisp-space-6) 0; }
11
+ & .crisp-importdialog-step { display: inline-flex; align-items: center; height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: default; transition: background-color .12s, color .12s; }
12
+ & button.crisp-importdialog-step { cursor: pointer; }
13
+ & .crisp-importdialog-step[data-active] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
14
+ & .crisp-importdialog-step:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: 1px; }
15
+ & .crisp-importdialog-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; padding: var(--crisp-space-6); }
16
+ & .crisp-importdialog-footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--crisp-space-3); flex-shrink: 0; min-height: 56px; padding: 0 var(--crisp-space-6); border-top: 1px solid var(--crisp-border-subtle); }
17
+ & .crisp-importdialog-dropzone { box-sizing: border-box; position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--crisp-space-1); width: 100%; border: 1px dashed var(--crisp-border-dropzone); border-radius: 20px; background: var(--crisp-bg-subtle); text-align: center; transition: background-color .12s, border-color .12s; }
18
+ & .crisp-importdialog-dropzone[data-dragging-over] { border-color: var(--crisp-bg-brand-solid); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 6%, transparent); }
19
+ & .crisp-importdialog-dropzone[data-invalid] { border-color: var(--crisp-bg-danger); }
20
+ & .crisp-importdialog-dropzone-title { color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
21
+ & .crisp-importdialog-dropzone-or { color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); line-height: 18px; }
22
+ & .crisp-importdialog-dropzone-choose { border: none; background: none; padding: 0; margin: 0; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-bg-brand-solid); cursor: pointer; }
23
+ & .crisp-importdialog-dropzone-choose:hover { color: var(--crisp-bg-brand-solid-pressed); }
24
+ & .crisp-importdialog-dropzone-choose:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: 2px; border-radius: var(--crisp-radius-sm); }
25
+ & .crisp-importdialog-dropzone-learnmore { color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-decoration: underline; }
26
+ & .crisp-importdialog-dropzone-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
27
+ & .crisp-importdialog-dropzone-errors { margin: 0; padding: 0; list-style: none; }
28
+ & .crisp-importdialog-dropzone-errors:empty { position: absolute; }
29
+ & .crisp-importdialog-dropzone-error { color: var(--crisp-bg-danger); font-size: var(--crisp-text-md); line-height: 18px; }
30
+ }
31
+
32
+ @media (prefers-reduced-motion: reduce) {
33
+ .crisp-importdialog, .crisp-importdialog * {
34
+ animation-duration: 0.01ms !important;
35
+ animation-iteration-count: 1 !important;
36
+ transition-duration: 0.01ms !important;
37
+ }
38
+ }
@@ -0,0 +1,7 @@
1
+ import type { RecipeFn } from "../core/types";
2
+
3
+ export interface ImportdialogVariants {
4
+
5
+ }
6
+
7
+ export declare const importdialogRecipe: RecipeFn<{ }>;
@@ -0,0 +1,40 @@
1
+ @layer crisp-components {
2
+ .crisp-importdialog {
3
+ display: contents; font-family: var(--crisp-font-sans);
4
+ & .crisp-importdialog-backdrop { position: fixed; inset: 0; z-index: 60; background: transparent; }
5
+ & .crisp-importdialog-positioner { position: fixed; inset: 0; z-index: 61; display: flex; }
6
+ & .crisp-importdialog-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 100%; height: 100%; border-radius: 0; background: var(--crisp-bg-surface); box-shadow: none; transform: none; opacity: 1; transition: opacity 0.2s ease; @starting-style { opacity: 0; } }
7
+ & .crisp-importdialog-header { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; height: 52px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-6); border-bottom: 1px solid var(--crisp-border-subtle); }
8
+ & .crisp-importdialog-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); margin: 0; }
9
+ & .crisp-importdialog-close { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; }
10
+ & .crisp-importdialog-close:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
11
+ & .crisp-importdialog-steps { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; padding: var(--crisp-space-4) var(--crisp-space-6) 0; }
12
+ & .crisp-importdialog-step { display: inline-flex; align-items: center; height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: default; transition: background-color .12s, color .12s; }
13
+ & button.crisp-importdialog-step { cursor: pointer; }
14
+ & .crisp-importdialog-step[data-active] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
15
+ & .crisp-importdialog-step:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: 1px; }
16
+ & .crisp-importdialog-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; padding: var(--crisp-space-6); }
17
+ & .crisp-importdialog-footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--crisp-space-3); flex-shrink: 0; min-height: 56px; padding: 0 var(--crisp-space-6); border-top: 1px solid var(--crisp-border-subtle); }
18
+ & .crisp-importdialog-dropzone { box-sizing: border-box; position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--crisp-space-1); width: 100%; border: 1px dashed var(--crisp-border-dropzone); border-radius: 20px; background: var(--crisp-bg-subtle); text-align: center; transition: background-color .12s, border-color .12s; }
19
+ & .crisp-importdialog-dropzone[data-dragging-over] { border-color: var(--crisp-bg-brand-solid); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 6%, transparent); }
20
+ & .crisp-importdialog-dropzone[data-invalid] { border-color: var(--crisp-bg-danger); }
21
+ & .crisp-importdialog-dropzone-title { color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
22
+ & .crisp-importdialog-dropzone-or { color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); line-height: 18px; }
23
+ & .crisp-importdialog-dropzone-choose { border: none; background: none; padding: 0; margin: 0; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-bg-brand-solid); cursor: pointer; }
24
+ & .crisp-importdialog-dropzone-choose:hover { color: var(--crisp-bg-brand-solid-pressed); }
25
+ & .crisp-importdialog-dropzone-choose:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: 2px; border-radius: var(--crisp-radius-sm); }
26
+ & .crisp-importdialog-dropzone-learnmore { color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-decoration: underline; }
27
+ & .crisp-importdialog-dropzone-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
28
+ & .crisp-importdialog-dropzone-errors { margin: 0; padding: 0; list-style: none; }
29
+ & .crisp-importdialog-dropzone-errors:empty { position: absolute; }
30
+ & .crisp-importdialog-dropzone-error { color: var(--crisp-bg-danger); font-size: var(--crisp-text-md); line-height: 18px; }
31
+ }
32
+
33
+ @media (prefers-reduced-motion: reduce) {
34
+ .crisp-importdialog, .crisp-importdialog * {
35
+ animation-duration: 0.01ms !important;
36
+ animation-iteration-count: 1 !important;
37
+ transition-duration: 0.01ms !important;
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,3 @@
1
+ .crisp-mention-chip {
2
+ display: inline; border-radius: var(--crisp-radius-chip); padding-inline: var(--crisp-space-1); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); font-weight: var(--crisp-weight-medium); cursor: default;
3
+ }
@@ -0,0 +1,7 @@
1
+ import type { RecipeFn } from "../core/types";
2
+
3
+ export interface Mention-chipVariants {
4
+
5
+ }
6
+
7
+ export declare const mention-chipRecipe: RecipeFn<{ }>;
@@ -0,0 +1,5 @@
1
+ @layer crisp-components {
2
+ .crisp-mention-chip {
3
+ display: inline; border-radius: var(--crisp-radius-chip); padding-inline: var(--crisp-space-1); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); font-weight: var(--crisp-weight-medium); cursor: default;
4
+ }
5
+ }
@@ -2,7 +2,7 @@
2
2
  // The same tokens the CSS custom properties carry, resolved per theme, with
3
3
  // dimensions as numbers for React Native and Lynx style objects.
4
4
  export type Theme = "light" | "dark";
5
- export type ColorTokens = Record<"bgBrandSolid" | "bgBrandSolidPressed" | "fgOnBrand" | "fgOnTone" | "bgSurface" | "bgRaised" | "borderDefault" | "borderSubtle" | "ringNeutral" | "ringField" | "ringSwitch" | "bgTileActive" | "shadowTileActive" | "bgOverlayFrost" | "shadowOverlay1" | "shadowOverlay2" | "shadowOverlay3" | "bgPopover" | "ringPopover" | "shadowPopover1" | "shadowPopover2" | "shadowPopover3" | "fgPrimary" | "fgMuted" | "bgDanger" | "bgDangerSolid" | "strokeFieldFocus" | "fgDisabled" | "bgNeutralWeak" | "bgNeutralInverted" | "fgOnNeutralInverted" | "fgNeutralSubtle" | "fgNeutralMuted" | "strokeFocusRing" | "bgSuccess" | "bgWarning" | "bgOrange" | "bgCyan" | "bgPurple" | "bgSidebar" | "bgSubtle" | "fgBrandSoft" | "fgSuccessSoft" | "fgWarningSoft" | "fgDangerSoft" | "fgNeutralSoft" | "bgPurpleSoft" | "fgPurpleSoft" | "ringPurpleSoft", string>;
5
+ export type ColorTokens = Record<"bgBrandSolid" | "bgBrandSolidPressed" | "fgOnBrand" | "fgOnTone" | "bgSurface" | "bgRaised" | "borderDefault" | "borderSubtle" | "borderDropzone" | "ringNeutral" | "ringField" | "ringSwitch" | "bgTileActive" | "shadowTileActive" | "bgOverlayFrost" | "shadowOverlay1" | "shadowOverlay2" | "shadowOverlay3" | "bgPopover" | "ringPopover" | "shadowPopover1" | "shadowPopover2" | "shadowPopover3" | "fgPrimary" | "fgMuted" | "bgDanger" | "bgDangerSolid" | "fgDanger" | "strokeFieldFocus" | "fgDisabled" | "bgNeutralWeak" | "bgNeutralInverted" | "fgOnNeutralInverted" | "fgNeutralSubtle" | "fgNeutralMuted" | "strokeFocusRing" | "bgSuccess" | "bgWarning" | "bgOrange" | "bgCyan" | "bgPurple" | "bgSidebar" | "bgSubtle" | "fgBrandSoft" | "fgSuccessSoft" | "fgWarningSoft" | "fgDangerSoft" | "fgNeutralSoft" | "bgPurpleSoft" | "fgPurpleSoft" | "ringPurpleSoft", string>;
6
6
  export declare const tokens: {
7
7
  color: Record<Theme, ColorTokens>;
8
8
  palette: Record<Theme, Record<string, string>>;
@@ -12,6 +12,7 @@ export const tokens = {
12
12
  "bgRaised": "#f4f4f5",
13
13
  "borderDefault": "#e4e4e7",
14
14
  "borderSubtle": "#eeeff1",
15
+ "borderDropzone": "#e6e7ea",
15
16
  "ringNeutral": "transparent",
16
17
  "ringField": "rgba(0,0,0,0.06)",
17
18
  "ringSwitch": "#d9dade",
@@ -30,6 +31,7 @@ export const tokens = {
30
31
  "fgMuted": "#71717a",
31
32
  "bgDanger": "#e5484d",
32
33
  "bgDangerSolid": "#ba2525",
34
+ "fgDanger": "#eb3b3b",
33
35
  "strokeFieldFocus": "#1a1c20",
34
36
  "fgDisabled": "#d1d3d8",
35
37
  "bgNeutralWeak": "#f3f4f5",
@@ -63,6 +65,7 @@ export const tokens = {
63
65
  "bgRaised": "#101112",
64
66
  "borderDefault": "#212224",
65
67
  "borderSubtle": "#1c1d1f",
68
+ "borderDropzone": "#212224",
66
69
  "ringNeutral": "#212224",
67
70
  "ringField": "#212224",
68
71
  "ringSwitch": "#212224",
@@ -81,6 +84,7 @@ export const tokens = {
81
84
  "fgMuted": "#9a9aa2",
82
85
  "bgDanger": "#ff5a5f",
83
86
  "bgDangerSolid": "#ba2525",
87
+ "fgDanger": "#ff5a5f",
84
88
  "strokeFieldFocus": "#f3f4f5",
85
89
  "fgDisabled": "#5b606a",
86
90
  "bgNeutralWeak": "#1d2025",
@@ -101,9 +105,9 @@ export const tokens = {
101
105
  "fgWarningSoft": "#e0982a",
102
106
  "fgDangerSoft": "#ff5a5f",
103
107
  "fgNeutralSoft": "#9a9aa2",
104
- "bgPurpleSoft": "#f5f0ff",
105
- "fgPurpleSoft": "#6238b5",
106
- "ringPurpleSoft": "#e8ddfe"
108
+ "bgPurpleSoft": "#2f1e5a",
109
+ "fgPurpleSoft": "#d8c4ff",
110
+ "ringPurpleSoft": "#45297d"
107
111
  }
108
112
  },
109
113
  "palette": {
@@ -115,6 +119,7 @@ export const tokens = {
115
119
  "gray900": "#101112",
116
120
  "line200": "#e4e4e7",
117
121
  "line100": "#eeeff1",
122
+ "line150": "#e6e7ea",
118
123
  "ringNeutral": "transparent",
119
124
  "ringField": "rgba(0,0,0,0.06)",
120
125
  "ringSwitch": "#d9dade",
@@ -134,6 +139,7 @@ export const tokens = {
134
139
  "brand700": "#1f5fd6",
135
140
  "red600": "#e5484d",
136
141
  "red700": "#ba2525",
142
+ "red500": "#eb3b3b",
137
143
  "fieldFocus": "#1a1c20",
138
144
  "disabledFg": "#d1d3d8",
139
145
  "neutralWeak": "#f3f4f5",
@@ -165,6 +171,7 @@ export const tokens = {
165
171
  "gray900": "#f5f5f5",
166
172
  "line200": "#212224",
167
173
  "line100": "#1c1d1f",
174
+ "line150": "#212224",
168
175
  "ringNeutral": "#212224",
169
176
  "ringField": "#212224",
170
177
  "ringSwitch": "#212224",
@@ -184,6 +191,7 @@ export const tokens = {
184
191
  "brand700": "#1f5fd6",
185
192
  "red600": "#ff5a5f",
186
193
  "red700": "#ba2525",
194
+ "red500": "#ff5a5f",
187
195
  "fieldFocus": "#f3f4f5",
188
196
  "disabledFg": "#5b606a",
189
197
  "neutralWeak": "#1d2025",
@@ -203,9 +211,9 @@ export const tokens = {
203
211
  "softWarningText": "#e0982a",
204
212
  "softDangerText": "#ff5a5f",
205
213
  "softNeutralText": "#9a9aa2",
206
- "purpleTint": "#f5f0ff",
207
- "softPurpleText": "#6238b5",
208
- "purpleRing": "#e8ddfe"
214
+ "purpleTint": "#2f1e5a",
215
+ "softPurpleText": "#d8c4ff",
216
+ "purpleRing": "#45297d"
209
217
  }
210
218
  },
211
219
  "space": {