@crisp-ui-kit/crisp 0.56.0 → 0.57.0

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 (90) hide show
  1. package/dist/callout.css +6 -0
  2. package/dist/callout.d.ts +2 -2
  3. package/dist/callout.layered.css +6 -0
  4. package/dist/cjs/components/callout/callout.js +2 -2
  5. package/dist/cjs/components/callout/callout.recipe.js +15 -2
  6. package/dist/cjs/components/input/input.recipe.js +6 -0
  7. package/dist/cjs/components/menu/menu.js +2 -2
  8. package/dist/cjs/components/menu/menu.recipe.js +8 -0
  9. package/dist/cjs/components/multiselect/multiselect.js +23 -10
  10. package/dist/cjs/components/multiselect/multiselect.recipe.js +95 -65
  11. package/dist/cjs/components/select/listbox-keyboard.js +7 -1
  12. package/dist/cjs/components/select/select.js +24 -11
  13. package/dist/cjs/components/select/select.recipe.js +150 -78
  14. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +3 -3
  15. package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +26 -1
  16. package/dist/cjs/components/tabs/tabs.js +63 -4
  17. package/dist/cjs/components/tabs/tabs.recipe.js +13 -0
  18. package/dist/cjs/components/textlink/textlink.js +2 -2
  19. package/dist/cjs/components/textlink/textlink.recipe.js +18 -0
  20. package/dist/cjs/product/recordpage/recordpage.js +17 -4
  21. package/dist/cjs/tokens/elevation.js +7 -0
  22. package/dist/cjs/tokens/palette.js +41 -0
  23. package/dist/cjs/tokens/scale.js +8 -0
  24. package/dist/cjs/tokens/semantic.js +18 -0
  25. package/dist/esm/components/callout/callout.js +2 -2
  26. package/dist/esm/components/callout/callout.recipe.js +15 -2
  27. package/dist/esm/components/input/input.recipe.js +6 -0
  28. package/dist/esm/components/menu/menu.js +2 -2
  29. package/dist/esm/components/menu/menu.recipe.js +8 -0
  30. package/dist/esm/components/multiselect/multiselect.js +23 -10
  31. package/dist/esm/components/multiselect/multiselect.recipe.js +95 -65
  32. package/dist/esm/components/select/listbox-keyboard.js +7 -1
  33. package/dist/esm/components/select/select.js +24 -11
  34. package/dist/esm/components/select/select.recipe.js +150 -78
  35. package/dist/esm/components/tabletoolbar/tabletoolbar.js +3 -3
  36. package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +26 -1
  37. package/dist/esm/components/tabs/tabs.js +63 -4
  38. package/dist/esm/components/tabs/tabs.recipe.js +13 -0
  39. package/dist/esm/components/textlink/textlink.js +2 -2
  40. package/dist/esm/components/textlink/textlink.recipe.js +18 -0
  41. package/dist/esm/product/recordpage/recordpage.js +18 -5
  42. package/dist/esm/tokens/elevation.js +7 -0
  43. package/dist/esm/tokens/palette.js +41 -0
  44. package/dist/esm/tokens/scale.js +8 -0
  45. package/dist/esm/tokens/semantic.js +18 -0
  46. package/dist/input.css +4 -0
  47. package/dist/input.d.ts +2 -2
  48. package/dist/input.layered.css +4 -0
  49. package/dist/menu.css +8 -0
  50. package/dist/menu.layered.css +8 -0
  51. package/dist/multiselect.css +53 -29
  52. package/dist/multiselect.d.ts +3 -1
  53. package/dist/multiselect.layered.css +53 -29
  54. package/dist/native/tokens.d.ts +1 -1
  55. package/dist/native/tokens.js +49 -6
  56. package/dist/select.css +80 -42
  57. package/dist/select.d.ts +3 -2
  58. package/dist/select.layered.css +80 -42
  59. package/dist/styles.css +199 -72
  60. package/dist/styles.layered.css +199 -72
  61. package/dist/tabletoolbar.css +8 -1
  62. package/dist/tabletoolbar.layered.css +8 -1
  63. package/dist/tabs.css +6 -0
  64. package/dist/tabs.layered.css +6 -0
  65. package/dist/textlink.css +9 -0
  66. package/dist/textlink.d.ts +2 -1
  67. package/dist/textlink.layered.css +9 -0
  68. package/dist/tokens.css +25 -0
  69. package/dist/tokens.json +49 -6
  70. package/dist/types/components/callout/callout.d.ts +9 -1
  71. package/dist/types/components/callout/callout.recipe.d.ts +12 -2
  72. package/dist/types/components/input/input.d.ts +2 -0
  73. package/dist/types/components/input/input.recipe.d.ts +3 -0
  74. package/dist/types/components/menu/menu.d.ts +7 -1
  75. package/dist/types/components/multiselect/multiselect.d.ts +24 -6
  76. package/dist/types/components/multiselect/multiselect.recipe.d.ts +24 -0
  77. package/dist/types/components/select/listbox-keyboard.d.ts +10 -1
  78. package/dist/types/components/select/select.d.ts +28 -6
  79. package/dist/types/components/select/select.recipe.d.ts +22 -10
  80. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +14 -0
  81. package/dist/types/components/tabs/tabs.d.ts +9 -1
  82. package/dist/types/components/textlink/textlink.d.ts +8 -1
  83. package/dist/types/components/textlink/textlink.recipe.d.ts +10 -0
  84. package/dist/types/product/recordpage/recordpage.d.ts +25 -1
  85. package/dist/types/tokens/contract.d.ts +13 -3
  86. package/dist/types/tokens/elevation.d.ts +7 -0
  87. package/dist/types/tokens/palette.d.ts +36 -0
  88. package/dist/types/tokens/scale.d.ts +5 -0
  89. package/dist/types/tokens/semantic.d.ts +18 -0
  90. package/package.json +1 -1
