@crisp-ui-kit/crisp 0.54.7 → 0.54.8

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 (113) hide show
  1. package/dist/authshell.css +5 -1
  2. package/dist/authshell.layered.css +5 -1
  3. package/dist/badge.css +5 -5
  4. package/dist/badge.layered.css +5 -5
  5. package/dist/board.css +13 -9
  6. package/dist/board.layered.css +13 -9
  7. package/dist/button.css +3 -1
  8. package/dist/button.layered.css +3 -1
  9. package/dist/cjs/components/badge/badge.recipe.js +28 -5
  10. package/dist/cjs/components/button/button.js +33 -2
  11. package/dist/cjs/components/button/button.recipe.js +31 -5
  12. package/dist/cjs/components/datatable/datatable.js +66 -7
  13. package/dist/cjs/components/datatable/datatable.recipe.js +57 -2
  14. package/dist/cjs/components/dialog/dialog.js +8 -5
  15. package/dist/cjs/components/dialog/dialog.recipe.js +15 -1
  16. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +12 -3
  17. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +231 -48
  18. package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +44 -0
  19. package/dist/cjs/components/tabs/tabs.recipe.js +11 -2
  20. package/dist/cjs/components/tooltip/tooltip.js +23 -9
  21. package/dist/cjs/components/tooltip/tooltip.recipe.js +10 -9
  22. package/dist/cjs/product/authshell/authshell.js +14 -1
  23. package/dist/cjs/product/authshell/authshell.recipe.js +13 -1
  24. package/dist/cjs/product/board/board.js +122 -27
  25. package/dist/cjs/product/board/board.recipe.js +14 -2
  26. package/dist/cjs/product/comments/comments.js +23 -10
  27. package/dist/cjs/product/comments/comments.recipe.js +17 -3
  28. package/dist/cjs/product/formdialog/formdialog.js +10 -4
  29. package/dist/cjs/product/navitem/navitem.js +7 -2
  30. package/dist/cjs/product/navitem/navitem.recipe.js +16 -0
  31. package/dist/cjs/product/objectsettings/index.js +1 -2
  32. package/dist/cjs/product/objectsettings/objectsettings.js +3 -13
  33. package/dist/cjs/product/richtext/richtext.js +76 -1
  34. package/dist/cjs/product/sidebar/sidebar.js +68 -15
  35. package/dist/cjs/product/sidebar/sidebar.recipe.js +6 -1
  36. package/dist/cjs/tokens/palette.js +32 -1
  37. package/dist/cjs/tokens/semantic.js +11 -0
  38. package/dist/comments.css +36 -10
  39. package/dist/comments.layered.css +36 -10
  40. package/dist/datatable.css +47 -9
  41. package/dist/datatable.layered.css +47 -9
  42. package/dist/dialog.css +13 -1
  43. package/dist/dialog.layered.css +13 -1
  44. package/dist/esm/components/badge/badge.recipe.js +28 -5
  45. package/dist/esm/components/button/button.js +34 -3
  46. package/dist/esm/components/button/button.recipe.js +31 -5
  47. package/dist/esm/components/datatable/datatable.js +67 -8
  48. package/dist/esm/components/datatable/datatable.recipe.js +57 -2
  49. package/dist/esm/components/dialog/dialog.js +8 -5
  50. package/dist/esm/components/dialog/dialog.recipe.js +15 -1
  51. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +12 -3
  52. package/dist/esm/components/tabletoolbar/tabletoolbar.js +231 -48
  53. package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +44 -0
  54. package/dist/esm/components/tabs/tabs.recipe.js +11 -2
  55. package/dist/esm/components/tooltip/tooltip.js +23 -9
  56. package/dist/esm/components/tooltip/tooltip.recipe.js +10 -9
  57. package/dist/esm/product/authshell/authshell.js +15 -2
  58. package/dist/esm/product/authshell/authshell.recipe.js +13 -1
  59. package/dist/esm/product/authshell/index.js +1 -1
  60. package/dist/esm/product/board/board.js +122 -27
  61. package/dist/esm/product/board/board.recipe.js +14 -2
  62. package/dist/esm/product/comments/comments.js +23 -10
  63. package/dist/esm/product/comments/comments.recipe.js +17 -3
  64. package/dist/esm/product/formdialog/formdialog.js +10 -4
  65. package/dist/esm/product/navitem/index.js +1 -1
  66. package/dist/esm/product/navitem/navitem.js +7 -2
  67. package/dist/esm/product/navitem/navitem.recipe.js +16 -0
  68. package/dist/esm/product/objectsettings/index.js +1 -1
  69. package/dist/esm/product/objectsettings/objectsettings.js +2 -12
  70. package/dist/esm/product/richtext/richtext.js +76 -1
  71. package/dist/esm/product/sidebar/sidebar.js +69 -16
  72. package/dist/esm/product/sidebar/sidebar.recipe.js +6 -1
  73. package/dist/esm/tokens/palette.js +32 -1
  74. package/dist/esm/tokens/semantic.js +11 -0
  75. package/dist/native/tokens.d.ts +1 -1
  76. package/dist/native/tokens.js +16 -2
  77. package/dist/navitem.css +7 -0
  78. package/dist/navitem.layered.css +7 -0
  79. package/dist/recordstable.css +1 -1
  80. package/dist/recordstable.layered.css +1 -1
  81. package/dist/sidebar.css +6 -1
  82. package/dist/sidebar.layered.css +6 -1
  83. package/dist/styles.css +163 -42
  84. package/dist/styles.layered.css +163 -42
  85. package/dist/tabletoolbar.css +16 -1
  86. package/dist/tabletoolbar.layered.css +16 -1
  87. package/dist/tabs.css +1 -1
  88. package/dist/tabs.layered.css +1 -1
  89. package/dist/tokens.css +9 -1
  90. package/dist/tokens.json +16 -2
  91. package/dist/tooltip.css +1 -1
  92. package/dist/tooltip.layered.css +1 -1
  93. package/dist/types/components/badge/badge.recipe.d.ts +5 -1
  94. package/dist/types/components/button/button.recipe.d.ts +18 -5
  95. package/dist/types/components/datatable/datatable.d.ts +9 -0
  96. package/dist/types/components/dialog/dialog.d.ts +25 -2
  97. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +43 -3
  98. package/dist/types/components/tooltip/tooltip.d.ts +12 -4
  99. package/dist/types/components/tooltip/tooltip.recipe.d.ts +1 -1
  100. package/dist/types/product/authshell/authshell.d.ts +26 -2
  101. package/dist/types/product/authshell/index.d.ts +1 -1
  102. package/dist/types/product/board/board.d.ts +5 -4
  103. package/dist/types/product/comments/comments.d.ts +10 -2
  104. package/dist/types/product/formdialog/formdialog.d.ts +2 -1
  105. package/dist/types/product/navitem/index.d.ts +1 -1
  106. package/dist/types/product/navitem/navitem.d.ts +23 -0
  107. package/dist/types/product/objectsettings/index.d.ts +1 -1
  108. package/dist/types/product/objectsettings/objectsettings.d.ts +0 -10
  109. package/dist/types/product/sidebar/sidebar.d.ts +33 -5
  110. package/dist/types/tokens/contract.d.ts +4 -0
  111. package/dist/types/tokens/palette.d.ts +13 -1
  112. package/dist/types/tokens/semantic.d.ts +11 -0
  113. package/package.json +1 -1