package/dist/tokens.json CHANGED
@@ -55,7 +55,17 @@
55
55
  "fgNeutralSoft": "#505155",
56
56
  "bgPurpleSoft": "#f5f0ff",
57
57
  "fgPurpleSoft": "#6238b5",
58
- "ringPurpleSoft": "#e8ddfe"
58
+ "ringPurpleSoft": "#e8ddfe",
59
+ "ringBrandSoft": "#d6e5ff",
60
+ "fgSelectNeutral": "#1a1c20",
61
+ "bgSelectListbox": "#ffffff",
62
+ "strokeSelectTrigger": "#dcdee3",
63
+ "bgSelectPressed": "#00000007",
64
+ "bgSelectDisabled": "#f3f4f5",
65
+ "strokeSelectInvalid": "#fa342c",
66
+ "strokeSelectDivider": "#00000010",
67
+ "fgSelectPlaceholder": "#b0b3ba",
68
+ "shadowSelect": "#0000001f"
59
69
  },
60
70
  "dark": {
61
71
  "bgBrandSolid": "#266df0",
@@ -112,7 +122,17 @@
112
122
  "fgNeutralSoft": "#9a9aa2",
113
123
  "bgPurpleSoft": "#2f1e5a",
114
124
  "fgPurpleSoft": "#d8c4ff",
115
- "ringPurpleSoft": "#45297d"
125
+ "ringPurpleSoft": "#45297d",
126
+ "ringBrandSoft": "#212224",
127
+ "fgSelectNeutral": "#f3f4f5",
128
+ "bgSelectListbox": "#1d2025",
129
+ "strokeSelectTrigger": "#393d46",
130
+ "bgSelectPressed": "#ffffff0d",
131
+ "bgSelectDisabled": "#2b2e35",
132
+ "strokeSelectInvalid": "#ff6e60",
133
+ "strokeSelectDivider": "#ffffff17",
134
+ "fgSelectPlaceholder": "#868b94",
135
+ "shadowSelect": "#000000cc"
116
136
  }
117
137
  },
118
138
  "palette": {
@@ -129,6 +149,7 @@
129
149
  "ringNeutral": "transparent",
130
150
  "ringField": "rgba(0,0,0,0.06)",
131
151
  "ringSwitch": "#d9dade",
152
+ "ringBrandSoft": "#d6e5ff",
132
153
  "tileActive": "#ffffff",
133
154
  "tileActiveShadow": "rgba(0,0,0,0.04)",
134
155
  "bgScrim": "rgba(0,0,0,0.25)",
@@ -169,7 +190,15 @@
169
190
  "softNeutralText": "#505155",
170
191
  "purpleTint": "#f5f0ff",
171
192
  "softPurpleText": "#6238b5",
172
- "purpleRing": "#e8ddfe"
193
+ "purpleRing": "#e8ddfe",
194
+ "selectListboxBg": "#ffffff",
195
+ "selectTriggerStroke": "#dcdee3",
196
+ "selectPressedTint": "#00000007",
197
+ "selectDisabledBg": "#f3f4f5",
198
+ "selectInvalidStroke": "#fa342c",
199
+ "selectDivider": "#00000010",
200
+ "selectPlaceholder": "#b0b3ba",
201
+ "selectShadow": "#0000001f"
173
202
  },
174
203
  "dark": {
175
204
  "gray00": "#0a0a0a",
@@ -184,6 +213,7 @@
184
213
  "ringNeutral": "#212224",
185
214
  "ringField": "#212224",
186
215
  "ringSwitch": "#212224",
216
+ "ringBrandSoft": "#212224",
187
217
  "tileActive": "#101112",
188
218
  "tileActiveShadow": "rgba(0,0,0,0)",
189
219
  "bgScrim": "rgba(0,0,0,0.55)",
@@ -224,7 +254,15 @@
224
254
  "softNeutralText": "#9a9aa2",
225
255
  "purpleTint": "#2f1e5a",
226
256
  "softPurpleText": "#d8c4ff",
227
- "purpleRing": "#45297d"
257
+ "purpleRing": "#45297d",
258
+ "selectListboxBg": "#1d2025",
259
+ "selectTriggerStroke": "#393d46",
260
+ "selectPressedTint": "#ffffff0d",
261
+ "selectDisabledBg": "#2b2e35",
262
+ "selectInvalidStroke": "#ff6e60",
263
+ "selectDivider": "#ffffff17",
264
+ "selectPlaceholder": "#868b94",
265
+ "selectShadow": "#000000cc"
228
266
  }
229
267
  },
230
268
  "space": {
@@ -238,7 +276,8 @@
238
276
  "px": 1,
239
277
  "0.5": 2,
240
278
  "1.5": 6,
241
- "2.5": 10
279
+ "2.5": 10,
280
+ "3.5": 14
242
281
  },
243
282
  "radius": {
244
283
  "chip": 7,
@@ -247,6 +286,7 @@
247
286
  "lg": 9,
248
287
  "xl": 12,
249
288
  "2xl": 16,
289
+ "3xl": 20,
250
290
  "full": 999
251
291
  },
252
292
  "size": {
@@ -258,7 +298,10 @@
258
298
  "tableHeader": 40,
259
299
  "header": 48,
260
300
  "calendarCell": 34,
261
- "calendarPill": 32
301
+ "calendarPill": 32,
302
+ "selectTriggerMd": 40,
303
+ "selectTriggerLg": 52,
304
+ "selectIconLg": 20
262
305
  },
263
306
  "text": {
264
307
  "xs": 11,
@@ -8,13 +8,21 @@ export type CalloutProps = Omit<React.ComponentPropsWithoutRef<"div">, "title">
8
8
  children?: React.ReactNode;
9
9
  /** Trailing action (e.g. a Button). */
10
10
  action?: React.ReactNode;
11
+ /**
12
+ * A page-level banner look (crisp#869): a 1px border, 12px radius, tighter
13
+ * 8px/12px padding, and a brand-tinted background — measured live on
14
+ * Attio's own Objects settings page (a real full-width Pro-plan nudge).
15
+ * There's no measured close/dismiss button on that banner, so this adds
16
+ * none.
17
+ */
18
+ bordered?: boolean;
11
19
  className?: string;
12
20
  };
13
21
  /**
14
22
  * An inline callout / banner — measured from info notices. `tone` tints
15
23
  * the background and icon; pass a `title` and/or body `children`.
16
24
  */
17
- export declare function Callout({ tone, icon, title, children, action, className, ...rest }: CalloutProps): React.JSX.Element;
25
+ export declare function Callout({ tone, icon, title, children, action, bordered, className, ...rest }: CalloutProps): React.JSX.Element;
18
26
  export declare namespace Callout {
19
27
  var displayName: string;
20
28
  }
@@ -1,3 +1,13 @@
1
- declare const config: import("../..").RecipeConfig<{}>;
2
- export declare const calloutRecipe: import("../..").RecipeFn<{}>;
1
+ declare const config: import("../..").RecipeConfig<{
2
+ bordered: {
3
+ true: string;
4
+ false: string;
5
+ };
6
+ }>;
7
+ export declare const calloutRecipe: import("../..").RecipeFn<{
8
+ bordered: {
9
+ true: string;
10
+ false: string;
11
+ };
12
+ }>;
3
13
  export default config;
@@ -7,6 +7,7 @@ export type InputProps = Omit<React.ComponentPropsWithoutRef<"input">, "size"> &
7
7
  };