@@ -21,8 +21,20 @@ const config = defineRecipe({
21
21
  }
22
22
  /* The header cell has no padding of its own -- the button owns the
23
23
  full cell so the whole header is clickable (its own inset is 12px).
24
- Mirrors the summary-row fix. */
25
- & th { padding: 0; }
24
+ Mirrors the summary-row fix.
25
+ \`& .crisp-table th\`, not bare \`& th\` (found while re-checking #691's
26
+ own fix live): DataTable's root nests \`Table\`'s own wrapper, whose
27
+ \`table.recipe.ts\` carries \`& th, & td { padding: 0 12px }\` at the
28
+ SAME specificity (.crisp-table th vs .crisp-datatable th, both one
29
+ class + one element) -- a bare \`& th\` here only won by source
30
+ order, which flipped the moment table.recipe.ts's own CSS file
31
+ happened to land after datatable's in the build (alphabetical:
32
+ datatable < table), silently reinstating 12px on every header cell
33
+ in the whole product and making every interactive column's button
34
+ double it to 24px. Scoping through \`.crisp-table\` adds a second
35
+ class to the selector (0,2,1 beats 0,1,1) so this can never lose a
36
+ specificity tie to source order again. */
37
+ & .crisp-table th { padding: 0; }
26
38
  /* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
27
39
  Menu wraps its trigger in a flex div that sizes to its content, so a
28
40
  long header grew past the column instead of filling it -- with nothing
@@ -33,6 +45,20 @@ const config = defineRecipe({
33
45
  & th .crisp-menu { width: 100%; height: 100%; }
34
46
  & .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: ${c.space["1.5"]}; width: 100%; min-width: 0; height: 100%; }
35
47
  & .crisp-datatable-th-inner > svg { flex-shrink: 0; color: ${c.fgMuted}; }
48
+ /* crisp/#605 follow-up: a header with neither a Menu nor a sort button
49
+ (the primary/entity column's now-inert path, or any column with no
50
+ columnMenu/sortable at all) renders .crisp-datatable-th-inner as a
51
+ DIRECT child of th instead of nested inside a button -- and loses
52
+ the button's own 12px inset, drifting left of the td's 12px base
53
+ inset. Measured live on Attio's own Companies grid: the header label
54
+ and the cell's own text land at the exact same x (335px from the
55
+ viewport, both 40px from the column's left edge) via two different
56
+ padding+icon+gap combinations -- Attio does not leave the inert
57
+ primary header flush left either. The \`>\` combinator targets only
58
+ the button-less case: Menu's own wrapper (\`.crisp-menu\`) and the
59
+ plain sort \`button\` both put >=1 more level between \`th\` and this
60
+ span, so their own 12px (already on the button) isn't doubled. */
61
+ & th > .crisp-datatable-th-inner { box-sizing: border-box; padding: 0 ${c.space["3"]}; }
36
62
  /* The summary cell has NO padding of its own -- the calculation trigger
37
63
  owns the whole 246x37 area so a click anywhere in the cell opens the
38
64
  menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
@@ -116,8 +142,37 @@ const config = defineRecipe({
116
142
  & .crisp-datatable-refoption-avatar { flex-shrink: 0; }
117
143
  & .crisp-datatable-refoption--create { color: ${c.fgMuted}; }
118
144
  & .crisp-datatable-empty { padding: ${c.space["8"]} ${c.space["3"]}; text-align: center; color: ${c.fgMuted}; font-size: ${c.text.lg}; }
145
+ /* #579: click-to-expand overlay for a truncated cell -- a read-only,
146
+ full-value card, settled live as click (not Attio's usual
147
+ hover-expand) and measured position: absolute, unlike this file's
148
+ floating chrome (Menu/Select popovers) which portals and escapes the
149
+ scroll container. Deliberately NOT the edit-error pattern above
150
+ (grow the row, block-level, never clipped): a virtualized grid
151
+ assumes a fixed row height for its scroll math (owned by the grid
152
+ core, not this cell), so growing a row here would fight it. Anchored
153
+ to the SAME column width the cell itself renders at (measured:
154
+ Attio's own overlay came out only slightly wider than the
155
+ triggering cell's clientWidth -- the overshoot is this padding),
156
+ wrapping onto as many lines as the value needs; it CAN be clipped by
157
+ \`.crisp-table-scroll\`'s own \`overflow: auto\` if it grows past the
158
+ visible viewport, same as the edit-error comment above already
159
+ notes for any position:absolute escape -- unmeasured against Attio
160
+ for this exact case, flagged rather than guessed. */
161
+ & td[data-cell-expanded] { overflow: visible; z-index: 7; }
162
+ & .crisp-datatable-cell-overlay {
163
+ position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box;
164
+ padding: ${c.space["2"]} ${c.space["3"]}; background: ${c.bgSurface};
165
+ border: 1px solid ${c.bgBrandSolid}; border-radius: 4px;
166
+ font-family: ${c.font.sans}; font-size: ${c.text.lg}; line-height: 20px; font-weight: ${c.weight.medium};
167
+ color: ${c.fgPrimary}; white-space: normal; word-break: break-word; cursor: default;
168
+ }
119
169
  /* fixed layout so column widths (and resize) are exact — like RecordsTable */
120
170
  & table { table-layout: fixed; }
171
+ /* read-only/computed column marker (#596) -- sits just inside the
172
+ resize handle, same absolute-positioned-against-the-th approach the
173
+ handle itself uses, since th has zero padding and the button/inner
174
+ row fills the whole cell with no room left for a trailing sibling. */
175
+ & .crisp-datatable-readonly { position: absolute; top: 50%; inset-inline-end: 11px; transform: translateY(-50%); color: ${c.fgMuted}; pointer-events: none; z-index: 5; }
121
176
  /* column resize grip */
122
177
  & .crisp-datatable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
123
178
  & .crisp-datatable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: ${c.bgBrandSolid}; opacity: 0; transition: opacity .12s; }
@@ -22,12 +22,13 @@ function useDialogInstanceId() {
22
22
  * Escape / outside-click dismissal) with the measured modal surface.
23
23
  * Compose the body with `DialogBody` and actions with `DialogFooter`.
24
24
  */
25
- export function Dialog({ open, onOpenChange, title, icon, width = 640, "aria-label": ariaLabel, closeLabel: closeLabelProp, children, className, style, "aria-describedby": describedBy, ...rest }) {
25
+ export function Dialog({ open, onOpenChange, title, icon, width = 640, variant = "panel", description, "aria-label": ariaLabel, closeLabel: closeLabelProp, children, className, style, "aria-describedby": describedBy, ...rest }) {
26
26
  const closeLabel = useCrispMessage(closeLabelProp, "Close");
27
27
  const id = useDialogInstanceId();
28
28
  const service = useMachine(dialog.machine, {
29
29
  id,
30
30
  open,
31
+ role: variant === "alert" ? "alertdialog" : "dialog",
31
32
  onOpenChange(details) {
32
33
  onOpenChange(details.open);
33
34
  },
@@ -51,15 +52,17 @@ export function Dialog({ open, onOpenChange, title, icon, width = 640, "aria-lab
51
52
  const api = dialog.connect(service, normalizeProps);
52
53
  if (!api.open)
53
54
  return null;
54
- return (_jsx(Portal, { children: _jsxs("div", { className: dialogRecipe(), children: [_jsx("div", { ...api.getBackdropProps(), className: "crisp-dialog-backdrop" }), _jsx("div", { ...api.getPositionerProps(), className: "crisp-dialog-positioner", children: _jsx("div", { ...rest, ...withDescribedBy(api.getContentProps(), describedBy), className: cx("crisp-dialog-content", className), "data-crisp-dialog": id,
55
+ return (_jsx(Portal, { children: _jsxs("div", { className: dialogRecipe(), children: [_jsx("div", { ...api.getBackdropProps(), className: "crisp-dialog-backdrop" }), _jsx("div", { ...api.getPositionerProps(), className: "crisp-dialog-positioner", "data-variant": variant, children: _jsx("div", { ...rest, ...withDescribedBy(api.getContentProps(), describedBy), className: cx("crisp-dialog-content", className), "data-crisp-dialog": id, "data-variant": variant,
55
56
  // `width` is the component's own knob, so it wins over a passed
56
57
  // maxWidth; everything else a consumer sets survives
57
- style: { ...style, maxWidth: `min(${width}px, 90vw)` }, children: _jsxs("div", { className: "crisp-dialog-card", children: [title != null && (_jsxs("div", { className: "crisp-dialog-header", children: [icon, _jsx("h2", { ...api.getTitleProps(), className: "crisp-dialog-title", children: title }), _jsx("button", { type: "button", ...api.getCloseTriggerProps(), className: "crisp-dialog-close", "aria-label": closeLabel, children: _jsx(X, { size: 16, strokeWidth: 2, "aria-hidden": "true" }) })] })), children] }) }) })] }) }));
58
+ style: { ...style, maxWidth: `min(${width}px, 90vw)` }, children: _jsxs("div", { className: "crisp-dialog-card", children: [variant === "alert"
59
+ ? (title != null || description != null) && (_jsxs("div", { className: "crisp-dialog-alert-header", children: [title != null && (_jsx("h2", { ...api.getTitleProps(), className: "crisp-dialog-alert-title", children: title })), description != null && (_jsx("p", { ...api.getDescriptionProps(), className: "crisp-dialog-alert-description", children: description }))] }))
60
+ : title != null && (_jsxs("div", { className: "crisp-dialog-header", children: [icon, _jsx("h2", { ...api.getTitleProps(), className: "crisp-dialog-title", children: title }), _jsx("button", { type: "button", ...api.getCloseTriggerProps(), className: "crisp-dialog-close", "aria-label": closeLabel, children: _jsx(X, { size: 16, strokeWidth: 2, "aria-hidden": "true" }) })] })), children] }) }) })] }) }));
58
61
  }
59
62
  Dialog.displayName = "Dialog";
60
63
  export function DialogBody({ children, className, }) {
61
64
  return (_jsx("div", { className: className ? `crisp-dialog-body ${className}` : "crisp-dialog-body", children: children }));
62
65
  }
63
- export function DialogFooter({ children }) {
64
- return _jsx("div", { className: "crisp-dialog-footer", children: children });
66
+ export function DialogFooter({ children, variant = "panel", }) {
67
+ return (_jsx("div", { className: "crisp-dialog-footer", "data-variant": variant, children: children }));
65
68
  }
@@ -15,17 +15,31 @@ import { contract as c, elevation as e } from "../../tokens/index.js";
15
15
  const config = defineRecipe({
16
16
  name: "dialog",
17
17
  base: `display: contents; font-family: ${c.font.sans};
18
- & .crisp-dialog-backdrop { position: fixed; inset: 0; z-index: 60; background: transparent; }
18
+ & .crisp-dialog-backdrop { position: fixed; inset: 0; z-index: 60; background: ${c.bgScrim}; }
19
19
  & .crisp-dialog-positioner { position: fixed; inset: 0; z-index: 61; display: flex; align-items: flex-start; justify-content: center; padding: 15vh ${c.space["4"]} ${c.space["4"]}; }
20
+ & .crisp-dialog-positioner[data-variant="alert"] { align-items: center; padding: ${c.space["4"]}; }
20
21
  & .crisp-dialog-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 90vw; max-height: 74vh; padding: ${c.space["1"]}; border-radius: ${c.radius["2xl"]}; background: color-mix(in srgb, ${c.bgOverlayFrost} 60%, transparent); backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px); box-shadow: ${e.modal}; opacity: 1; transform: scale(1); transition: opacity 0.2s ease, transform 0.2s ease; @starting-style { opacity: 0; transform: scale(0.97); } }