8
8
  export declare const Input: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "size"> & VariantProps<import("../..").RecipeFn<{
9
9
  size: {
10
+ sm: string;
10
11
  medium: string;
11
12
  large: string;
12
13
  };
@@ -17,6 +18,7 @@ export declare const Input: React.ForwardRefExoticComponent<Omit<Omit<React.Deta
17
18
  }> & {
18
19
  config: import("../..").RecipeConfig<{
19
20
  size: {
21
+ sm: string;
20
22
  medium: string;
21
23
  large: string;
22
24
  };
@@ -1,5 +1,6 @@
1
1
  declare const config: import("../..").RecipeConfig<{
2
2
  size: {
3
+ sm: string;
3
4
  medium: string;
4
5
  large: string;
5
6
  };
@@ -10,6 +11,7 @@ declare const config: import("../..").RecipeConfig<{
10
11
  }>;
11
12
  export declare const inputRecipe: import("../..").RecipeFn<{
12
13
  size: {
14
+ sm: string;
13
15
  medium: string;
14
16
  large: string;
15
17
  };
@@ -20,6 +22,7 @@ export declare const inputRecipe: import("../..").RecipeFn<{
20
22
  }> & {
21
23
  config: import("../..").RecipeConfig<{
22
24
  size: {
25
+ sm: string;
23
26
  medium: string;
24
27
  large: string;
25
28
  };
@@ -39,13 +39,19 @@ export type MenuItemProps = {
39
39
  children: React.ReactNode;
40
40
  icon?: React.ReactNode;
41
41
  shortcut?: string;
42
+ /**
43
+ * A trailing count badge (crisp#875) — e.g. a saved-filter item showing
44
+ * how many rows match. Same measured neutral chip `ToolbarTool`'s own
45
+ * `count` prop uses, not bare text.
46
+ */
47
+ count?: React.ReactNode;
42
48
  danger?: boolean;
43
49
  disabled?: boolean;
44
50
  onSelect?: () => void;
45
51
  /** Keep the menu open after selecting (default closes). */
46
52
  closeOnSelect?: boolean;
47
53
  };
48
- export declare function MenuItem({ children, icon, shortcut, danger, disabled, onSelect, closeOnSelect, }: MenuItemProps): React.JSX.Element;
54
+ export declare function MenuItem({ children, icon, shortcut, count, danger, disabled, onSelect, closeOnSelect, }: MenuItemProps): React.JSX.Element;
49
55
  export declare namespace MenuItem {
50
56
  var displayName: string;
51
57
  }
@@ -45,18 +45,36 @@ export type MultiSelectProps = Omit<React.ComponentPropsWithoutRef<"div">, "valu
45
45
  /** Shown when the search matches nothing. */
46
46
  emptyLabel?: string;
47
47
  disabled?: boolean;
48
- /** Red ring + `aria-invalid`, matching `Input`'s and `Select`'s. */
48
+ /**
49
+ * Answered and locked, not editable — unlike `disabled`, the trigger stays
50
+ * focusable (crisp/#882, matching `Select`'s `readOnly`).
51
+ */
52
+ readOnly?: boolean;
53
+ /** 2px red border + `aria-invalid`, matching `Input`'s and `Select`'s. */
49
54
  invalid?: boolean;
55
+ /**
56
+ * seed-design's two Select-family sizes (crisp/#882): `medium` (default,
57
+ * 40px trigger floor) or `large` (52px). Purely visual.
58
+ */
59
+ size?: "medium" | "large";
60
+ /**
61
+ * `ghost` fills whatever row it's embedded in instead of the fixed
62
+ * trigger height — for inline table cell editors (crisp/#882, matching
63
+ * `Select`'s `variant`).
64
+ */
65
+ variant?: "default" | "ghost";
50
66
  className?: string;
51
67
  "aria-label"?: string;
52
68
  };
53
69
  /**
54
- * A multi-select / tag editor — measured from a cell tag picker. The
55
- * outlined trigger shows the selected values as coloured chips; it opens a
56
- * popover with a search field over rows of "[chip] … [checkbox]" that toggle on
57
- * click (the menu stays open). Keyboard: ↑/↓ move, Enter toggles, Esc closes.
70
+ * A multi-select / tag editor, its trigger/listbox/item chrome built to the
71
+ * same seed-design parity as `Select` (crisp/#882, following #867/#879) —
72
+ * its own chip/checkbox picker behaviour is unchanged. The outlined trigger
73
+ * shows the selected values as coloured chips; it opens a popover with a
74
+ * search field over rows of "[chip] … [checkbox]" that toggle on click (the
75
+ * menu stays open). Keyboard: ↑/↓ move, Enter/Space toggle, Esc closes.
58
76
  */
59
- export declare function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, name, required, id, placeholder: placeholderProp, searchable, searchPlaceholder: searchPlaceholderProp, emptyLabel: emptyLabelProp, disabled, invalid, className, "aria-label": ariaLabel, ...rest }: MultiSelectProps): React.JSX.Element;
77
+ export declare function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, name, required, id, placeholder: placeholderProp, searchable, searchPlaceholder: searchPlaceholderProp, emptyLabel: emptyLabelProp, disabled, readOnly, invalid, size, variant, className, "aria-label": ariaLabel, ...rest }: MultiSelectProps): React.JSX.Element;
60
78
  export declare namespace MultiSelect {
61
79
  var displayName: string;
62
80
  }
@@ -1,20 +1,44 @@
1
1
  declare const config: import("../..").RecipeConfig<{
2
+ size: {
3
+ medium: string;
4
+ large: string;
5
+ };
2
6
  invalid: {
3
7
  true: string;
4
8
  false: string;
5
9
  };
10
+ variant: {
11
+ default: string;
12
+ ghost: string;
13
+ };
6
14
  }>;
7
15
  export declare const multiselectRecipe: import("../..").RecipeFn<{
16
+ size: {
17
+ medium: string;
18
+ large: string;
19
+ };
8
20
  invalid: {
9
21
  true: string;
10
22
  false: string;
11
23
  };
24
+ variant: {
25
+ default: string;
26
+ ghost: string;
27
+ };
12
28
  }> & {
13
29
  config: import("../..").RecipeConfig<{
30
+ size: {
31
+ medium: string;
32
+ large: string;
33
+ };
14
34
  invalid: {
15
35
  true: string;
16
36
  false: string;
17
37
  };
38
+ variant: {
39
+ default: string;
40
+ ghost: string;
41
+ };
18
42
  }>;
19
43
  };
20
44
  export default config;
@@ -19,6 +19,15 @@ export type UseListboxKeyboardOptions = {
19
19
  * lands the user in the wrong place. Defaults to `close`.
20
20
  */
21
21
  dismiss?: () => void;
22
+ /**
23
+ * Space also commits the highlighted option, matching seed-design's
24
+ * Select (crisp/#867: Enter AND Space both commit) and native `<select>`.
25
+ * Defaults `false` because this same hook wires a `searchable` popup's own
26
+ * text input — there, Space must stay a normal character, never a commit.
27
+ * Pass `true` only when the element this hook is bound to is NOT a text
28
+ * field (the trigger itself, when not `searchable`).
29
+ */
30
+ commitOnSpace?: boolean;
22
31
  };
23
32
  /**
24
33
  * The WAI-ARIA listbox keyboard model for a POPUP listbox: ↑/↓ to move the
@@ -33,6 +42,6 @@ export type UseListboxKeyboardOptions = {
33
42
  * NOT for `WheelPicker`: that is an always-visible multi-column wheel that
34
43
  * commits on move, so Enter, Escape and Tab have no meaning in it.
35
44
  */
36
- export declare function useListboxKeyboard({ enabledIndexes, highlight, setHighlight, commit, close, dismiss, }: UseListboxKeyboardOptions): {
45
+ export declare function useListboxKeyboard({ enabledIndexes, highlight, setHighlight, commit, close, dismiss, commitOnSpace, }: UseListboxKeyboardOptions): {
37
46
  onKeyDown: (e: React.KeyboardEvent) => void;
38
47
  };
@@ -20,6 +20,12 @@ export type SelectOption = {
20
20
  * with no `group` render exactly as before this existed.
21
21
  */
22
22
  group?: string;
23
+ /**
24
+ * A second line under `label` (crisp/#867, seed-design's `SelectItem`
25
+ * label + description). Omit for the plain single-line row every existing
26
+ * consumer already renders.
27
+ */
28
+ description?: React.ReactNode;
23
29
  };
24
30
  export type SelectProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" | "defaultValue" | "onChange"> & {
25
31
  options: SelectOption[];
@@ -49,6 +55,19 @@ export type SelectProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" |
49
55
  variant?: "default" | "ghost";
50
56
  /** `full` (default) fills its container; `auto` sizes to content. */
51
57
  width?: "full" | "auto";
58
+ /**
59
+ * seed-design's two Select sizes (crisp/#867): `medium` (default, 40px
60
+ * trigger) for general use, `large` (52px) where the surrounding layout
61
+ * calls for it. Purely visual — everything else about the control is
62
+ * identical between the two.
63
+ */
64
+ size?: "medium" | "large";
65
+ /**
66
+ * Answered and locked, not editable — unlike `disabled`, the trigger stays
67
+ * focusable and its text stays full-strength ink (crisp/#867, seed-design's
68
+ * `readonly` state: the fill greys like `disabled`, the text doesn't).
69
+ */
70
+ readOnly?: boolean;
52
71
  /** Show a search field at the top of the list that filters options (Linear/cmdk style). */
53
72
  searchable?: boolean;
54
73
  searchPlaceholder?: string;
@@ -68,13 +87,16 @@ export type SelectProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" |
68
87
  id?: string;
69
88
  };
70
89
  /**
71
- * A select / dropdown — the settings control, measured live, with an
72
- * optional Linear-style search. A `role="combobox"` trigger opens a
73
- * `role="listbox"`; pass `searchable` to add a filter field at the top (with a
74
- * "No results" empty state). Full keyboard model — ↑/↓ move, Enter/Space pick,
75
- * Esc close, Home/End jump, opens upward when tight. Controlled or uncontrolled.
90
+ * A select / dropdown, built to seed-design's Select (crisp/#867) rather than
91
+ * measured from Attio — a deliberate one-component exception, the same way
92
+ * `DatePicker` follows seed's calendar structure — with an optional
93
+ * Linear-style search seed itself has no equivalent of. A `role="combobox"`
94
+ * trigger opens a `role="listbox"`; pass `searchable` to add a filter field
95
+ * at the top (with a "No results" empty state). Full keyboard model — ↑/↓
96
+ * move, Enter/Space pick, Esc close, Home/End jump, opens upward when tight.
97
+ * Controlled or uncontrolled.
76
98
  */
77
- export declare function Select({ options, value, defaultValue, onValueChange, name, required, placeholder: placeholderProp, variant, width, searchable, searchPlaceholder: searchPlaceholderProp, onSearchChange, emptyLabel: emptyLabelProp, disabled, invalid, className, "aria-label": ariaLabel, id, ...rest }: SelectProps): React.JSX.Element;
99
+ export declare function Select({ options, value, defaultValue, onValueChange, name, required, placeholder: placeholderProp, variant, width, size, searchable, searchPlaceholder: searchPlaceholderProp, onSearchChange, emptyLabel: emptyLabelProp, disabled, readOnly, invalid, className, "aria-label": ariaLabel, id, ...rest }: SelectProps): React.JSX.Element;
78
100
  export declare namespace Select {
79
101
  var displayName: string;
80
102
  }
@@ -1,44 +1,56 @@
1
1
  declare const config: import("../..").RecipeConfig<{
2
- variant: {
3
- default: string;
4
- ghost: string;
5
- };
6
2
  width: {
7
3
  full: string;
8
4
  auto: string;
9
5
  };
6
+ size: {
7
+ medium: string;
8
+ large: string;
9
+ };
10
10
  invalid: {
11
11
  true: string;
12
12
  false: string;
13
13
  };
14
- }>;
15
- export declare const selectRecipe: import("../..").RecipeFn<{
16
14
  variant: {
17
15
  default: string;
18
16
  ghost: string;
19
17
  };
18
+ }>;
19
+ export declare const selectRecipe: import("../..").RecipeFn<{
20
20
  width: {
21
21
  full: string;
22
22
  auto: string;
23
23
  };
24
+ size: {
25
+ medium: string;
26
+ large: string;
27
+ };
24
28
  invalid: {
25
29
  true: string;
26
30
  false: string;
27
31
  };
32
+ variant: {
33
+ default: string;
34
+ ghost: string;
35
+ };
28
36
  }> & {
29
37
  config: import("../..").RecipeConfig<{
30
- variant: {
31
- default: string;
32
- ghost: string;
33
- };
34
38
  width: {
35
39
  full: string;
36
40
  auto: string;
37
41
  };
42
+ size: {
43
+ medium: string;
44
+ large: string;
45
+ };
38
46
  invalid: {
39
47
  true: string;
40
48
  false: string;
41
49
  };
50
+ variant: {
51
+ default: string;
52
+ ghost: string;
53
+ };
42
54
  }>;
43
55
  };
44
56
  export default config;
@@ -320,6 +320,13 @@ export type ToolbarToolProps = React.ComponentPropsWithoutRef<"button"> & {
320
320
  /** The quieter, no-ring variant Sort/Filter never use themselves, for a
321
321
  * chip whose "on" state should read as less committed than a real filter. */
322
322
  ghost?: boolean;
323
+ /**
324
+ * A trailing count badge (crisp#875) — a screen's own quick filter
325
+ * showing how many rows match, e.g. "My tasks 5". Measured live on two
326
+ * independent Attio surfaces (the Sort tool's own "+N" overflow, a Kanban
327
+ * board's stage-column count): a small neutral chip, not bare text.
328
+ */
329
+ count?: React.ReactNode;
323
330
  };
324
331
  /**
325
332
  * The Sort/Filter chip's own chrome (`.crisp-tabletoolbar-tool`), standalone
@@ -337,5 +344,12 @@ export declare const ToolbarTool: React.ForwardRefExoticComponent<Omit<React.Det
337
344
  /** The quieter, no-ring variant Sort/Filter never use themselves, for a
338
345
  * chip whose "on" state should read as less committed than a real filter. */
339
346
  ghost?: boolean;
347
+ /**
348
+ * A trailing count badge (crisp#875) — a screen's own quick filter
349
+ * showing how many rows match, e.g. "My tasks 5". Measured live on two
350
+ * independent Attio surfaces (the Sort tool's own "+N" overflow, a Kanban
351
+ * board's stage-column count): a small neutral chip, not bare text.
352
+ */
353
+ count?: React.ReactNode;
340
354
  } & React.RefAttributes<HTMLButtonElement>>;
341
355
  export {};
@@ -20,6 +20,14 @@ export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" | "d
20
20
  leading?: React.ReactNode;
21
21
  /** Rendered for the active tab. Receives the active value. */
22
22
  children?: (value: string) => React.ReactNode;
23
+ /**
24
+ * The "+N more" overflow trigger's own label (crisp#863, confirmed live:
25
+ * Attio's own copy is exactly "+N more", a chevron after it). Receives
26
+ * the hidden-tab count. Defaults to that measured copy.
27
+ */
28
+ moreLabel?: (count: number) => React.ReactNode;
29
+ /** aria-label on the overflow trigger/menu (default "More tabs"). */
30
+ moreMenuLabel?: string;
23
31
  className?: string;
24
32
  "aria-label"?: string;
25
33
  };
@@ -29,7 +37,7 @@ export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" | "d
29
37
  * Home/End jump); activation follows focus. Controlled via
30
38
  * `value`/`onValueChange`, or uncontrolled from `defaultValue`.
31
39
  */
32
- export declare function Tabs({ tabs, value, defaultValue, onValueChange, leading, children, className, fill, "aria-label": ariaLabel, ...rest }: TabsProps): React.JSX.Element;
40
+ export declare function Tabs({ tabs, value, defaultValue, onValueChange, leading, children, moreLabel, moreMenuLabel, className, fill, "aria-label": ariaLabel, ...rest }: TabsProps): React.JSX.Element;
33
41
  export declare namespace Tabs {
34
42
  var displayName: string;
35
43
  }