22
+ & .crisp-dialog-content[data-variant="alert"] { padding: 0; background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: none; }
21
23
  & .crisp-dialog-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: ${c.radius.xl}; background: ${c.bgSurface}; box-shadow: 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 8%, transparent); overflow: hidden; }
24
+ & .crisp-dialog-content[data-variant="alert"] .crisp-dialog-card { border-radius: ${c.radius.xl}; background: ${c.bgPopover}; box-shadow: ${e.floating}; }
22
25
  & .crisp-dialog-header { display: flex; align-items: center; gap: ${c.space["2"]}; flex-shrink: 0; height: 52px; padding: 0 ${c.space["2"]} 0 ${c.space["4"]}; border-bottom: 1px solid ${c.borderSubtle}; }
23
26
  & .crisp-dialog-header svg { flex-shrink: 0; color: ${c.fgMuted}; }
24
27
  & .crisp-dialog-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}; margin: 0; }
25
28
  & .crisp-dialog-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: ${c.radius.md}; background: none; color: ${c.fgMuted}; font-family: inherit; cursor: pointer; }
26
29
  & .crisp-dialog-close:hover { background: color-mix(in srgb, ${c.fgPrimary} 6%, transparent); color: ${c.fgPrimary}; }
30
+ /* The discard-confirm's own stacked title + sentence (crisp#677) — no
31
+ border, no close button, unlike the panel header above: measured
32
+ live, both themes, 18px/24px 600-weight title (no scale token
33
+ reaches 18px — the scale tops out at text.xl's 16px, so this is raw
34
+ px per Golden Rule 3's "genuinely intrinsic size" exception, same as
35
+ this file's own submit-key glyphs) then a 14px/20px 500-weight
36
+ sentence 4px below it. */
37
+ & .crisp-dialog-alert-header { display: flex; flex-direction: column; gap: ${c.space["1"]}; padding: ${c.space["4"]} ${c.space["4"]} 0; }
38
+ & .crisp-dialog-alert-title { margin: 0; font-size: 18px; line-height: 24px; font-weight: ${c.weight.semibold}; color: ${c.fgPrimary}; }
39
+ & .crisp-dialog-alert-description { margin: 0; font-size: ${c.text.lg}; line-height: 20px; font-weight: ${c.weight.medium}; color: ${c.fgAlertDescription}; }
27
40
  & .crisp-dialog-body { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: ${c.space["4"]}; padding: ${c.space["5"]} ${c.space["4"]}; }