@@ -4,6 +4,13 @@ export type TextLinkProps = React.ComponentPropsWithoutRef<"a"> & {
4
4
  * `"muted"` (default) — quiet until hover, then brand-coloured (an
5
5
  * in-context reference link, e.g. a sample record under a finding). */
6
6
  tone?: "brand" | "muted";
7
+ /**
8
+ * Overrides the tone's own font-size only (colour/weight/hover stay
9
+ * whatever `tone` gives). Omit it and each tone keeps its existing size
10
+ * unchanged — `brand`'s 12px, `muted`'s 13px. `"lg"` (14px) matches a
11
+ * `DataTable` primary-column's own ambient size (crisp#874).
12
+ */
13
+ size?: "sm" | "md" | "lg";
7
14
  className?: string;
8
15
  };
9
16
  /**
@@ -13,7 +20,7 @@ export type TextLinkProps = React.ComponentPropsWithoutRef<"a"> & {
13
20
  * `event.preventDefault()` pairs it with client-side routing (e.g.
14
21
  * react-router's own `Link`).
15
22
  */
16
- export declare function TextLink({ tone, className, ...rest }: TextLinkProps): React.JSX.Element;
23
+ export declare function TextLink({ tone, size, className, ...rest }: TextLinkProps): React.JSX.Element;
17
24
  export declare namespace TextLink {
18
25
  var displayName: string;
19
26
  }
@@ -3,11 +3,21 @@ declare const config: import("../..").RecipeConfig<{
3
3
  brand: string;
4
4
  muted: string;
5
5
  };
6
+ size: {
7
+ sm: string;
8
+ md: string;
9
+ lg: string;
10
+ };
6
11
  }>;
7
12
  export declare const textlinkRecipe: import("../..").RecipeFn<{
8
13
  tone: {
9
14
  brand: string;
10
15
  muted: string;
11
16
  };
17
+ size: {
18
+ sm: string;
19
+ md: string;
20
+ lg: string;
21
+ };
12
22
  }>;
13
23
  export default config;
@@ -57,6 +57,17 @@ export type RecordPageHighlight = {
57
57
  value: React.ReactNode | null;
58
58
  empty?: React.ReactNode;
59
59
  };
60
+ /**
61
+ * One icon button in the quick-action row (#865) — "New note"/"Run
62
+ * workflow"/"New task" in the built-in CRM set. `label` doubles as the
63
+ * button's `aria-label`, since these render icon-only (measured live: no
64
+ * visible text next to any of the three, only a native-title tooltip).
65
+ */
66
+ export type RecordPageQuickAction = {
67
+ label: string;
68
+ icon: LucideIcon;
69
+ onSelect?: () => void;
70
+ };
60
71
  export type RecordPageProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
61
72
  record: Row;
62
73
  columns: Column[];
@@ -90,6 +101,18 @@ export type RecordPageProps = Omit<React.ComponentPropsWithoutRef<"div">, "child
90
101
  tabs?: RecordPageTab[];
91
102
  /** Active tab id on first render, when `tabs` is supplied. Defaults to the first tab. Ignored for the built-in tab set (Overview is always first there). */
92
103
  defaultTab?: string;