28
41
  & .crisp-dialog-footer { display: flex; align-items: center; justify-content: flex-end; gap: ${c.space["3"]}; flex-shrink: 0; min-height: 56px; padding: 0 ${c.space["4"]}; border-top: 1px solid ${c.borderSubtle}; }
42
+ & .crisp-dialog-footer[data-variant="alert"] { min-height: 45px; padding: ${c.space["2"]}; }
29
43
  & .crisp-dialog-field { display: flex; flex-direction: column; gap: ${c.space["1.5"]}; }
30
44
  & .crisp-dialog-field-label { font-size: ${c.text.sm}; font-weight: ${c.weight.medium}; color: color-mix(in srgb, ${c.fgPrimary} 50%, transparent); }
31
45
  & .crisp-dialog-more { display: inline-flex; align-items: center; gap: ${c.space["2"]}; margin-inline-end: auto; border: none; background: none; padding: 0; font-family: inherit; font-size: ${c.text.md}; color: ${c.fgMuted}; cursor: pointer; }
@@ -16,12 +16,21 @@ import { contract as c, elevation as e } from "../../tokens/index.js";
16
16
  // stay byte-for-byte identical to what shipped before the extraction.
17
17
  //
18
18
  // `.menu--op` (#594 follow-up) is the filter condition's own operator list —
19
- // measured live against Attio's own popover at 135px (rounds to 134px), not
20
- // the default 232px every other menu here uses. `.menu-item` also picked up
19
+ // no fixed min-width of its own (#593 correction below), unlike the default
20
+ // 232px every other menu here uses. `.menu-item` also picked up
21
21
  // `line-height: 20px` and `font-weight: medium` from the same measurement
22
22
  // (its 8 rows read 14px/20px/500) — shared by every menu that renders one,
23
23
  // not just the operator list, since crisp's menu-item typography was
24
24
  // previously unset rather than wrong.
25
+ //
26
+ // #593 correction: `.menu--op` originally carried a fixed `min-width: 134px`
27
+ // (rounded from one live measurement, the 8-op text set at 135px). Adding
28
+ // number/date columns' own shorter operator sets and re-measuring them live
29
+ // (104.86px for 6 number ops, 91.16px for 6 date ops — both narrower than
30
+ // 134px) showed that number wasn't a real Attio constant, just one set's own
31
+ // content width: a floor sized for the text set overshoots the other two.
32
+ // Dropped to `min-width: 0` so every op set sizes to its own content, the
33
+ // same as any other menu here without an explicit floor.
25
34
  export const toolbarChromeHead = (p) => ` & .${CLASS_PREFIX}${p}-toolbar { display: flex; align-items: center; gap: ${c.space["2"]}; padding: 0 ${c.space["3"]} ${c.space["2"]}; }
26
35
  & .${CLASS_PREFIX}${p}-toolbar[data-inline] { padding-bottom: 0; }
27
36
  & .${CLASS_PREFIX}${p}-search { display: flex; align-items: center; gap: ${c.space["1.5"]}; height: ${c.size.row}; padding: 0 ${c.space["2.5"]}; border: none; border-radius: ${c.radius.md}; background: ${c.bgSurface}; box-shadow: inset 0 0 0 1px ${c.borderSubtle}; color: ${c.fgMuted}; }
@@ -73,7 +82,7 @@ export const toolbarChromeBody = (p) => ` & .${CLASS_PREFIX}${p}-menu-head {
73
82
  & .${CLASS_PREFIX}${p}-menu--right { left: auto; right: 0; }
74
83
  & .${CLASS_PREFIX}${p}-menu--fixed { position: fixed; top: auto; left: auto; z-index: 40; }
75
84
  & .${CLASS_PREFIX}${p}-menu--hdr { min-width: 200px; }
76
- & .${CLASS_PREFIX}${p}-menu--op { min-width: 134px; }
85
+ & .${CLASS_PREFIX}${p}-menu--op { min-width: 0; }
77
86
  & .${CLASS_PREFIX}${p}-menu-item--danger { color: ${c.bgDanger}; }
78
87
  & .${CLASS_PREFIX}${p}-menu-item--danger svg { color: ${c.bgDanger}; }
79
88
  & .${CLASS_PREFIX}${p}-menu-item--danger:hover { background: color-mix(in srgb, ${c.bgDanger} 10%, transparent); }