104
+ /**
105
+ * Replaces the quick-action row's icon buttons (New note / Run workflow /
106
+ * New task) — the same "caller's own list, not a merge" choice `tabs`
107
+ * (#379) and `highlights` (#528) already make. Confirmed live this set
108
+ * varies by object type (#865): a Person record carries a 4th,
109
+ * unidentified icon that Company and Deal records don't, so a consumer
110
+ * targeting a non-CRM object supplies its own icons rather than crisp
111
+ * guessing at a superset. The row's two text buttons ("Compose email",
112
+ * "Add to list") aren't part of this override — discovery found no
113
+ * variance there, only in the icon set. Omit to keep the built-in three.
114
+ */
115
+ quickActions?: RecordPageQuickAction[];
93
116
  /**
94
117
  * Controlled Notes: when supplied (even as `[]`), RecordPage renders
95
118
  * this list instead of managing its own, and the composer calls
@@ -142,6 +165,7 @@ export type RecordPageLabels = {
142
165
  linkRecords: string;
143
166
  logANote: string;
144
167
  createATask: string;
168
+ runWorkflow: string;
145
169
  fullScreen: string;
146
170
  exitFullScreen: string;
147
171
  resizeDetails: string;
@@ -244,7 +268,7 @@ export declare namespace RecordDetails {
244
268
  * Emails sections (Notes & Tasks are live — add and check things off). Drop it
245
269
  * into the app's main content area.
246
270
  */
247
- export declare function RecordPage({ record, columns, collection, labels, onBack, onToggleFull, full, className, onEdit, tabs: tabsProp, defaultTab, notes: notesProp, onAddNote, tasks: tasksProp, onAddTask, onToggleTask, sections, highlights: highlightsProp, ...rest }: RecordPageProps): React.JSX.Element;
271
+ export declare function RecordPage({ record, columns, collection, labels, onBack, onToggleFull, full, className, onEdit, tabs: tabsProp, defaultTab, notes: notesProp, onAddNote, tasks: tasksProp, onAddTask, onToggleTask, sections, highlights: highlightsProp, quickActions: quickActionsProp, ...rest }: RecordPageProps): React.JSX.Element;
248
272
  export declare namespace RecordPage {
249
273
  var displayName: string;
250
274
  }
@@ -56,10 +56,20 @@ export declare const contract: MapLeafNodes<{
56
56
  bgPurpleSoft: "purpleTint";
57
57
  fgPurpleSoft: "softPurpleText";
58
58
  ringPurpleSoft: "purpleRing";
59
+ ringBrandSoft: "ringBrandSoft";
60
+ fgSelectNeutral: "fieldFocus";
61
+ bgSelectListbox: "selectListboxBg";
62
+ strokeSelectTrigger: "selectTriggerStroke";
63
+ bgSelectPressed: "selectPressedTint";
64
+ bgSelectDisabled: "selectDisabledBg";
65
+ strokeSelectInvalid: "selectInvalidStroke";
66
+ strokeSelectDivider: "selectDivider";
67
+ fgSelectPlaceholder: "selectPlaceholder";
68
+ shadowSelect: "selectShadow";
59
69
  }, `var(--${string})`> & {
60
- space: Record<"0.5" | "1" | "1.5" | "2" | "2.5" | "3" | "4" | "5" | "6" | "8" | "px", `var(--${string})`>;
61
- radius: Record<"2xl" | "chip" | "full" | "lg" | "md" | "sm" | "xl", `var(--${string})`>;
62
- size: Record<"calendarCell" | "calendarPill" | "chip" | "header" | "icon" | "menuRow" | "row" | "tableHeader" | "tableRow", `var(--${string})`>;
70
+ space: Record<"0.5" | "1" | "1.5" | "2" | "2.5" | "3" | "3.5" | "4" | "5" | "6" | "8" | "px", `var(--${string})`>;
71
+ radius: Record<"2xl" | "3xl" | "chip" | "full" | "lg" | "md" | "sm" | "xl", `var(--${string})`>;
72
+ size: Record<"calendarCell" | "calendarPill" | "chip" | "header" | "icon" | "menuRow" | "row" | "selectIconLg" | "selectTriggerLg" | "selectTriggerMd" | "tableHeader" | "tableRow", `var(--${string})`>;
63
73
  font: Record<"sans", `var(--${string})`>;
64
74
  text: Record<"lg" | "md" | "sm" | "xl" | "xs", `var(--${string})`>;
65
75
  weight: Record<"bold" | "medium" | "regular" | "semibold", `var(--${string})`>;
@@ -55,5 +55,12 @@ export declare const elevation: {
55
55
  * nobody measured for them.
56
56
  */
57
57
  readonly fieldNoRing: `0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04)`;
58
+ /**
59
+ * Select's own listbox shadow (crisp/#867) — seed-design's `$shadow.s3`, a
60
+ * single layer, NOT `floating` above. This component follows seed, not
61
+ * Attio, for the same reason `DatePicker` follows seed's calendar
62
+ * structure: an explicit owner request to match seed-design exactly.
63
+ */
64
+ readonly selectFloating: `0 4px 16px var(--${string})`;
58
65
  };
59
66
  export type ElevationKey = keyof typeof elevation;