@crisp-ui-kit/crisp 0.54.10 → 0.55.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 (77) hide show
  1. package/dist/cjs/components/datatable/datatable.js +249 -46
  2. package/dist/cjs/components/datatable/datatable.recipe.js +24 -0
  3. package/dist/cjs/components/resizablepanel/resizablepanel.js +10 -1
  4. package/dist/cjs/components/table/table.js +8 -1
  5. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +25 -2
  6. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +176 -43
  7. package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +28 -9
  8. package/dist/cjs/index.js +0 -2
  9. package/dist/cjs/product/recordpage/column.js +19 -0
  10. package/dist/cjs/product/recordpage/index.js +6 -1
  11. package/dist/cjs/product/recordpage/recordpage.js +25 -8
  12. package/dist/cjs/product/recordpage/test-fixtures.js +55 -0
  13. package/dist/cjs/product/savedviews/savedviews.recipe.js +13 -11
  14. package/dist/datatable.css +14 -0
  15. package/dist/datatable.layered.css +14 -0
  16. package/dist/esm/components/datatable/datatable.js +250 -47
  17. package/dist/esm/components/datatable/datatable.recipe.js +24 -0
  18. package/dist/esm/components/resizablepanel/resizablepanel.js +10 -1
  19. package/dist/esm/components/table/table.js +8 -1
  20. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +25 -2
  21. package/dist/esm/components/tabletoolbar/tabletoolbar.js +177 -44
  22. package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +28 -9
  23. package/dist/esm/index.js +0 -2
  24. package/dist/esm/product/recordpage/column.js +16 -0
  25. package/dist/esm/product/recordpage/index.js +2 -0
  26. package/dist/esm/product/recordpage/recordpage.js +22 -5
  27. package/dist/esm/product/recordpage/test-fixtures.js +52 -0
  28. package/dist/esm/product/savedviews/savedviews.recipe.js +13 -11
  29. package/dist/savedviews.css +6 -18
  30. package/dist/savedviews.layered.css +6 -18
  31. package/dist/styles.css +43 -276
  32. package/dist/styles.layered.css +43 -276
  33. package/dist/tabletoolbar.css +23 -3
  34. package/dist/tabletoolbar.layered.css +23 -3
  35. package/dist/types/components/datatable/datatable.d.ts +30 -3
  36. package/dist/types/components/table/table.d.ts +14 -0
  37. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +26 -1
  38. package/dist/types/index.d.ts +0 -2
  39. package/dist/types/product/recordpage/column.d.ts +112 -0
  40. package/dist/types/product/recordpage/index.d.ts +2 -0
  41. package/dist/types/product/recordpage/recordpage.d.ts +1 -1
  42. package/dist/types/product/recordpage/test-fixtures.d.ts +3 -0
  43. package/dist/types/product/recordpanel/recordpanel.d.ts +1 -1
  44. package/package.json +2 -12
  45. package/dist/cjs/product/recordstable/company-logos.js +0 -29
  46. package/dist/cjs/product/recordstable/index.js +0 -13
  47. package/dist/cjs/product/recordstable/recordstable.js +0 -1357
  48. package/dist/cjs/product/recordstable/recordstable.recipe.js +0 -175
  49. package/dist/cjs/product/recordstable/recordstable.tag.js +0 -26
  50. package/dist/cjs/product/taskstable/index.js +0 -7
  51. package/dist/cjs/product/taskstable/taskstable.js +0 -27
  52. package/dist/cjs/product/taskstable/taskstable.recipe.js +0 -56
  53. package/dist/esm/product/recordstable/company-logos.js +0 -26
  54. package/dist/esm/product/recordstable/index.js +0 -3
  55. package/dist/esm/product/recordstable/recordstable.js +0 -1317
  56. package/dist/esm/product/recordstable/recordstable.recipe.js +0 -172
  57. package/dist/esm/product/recordstable/recordstable.tag.js +0 -23
  58. package/dist/esm/product/taskstable/index.js +0 -2
  59. package/dist/esm/product/taskstable/taskstable.js +0 -24
  60. package/dist/esm/product/taskstable/taskstable.recipe.js +0 -53
  61. package/dist/recordstable.css +0 -223
  62. package/dist/recordstable.d.ts +0 -7
  63. package/dist/recordstable.layered.css +0 -225
  64. package/dist/taskstable.css +0 -30
  65. package/dist/taskstable.d.ts +0 -7
  66. package/dist/taskstable.layered.css +0 -32
  67. package/dist/types/product/recordstable/company-logos.d.ts +0 -1
  68. package/dist/types/product/recordstable/index.d.ts +0 -3
  69. package/dist/types/product/recordstable/recordstable.d.ts +0 -289
  70. package/dist/types/product/recordstable/recordstable.recipe.d.ts +0 -5
  71. package/dist/types/product/recordstable/recordstable.tag.d.ts +0 -15
  72. package/dist/types/product/taskstable/index.d.ts +0 -2
  73. package/dist/types/product/taskstable/taskstable.d.ts +0 -54
  74. package/dist/types/product/taskstable/taskstable.recipe.d.ts +0 -3
  75. /package/dist/cjs/product/{recordstable → recordpage}/editable-field.js +0 -0
  76. /package/dist/esm/product/{recordstable → recordpage}/editable-field.js +0 -0
  77. /package/dist/types/product/{recordstable → recordpage}/editable-field.d.ts +0 -0
@@ -752,6 +752,10 @@
752
752
  & th[data-drop-after]::after { inset-inline-end: -1.5px; }
753
753
  /* typed cells — entity (avatar + name), colour-coded tags, numbers, dates */
754
754
  & .crisp-datatable-entity { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; color: var(--crisp-fg-primary); font-weight: var(--crisp-weight-medium); }
755
+ /* crisp/#601 supersession follow-up -- the same flex-row shape .crisp-datatable-entity gives its own avatar+name+actions, but structural only (no entity-specific colour/weight): lets onOpenComments/onOpenPreview compose alongside ANY column's own
756
+ content (a custom render, or a non-entity built-in type), not just
757
+ type: "entity"'s own inline rendering. */
758
+ & .crisp-datatable-cell-actions-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; width: 100%; }
755
759
  /* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text, plain hover vs rest) that Attio's underline is unconditional, not a
756
760
  hover reveal -- identical at rest and on hover: text-decoration-color
757
761
  is rgba(0,0,0,0.09), a 9% tint, not the name's own full-contrast text colour. The previous :hover-gated, full-contrast rule here was itself unmeasured and wrong in two ways at once. */
@@ -783,6 +787,16 @@
783
787
  /* url/email cell types (#654) -- same measured values as RecordsTable's own .crisp-recordstable-link, which this mirrors: no underline at rest, underline on hover, own-colour text rather than a browser-blue link. */
784
788
  & .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
785
789
  & .crisp-datatable-link:hover { text-decoration: underline; }
790
+ /* rating cell type/editor (#760) -- measured live: 16px stars on an 18px pitch (a 2px gap), an empty star at rgba(0,0,0,0.1), a committed/filled star at brand600 (--crisp-bg-brand-solid, an exact match to the measured #266df0), and a distinct hover-preview colour -- rgb(33,91,196) -- that's close to but NOT brand700/bgBrandSolidPressed
791
+ (#1f5fd6); kept as its own literal rather than forced onto that token,
792
+ since the two were measured stable and different. The read-only svg
793
+ and the editable button's own inner svg both carry the crisp-datatable-rating-star class on the svg itself (not the button), so one set of fill rules covers both -- the button only adds its own reset + cursor via a separate -btn class. */
794
+ & .crisp-datatable-rating { display: inline-flex; align-items: center; gap: 2px; }
795
+ & .crisp-datatable-rating-star { display: block; }
796
+ & .crisp-datatable-rating-star path { fill: rgba(0, 0, 0, 0.1); }
797
+ & .crisp-datatable-rating-star[data-filled] path { fill: var(--crisp-bg-brand-solid); }
798
+ & .crisp-datatable-rating-star[data-hovering] path { fill: #215bc4; }
799
+ & .crisp-datatable-rating-star-btn { display: inline-flex; padding: 0; margin: 0; border: none; background: none; font-family: inherit; cursor: pointer; }
786
800
  /* row drag-to-reorder -- a Settings > Objects > Attributes screen measures a leading 20px grip column, a 16px grip icon, and the row's own
787
801
  hairline doubling as the drop indicator (it tints toward the brand
788
802
  colour as the active drop target). The affordance + geometry are
@@ -1828,12 +1842,29 @@
1828
1842
  & .crisp-tabletoolbar-search svg { flex-shrink: 0; }
1829
1843
  & .crisp-tabletoolbar-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
1830
1844
  & .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
1831
- & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
1845
+ & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
1832
1846
  & .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
1833
1847
  & .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
1834
- & .crisp-tabletoolbar-tool--active { background: var(--crisp-bg-raised); }
1848
+ /* crisp/#772: re-measured live on Sort with an actual sort applied -- an active trigger's own fill is white (bgSurface), the same as the
1849
+ base .tool rule above now already sets; this override existed to
1850
+ distinguish active from a base state that used to be transparent.
1851
+ Kept explicit (not just deleted) so a future change to the base
1852
+ rule's background can't silently change this one too. */
1853
+ & .crisp-tabletoolbar-tool--active { background: var(--crisp-bg-surface); }
1835
1854
  & .crisp-tabletoolbar-tool--ghost { box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 3%, transparent); color: var(--crisp-fg-muted); }
1836
1855
  & .crisp-tabletoolbar-tool--ghost:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
1856
+ /* crisp/#772 follow-up, re-measured live 2026-09-25: an EMPTY Sort/Filter
1857
+ trigger (no sort/condition set) isn't a solid-ring chip at all -- it's
1858
+ a dashed ::before (1px dashed, border-radius: inherit, absolutely
1859
+ positioned inset: 0) over a barely-there fill, confirmed on Attio's own empty Filter chip (its ::before border computes to exactly "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger drops the dashed pseudo and picks up the base tool's own solid ring
1860
+ instead (the --active modifier, unchanged) -- confirmed on Sort with
1861
+ an actual sort applied. color-mix (not the raw rgba Attio computes
1862
+ to) so both the border and the fill flip correctly in dark mode, the
1863
+ same reasoning --ghost above already uses. Only wired into
1864
+ TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. */
1865
+ & .crisp-tabletoolbar-tool--dashed { position: relative; box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
1866
+ & .crisp-tabletoolbar-tool--dashed::before { content: ""; position: absolute; inset: 0; border-radius: inherit; border: 1px dashed color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); pointer-events: none; }
1867
+ & .crisp-tabletoolbar-tool--dashed:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
1837
1868
  & .crisp-tabletoolbar-toolgroup { position: relative; display: inline-flex; }
1838
1869
  & .crisp-tabletoolbar-divider { flex-shrink: 0; width: 1px; height: 20px; background: var(--crisp-border-subtle); }
1839
1870
  & .crisp-tabletoolbar-menu { position: absolute; top: calc(100% + var(--crisp-space-1)); left: 0; z-index: 30; min-width: 232px; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); display: flex; flex-direction: column; gap: var(--crisp-space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
@@ -1943,7 +1974,10 @@
1943
1974
  & .crisp-tabletoolbar-datepop-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
1944
1975
  & .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
1945
1976
 
1946
- & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface-muted); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
1977
+ & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
1978
+
1979
+ & .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
1980
+ & .crisp-tabletoolbar-sorted-count { font-size: var(--crisp-text-sm); color: color-mix(in srgb, var(--crisp-fg-primary) 73%, transparent); }
1947
1981
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
1948
1982
  }
1949
1983
 
@@ -2954,230 +2988,6 @@
2954
2988
  }
2955
2989
  }
2956
2990
 
2957
- .crisp-recordstable {
2958
- box-sizing: border-box; position: relative; display: flex; flex-direction: column; min-height: 0; height: 100%; width: 100%; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
2959
- & * { box-sizing: border-box; }
2960
- /* toolbar */
2961
- & .crisp-recordstable-toolbar { display: flex; align-items: center; gap: var(--crisp-space-2); padding: 0 var(--crisp-space-3) var(--crisp-space-2); }
2962
- & .crisp-recordstable-toolbar[data-inline] { padding-bottom: 0; }
2963
- & .crisp-recordstable-search { display: flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
2964
- & .crisp-recordstable-search svg { flex-shrink: 0; }
2965
- & .crisp-recordstable-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
2966
- & .crisp-recordstable-search input::placeholder { color: var(--crisp-fg-muted); }
2967
- & .crisp-recordstable-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
2968
- & .crisp-recordstable-tool:hover { background: var(--crisp-bg-raised); }
2969
- & .crisp-recordstable-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
2970
- & .crisp-recordstable-tool--active { background: var(--crisp-bg-raised); }
2971
- & .crisp-recordstable-tool--ghost { box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 3%, transparent); color: var(--crisp-fg-muted); }
2972
- & .crisp-recordstable-tool--ghost:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
2973
- & .crisp-recordstable-toolgroup { position: relative; display: inline-flex; }
2974
- & .crisp-recordstable-divider { flex-shrink: 0; width: 1px; height: 20px; background: var(--crisp-border-subtle); }
2975
- & .crisp-recordstable-menu { position: absolute; top: calc(100% + var(--crisp-space-1)); left: 0; z-index: 30; min-width: 232px; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); display: flex; flex-direction: column; gap: var(--crisp-space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
2976
- & .crisp-recordstable-menu { @starting-style { opacity: 0; transform: scale(0.96); } }
2977
- & .crisp-recordstable-ctx { z-index: 60; }
2978
- & .crisp-recordstable-th[data-drop] { box-shadow: inset 2px 0 0 var(--crisp-bg-brand-solid); }
2979
- & .crisp-recordstable-th-inner[draggable="true"]:active { cursor: grabbing; }
2980
- & .crisp-recordstable-menu-head { padding: var(--crisp-space-1) var(--crisp-space-2) var(--crisp-space-0-5); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
2981
- & .crisp-recordstable-sortpop { min-width: 480px; overflow: visible; padding: var(--crisp-space-3) var(--crisp-space-1-5); gap: var(--crisp-space-2); }
2982
- & .crisp-recordstable-sort-empty { padding: var(--crisp-space-1) var(--crisp-space-1) var(--crisp-space-2); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
2983
- & .crisp-recordstable-sort-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); }
2984
- & .crisp-recordstable-sort-grip { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 28px; flex-shrink: 0; margin-right: calc(-1 * var(--crisp-space-1)); padding: 0; border: none; background: none; color: var(--crisp-fg-muted); cursor: grab; }
2985
- & .crisp-recordstable-sort-grip:active { cursor: grabbing; }
2986
- & .crisp-recordstable-sort-grip:hover { color: var(--crisp-fg-primary); }
2987
- & .crisp-recordstable-sort-optlabel { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
2988
- & .crisp-recordstable-sort-optlabel svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
2989
- & .crisp-recordstable-sort-field { flex: 1; min-width: 0; }
2990
- & .crisp-recordstable-sort-dir { width: 136px; flex-shrink: 0; }
2991
- & .crisp-recordstable-sort-field .crisp-select-trigger, & .crisp-recordstable-sort-dir .crisp-select-trigger { height: 28px; padding-right: var(--crisp-space-1); }
2992
- & .crisp-recordstable-sort-remove { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); cursor: pointer; transition: background-color .12s, color .12s; }
2993
- & .crisp-recordstable-sort-remove:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
2994
- & .crisp-recordstable-sort-addrow { display: flex; padding: var(--crisp-space-0-5) 0; }
2995
- & .crisp-recordstable-sort-add { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s; }
2996
- & .crisp-recordstable-sort-add:hover { background: var(--crisp-bg-raised); }
2997
- & .crisp-recordstable-sort-add svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
2998
- & .crisp-recordstable-sort-foot { display: flex; padding: var(--crisp-space-1-5) var(--crisp-space-1) var(--crisp-space-0-5); }
2999
- & .crisp-recordstable-sort-learn { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-lg); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); text-decoration: none; }
3000
- & .crisp-recordstable-sort-learn svg { flex-shrink: 0; }
3001
- & .crisp-recordstable-sort-learn:hover { color: var(--crisp-fg-primary); }
3002
- & .crisp-recordstable-menu-item { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: var(--crisp-size-menuRow); margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); text-align: left; text-decoration: none; cursor: pointer; }
3003
- & .crisp-recordstable-menu-item:hover { background: var(--crisp-bg-raised); }
3004
- & .crisp-recordstable-menu-item:disabled { opacity: 0.4; cursor: default; }
3005
- & .crisp-recordstable-menu-item:disabled:hover { background: none; }
3006
- & .crisp-recordstable-menu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
3007
- & .crisp-recordstable-menu-item[data-on] svg { color: var(--crisp-bg-brand-solid); }
3008
- & .crisp-recordstable-menu-item .crisp-recordstable-menu-check { margin-left: auto; }
3009
- & .crisp-recordstable-menu-input { height: var(--crisp-size-row); margin: var(--crisp-space-0-5); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); background: var(--crisp-bg-surface); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); outline: none; }
3010
- & .crisp-recordstable-menu-sep { height: 1px; border: none; background: var(--crisp-border-subtle); margin: var(--crisp-space-0-5) 0; }
3011
- /* #592: the Filter field picker's nested-scope header (back control +
3012
- search, once drilled into a nestedColumns column) and a search
3013
- result's own breadcrumb row ("Team › Twitter follower count", surfaced by the SAME query matching a nested column). menu-back reuses the established 28px icon-only control pattern this file already uses twice (sort-remove, the kebab segment) rather than an independent measurement of Attio's own back arrow. The breadcrumb
3014
- colours ARE measured live: the parent segment muted at the same
3015
- exact color-mix 63% sort-learn above already uses, the
3016
- separator chevron and leaf segment both full fgPrimary (the
3017
- generic menu-item svg rule below defaults every icon to
3018
- fgMuted, so the separator needs its own override to read
3019
- correctly here). */
3020
- & .crisp-recordstable-menu-nesthead { display: flex; align-items: center; gap: var(--crisp-space-1); margin: var(--crisp-space-0-5); }
3021
- & .crisp-recordstable-menu-nesthead .crisp-recordstable-menu-input { flex: 1; margin: 0; }
3022
- & .crisp-recordstable-menu-back { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); cursor: pointer; }
3023
- & .crisp-recordstable-menu-back:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
3024
- & .crisp-recordstable-menu-item--expand { justify-content: space-between; }
3025
- & .crisp-recordstable-menu-item-path { display: inline-flex; align-items: center; gap: 2px; min-width: 0; overflow: hidden; }
3026
- & .crisp-recordstable-menu-item-path-parent { flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; max-width: 100px; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
3027
- & .crisp-recordstable-menu-item-path-sep { flex-shrink: 0; color: var(--crisp-fg-primary); }
3028
- & .crisp-recordstable-menu-item-path > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3029
- & .crisp-recordstable-menu--up { top: auto; bottom: calc(100% + var(--crisp-space-1)); transform-origin: bottom; }
3030
- & .crisp-recordstable-menu--right { left: auto; right: 0; }
3031
- & .crisp-recordstable-menu--fixed { position: fixed; top: auto; left: auto; z-index: 40; }
3032
- & .crisp-recordstable-menu--hdr { min-width: 200px; }
3033
- & .crisp-recordstable-menu--op { min-width: 0; }
3034
- & .crisp-recordstable-menu-item--danger { color: var(--crisp-bg-danger); }
3035
- & .crisp-recordstable-menu-item--danger svg { color: var(--crisp-bg-danger); }
3036
- & .crisp-recordstable-menu-item--danger:hover { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
3037
- & .crisp-recordstable-menu-check { margin-left: auto; color: var(--crisp-bg-brand-solid); }
3038
- & .crisp-recordstable-fchip { display: inline-flex; align-items: center; height: var(--crisp-size-row); padding-right: var(--crisp-space-1); border-radius: var(--crisp-radius-md); box-shadow: inset 0 0 0 1px var(--crisp-border-default); background: var(--crisp-bg-surface); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); white-space: nowrap; }
3039
- & .crisp-recordstable-fchip-main { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 100%; margin: 0; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2); border: none; background: none; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); cursor: pointer; }
3040
- & .crisp-recordstable-fchip-field { font-weight: var(--crisp-weight-medium); }
3041
- & .crisp-recordstable-fchip-op { color: var(--crisp-fg-muted); }
3042
- & .crisp-recordstable-fchip-val { font-weight: var(--crisp-weight-medium); max-width: 140px; overflow: hidden; text-overflow: ellipsis; }
3043
- & .crisp-recordstable-fchip-x { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); cursor: pointer; }
3044
- & .crisp-recordstable-fchip-x:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
3045
- & .crisp-recordstable-spacer { flex: 1; }
3046
- & .crisp-recordstable-count { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
3047
- & .crisp-recordstable-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; transition: background-color .12s; }
3048
- & .crisp-recordstable-new:hover { background: var(--crisp-bg-brand-solid-pressed); }
3049
-
3050
- /* scroll frame + table */
3051
- & .crisp-recordstable-scroll { flex: 1; min-height: 0; overflow: auto; background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--crisp-fg-primary) 22%, transparent) transparent; }
3052
- & .crisp-recordstable-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
3053
- & .crisp-recordstable-scroll::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--crisp-fg-primary) 20%, transparent); border-radius: var(--crisp-radius-full); border: 2px solid var(--crisp-bg-surface); background-clip: padding-box; }
3054
- & .crisp-recordstable-scroll::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 34%, transparent); background-clip: padding-box; }
3055
- & .crisp-recordstable-scroll::-webkit-scrollbar-corner { background: transparent; }
3056
- & .crisp-recordstable-table { table-layout: fixed; border-collapse: separate; border-spacing: 0; }
3057
- & .crisp-recordstable-th, & .crisp-recordstable-td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; white-space: nowrap; overflow: hidden; }
3058
- & .crisp-recordstable-th { position: sticky; top: 0; z-index: 2; padding: 0; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); user-select: none; }
3059
- & .crisp-recordstable-th-inner { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-align: start; cursor: pointer; }
3060
- & .crisp-recordstable-th-inner svg { flex-shrink: 0; color: color-mix(in srgb, var(--crisp-fg-primary) 45%, transparent); }
3061
- & .crisp-recordstable-th-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
3062
- & .crisp-recordstable-th-rename { width: 100%; min-width: 0; height: 100%; margin: 0; padding: 0; border: none; outline: none; background: none; color: inherit; font: inherit; letter-spacing: inherit; }
3063
- & .crisp-recordstable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
3064
- & .crisp-recordstable-sort { flex-shrink: 0; opacity: 0.4; transition: opacity .12s; color: color-mix(in srgb, var(--crisp-fg-primary) 45%, transparent); }
3065
- & .crisp-recordstable-th:hover .crisp-recordstable-sort, & .crisp-recordstable-th[data-sorted] .crisp-recordstable-sort { opacity: 1; }
3066
- & .crisp-recordstable-th[data-sorted="desc"] .crisp-recordstable-sort svg { transform: rotate(180deg); }
3067
-
3068
- /* column resize handle */
3069
- & .crisp-recordstable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
3070
- & .crisp-recordstable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: var(--crisp-bg-brand-solid); opacity: 0; transition: opacity .12s; }
3071
- & .crisp-recordstable-resize:hover::after, & .crisp-recordstable-resize[data-resizing]::after { opacity: 1; }
3072
-
3073
- /* add-column header */
3074
- & .crisp-recordstable-addcol { min-width: 44px; }
3075
- & .crisp-recordstable-addcol button { display: flex; align-items: center; justify-content: center; width: 44px; height: 100%; border: none; background: none; color: var(--crisp-fg-muted); cursor: pointer; }
3076
- & .crisp-recordstable-addcol button:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
3077
-
3078
- /* cells */
3079
- /* font-weight is explicit because the first cell of each row is a
3080
- th[scope=row] — the record's name is what the row IS — and a th defaults to bold. Measured before the change and unchanged after: 400. */
3081
- & .crisp-recordstable-td { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); cursor: default; }
3082
- & .crisp-recordstable-td--editable { cursor: text; }
3083
- /* keyboard/click cell selection (spreadsheet-style) */
3084
- & .crisp-recordstable-td[data-selected] { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: -2px; border-radius: var(--crisp-radius-sm); z-index: 3; }
3085
- & .crisp-recordstable-scroll:focus { outline: none; }
3086
- /* picker cells (status / date / reference) host a ghost control edge-to-edge */
3087
- & .crisp-recordstable-td--picker { padding: 0; }
3088
- & .crisp-recordstable-td--picker .crisp-select-trigger, & .crisp-recordstable-td--picker .crisp-datepicker-trigger, & .crisp-recordstable-td--picker .crisp-multiselect-trigger { width: 100%; height: 100%; min-height: 0; border-radius: 0; box-shadow: none; padding: 0 var(--crisp-space-2); }
3089
- & .crisp-recordstable-td--picker .crisp-multiselect-trigger:hover { background: none; }
3090
- & .crisp-recordstable-td--picker .crisp-multiselect-trigger[data-open] { box-shadow: inset 0 0 0 1.5px var(--crisp-bg-brand-solid); }
3091
- /* tag cell: one compact clipped line of full chips, no chevron (opens the picker on click) */
3092
- & .crisp-recordstable-td--picker .crisp-multiselect-chips { flex-wrap: nowrap; overflow: hidden; }
3093
- & .crisp-recordstable-td--picker .crisp-multiselect-chips .crisp-recordstable-tag { flex-shrink: 0; max-width: none; }
3094
- & .crisp-recordstable-td--picker .crisp-multiselect-chevron { display: none; }
3095
- & .crisp-recordstable-td--picker .crisp-multiselect-placeholder { color: var(--crisp-fg-muted); }
3096
- /* reference picker: a leading 16px avatar per option, plus a trailing "Create X" row when the consumer supplies one (#449) -- measured live against Attio's own picker (16px circular avatar, 16px plain icon for
3097
- the create row, both sitting in the option's existing 8px gap, no new gap value invented). */
3098
- & .crisp-recordstable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
3099
- & .crisp-recordstable-refoption-avatar { flex-shrink: 0; }
3100
- & .crisp-recordstable-refoption--create { color: var(--crisp-fg-muted); }
3101
- & .crisp-recordstable-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
3102
- & .crisp-recordstable-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
3103
- & .crisp-recordstable-cell { display: flex; align-items: center; gap: var(--crisp-space-2); height: 100%; min-width: 0; }
3104
- & .crisp-recordstable-cell--num { justify-content: flex-end; font-variant-numeric: tabular-nums; }
3105
- & .crisp-recordstable-cell--tags { gap: var(--crisp-space-1); }
3106
- & .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); }
3107
- & .crisp-recordstable-tag[data-tone="brand"] { 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)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-brand-solid) 30%, transparent); }
3108
- & .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-success) 30%, transparent); }
3109
- & .crisp-recordstable-tag[data-tone="warning"] { background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-warning) 30%, transparent); }
3110
- & .crisp-recordstable-tag[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-danger) 30%, transparent); }
3111
- & .crisp-recordstable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-purple) 30%, transparent); }
3112
- & .crisp-recordstable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-cyan) 30%, transparent); }
3113
- & .crisp-recordstable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent); }
3114
- & .crisp-recordstable-muted { color: var(--crisp-fg-muted); }
3115
- & .crisp-recordstable-entity { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; color: var(--crisp-fg-primary); font-weight: var(--crisp-weight-medium); text-decoration: none; }
3116
- & .crisp-recordstable-entity:hover .crisp-recordstable-entity-name { text-decoration: underline; }
3117
- & .crisp-recordstable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3118
- & button.crisp-recordstable-entity-name--link { margin: 0; padding: 0; border: none; background: none; font: inherit; color: inherit; letter-spacing: inherit; text-align: start; cursor: pointer; max-width: 100%; }
3119
- & .crisp-recordstable-fav { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; object-fit: cover; background: var(--crisp-bg-raised); }
3120
- & .crisp-recordstable-open { position: absolute; inset-inline-end: var(--crisp-space-1); top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; opacity: 0; transition: opacity .12s, background-color .12s; z-index: 3; }
3121
- & .crisp-recordstable-open:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
3122
- & tbody tr:hover .crisp-recordstable-open { opacity: 1; }
3123
- & .crisp-recordstable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
3124
- & .crisp-recordstable-link:hover { text-decoration: underline; }
3125
- /* inline edit input */
3126
- & .crisp-recordstable-edit { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: -2px; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); z-index: 5; }
3127
- & .crisp-recordstable-edit--num { text-align: end; font-variant-numeric: tabular-nums; }
3128
- /* selection / hover / sticky */
3129
- & .crisp-recordstable-col-check { width: 40px; min-width: 40px; padding: 0; }
3130
- & .crisp-recordstable-check-inner { display: flex; align-items: center; justify-content: center; height: 100%; }
3131
- & .crisp-recordstable-col-check, & .crisp-recordstable-col-entity { position: sticky; z-index: 3; background: var(--crisp-bg-surface); }
3132
- /* The sticky pin is a LOGICAL offset: with physical `left` these columns were not pinned at all under RTL -- scrolled, they left the viewport entirely (measured: viewport 13..773, check column at x=1333). Nothing in JS measures these, so converting them is safe; the two properties below that have no logical form get an explicit RTL rule rather than being left to point the wrong way. */
3133
- & .crisp-recordstable-col-check { inset-inline-start: 0; }
3134
- & .crisp-recordstable-col-entity { inset-inline-start: 40px; clip-path: inset(0 -38px 0 0); transition: box-shadow .2s ease; }
3135
- [dir="rtl"] & .crisp-recordstable-col-entity { clip-path: inset(0 0 0 -38px); }
3136
- & thead .crisp-recordstable-col-check, & thead .crisp-recordstable-col-entity { z-index: 4; }
3137
- /* soft shadow on the sticky column edge once the grid is scrolled horizontally */
3138
- & .crisp-recordstable-scroll[data-scrolled] .crisp-recordstable-col-entity { box-shadow: 6px 0 16px 4px rgba(0,0,0,0.12); }
3139
- /* box-shadow has no logical form either: the bleed follows the scrolled content, which is the opposite side under RTL. */
3140
- [dir="rtl"] & .crisp-recordstable-scroll[data-scrolled] .crisp-recordstable-col-entity { box-shadow: -6px 0 16px 4px rgba(0,0,0,0.12); }
3141
- /* AI-enriched values carry a purple wash. Measured live: a full-bleed overlay at #9b69ff 4% (== bgPurple), composited OVER whatever row-state background the cell already has, which is why it is an ::after and not a background. */
3142
- & .crisp-recordstable-td[data-enriched]::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: color-mix(in srgb, var(--crisp-bg-purple) 4%, transparent); }
3143
- & tbody tr:hover .crisp-recordstable-td { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
3144
- & tbody tr[data-selected] .crisp-recordstable-td { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
3145
- & tbody tr[data-selected]:hover .crisp-recordstable-td { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface))); }
3146
- & .crisp-recordstable-th:last-child, & .crisp-recordstable-td:last-child { border-inline-end: none; }
3147
- /* add-row footer */
3148
- & .crisp-recordstable-addrow { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); border: none; border-top: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); cursor: pointer; }
3149
- & .crisp-recordstable-addrow:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
3150
- /* zero-row empty state — centred in the body region (headers + summary stay) */
3151
- & .crisp-recordstable-empty { display: flex; align-items: center; justify-content: center; min-height: 320px; padding: var(--crisp-space-8) var(--crisp-space-4); }
3152
- /* summary footer — per-column aggregation, sticky to the bottom */
3153
- & .crisp-recordstable-sum { position: sticky; bottom: 0; z-index: 2; height: var(--crisp-size-tableRow); padding: 0; border-top: 1px solid var(--crisp-border-subtle); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); }
3154
- & tfoot .crisp-recordstable-col-check, & tfoot .crisp-recordstable-col-entity { position: sticky; bottom: 0; z-index: 3; }
3155
- & .crisp-recordstable-sum:last-child { border-inline-end: none; }
3156
- & .crisp-recordstable-sum-btn { display: flex; align-items: center; justify-content: flex-end; gap: var(--crisp-space-1-5); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: none; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); cursor: pointer; white-space: nowrap; overflow: hidden; }
3157
- & .crisp-recordstable-sum-btn:hover { background: var(--crisp-bg-raised); }
3158
- & .crisp-recordstable-sum-label { color: color-mix(in srgb, var(--crisp-fg-primary) 45%, transparent); text-transform: capitalize; }
3159
- & .crisp-recordstable-sum-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; }
3160
- & .crisp-recordstable-sumgroup { width: 100%; height: 100%; }
3161
- & .crisp-recordstable-pin { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); color: var(--crisp-bg-warning); fill: color-mix(in srgb, var(--crisp-bg-warning) 35%, transparent); }
3162
- & .crisp-recordstable-sum-btn[data-empty] { opacity: 0; justify-content: flex-start; }
3163
- & .crisp-recordstable-sum-btn[data-empty]:hover { opacity: 1; }
3164
- /* bulk action bar lives in its own component now — see components/bulkbar */
3165
- & .crisp-recordstable-bulk-sep { width: 1px; height: 20px; margin: 0 var(--crisp-space-0-5); background: var(--crisp-border-subtle); }
3166
- & .crisp-recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); cursor: pointer; }
3167
- & .crisp-recordstable-bulk-close:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
3168
- /* announced, never drawn */
3169
- & .crisp-recordstable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
3170
- [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
3171
- }
3172
-
3173
- @media (prefers-reduced-motion: reduce) {
3174
- .crisp-recordstable, .crisp-recordstable * {
3175
- animation-duration: 0.01ms !important;
3176
- animation-iteration-count: 1 !important;
3177
- transition-duration: 0.01ms !important;
3178
- }
3179
- }
3180
-
3181
2991
  .crisp-richtext {
3182
2992
  display: flex; flex-direction: column; box-sizing: border-box; font-family: var(--crisp-font-sans); color: var(--crisp-fg-primary); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
3183
2993
  & .crisp-rte-title { font-size: 32px; line-height: 36px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.6px; color: var(--crisp-fg-primary); outline: none; }
@@ -3322,24 +3132,12 @@
3322
3132
  }
3323
3133
 
3324
3134
  .crisp-savedviews {
3325
- position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; /* Trigger fill measured rgb(246,247,247); bgRaised's light value is
3326
- #f4f4f5 (244,244,245) — a 2-unit-per-channel difference, inside
3327
- screenshot/anti-aliasing noise, not a second real colour. Reusing the
3328
- token (Lesson 3 — tokens, not raw px/hex) gets a correct,
3329
- already-established dark-mode fill for free instead of a light-only
3330
- literal; AUTHORING.md Lesson 29 is the case where that shortcut went
3331
- wrong (a flat colour that stayed visible where the reference had
3332
- none) — this is the opposite risk (a token that already flips per
3333
- theme, applied to the closest measured match). */
3334
- & .crisp-savedviews-trigger {
3335
- box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5);
3336
- height: var(--crisp-size-row); margin: 0; padding: var(--crisp-space-1) var(--crisp-space-1-5);
3337
- border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-raised);
3338
- font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary);
3339
- cursor: pointer; white-space: nowrap; transition: background-color .12s ease;
3340
- }
3341
- & .crisp-savedviews-trigger:hover,
3342
- & .crisp-savedviews-trigger[data-open] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-raised)); }
3135
+ position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; /* crisp/#772 follow-up, re-measured live 2026-09-25 in the trigger's
3136
+ actual position (Attio's real view bar, next to View settings -- fixed there in #766/#768/#778): white (bgSurface, rgb(255,255,255) exact) with elevation.field's 3-layer shadow, the same raised
3137
+ chrome View settings and Import/Export both carry
3138
+ (tabletoolbar.recipe.ts's own --raised, not reused here directly since this is a separate recipe/component, but the identical measured values). Supersedes the original #555 measurement (rgb(246,247,247), reused as bgRaised -- a flat grey fill with no shadow at all), which was wrong: this trigger was never re-checked once it moved into its real view-bar position. */
3139
+ & .crisp-savedviews-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: var(--crisp-space-1) var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); cursor: pointer; white-space: nowrap; transition: background-color .12s ease; }
3140
+ & .crisp-savedviews-trigger:hover, & .crisp-savedviews-trigger[data-open] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
3343
3141
  & .crisp-savedviews-trigger-icon { flex-shrink: 0; display: inline-flex; width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
3344
3142
  & .crisp-savedviews-trigger-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
3345
3143
  & .crisp-savedviews-trigger-chevron { flex-shrink: 0; color: var(--crisp-fg-muted); }
@@ -3480,37 +3278,6 @@
3480
3278
  }
3481
3279
  }
3482
3280
 
3483
- .crisp-taskstable {
3484
- display: flex; flex-direction: column; min-height: 0; box-sizing: border-box; font-family: var(--crisp-font-sans); color: var(--crisp-fg-primary); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
3485
- & .crisp-taskstable-colhead { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-height: 49px; max-height: 49px; padding: var(--crisp-space-2-5) var(--crisp-space-3); box-shadow: inset 0 -1px 0 var(--crisp-border-subtle); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
3486
- & .crisp-taskstable-colhead-cell { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
3487
- & .crisp-taskstable-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); }
3488
- /* #642: measured live -- title, due date and assignee name are ALL 14px/500 on Attio's own Tasks page. Only -title/-due set their own
3489
- font-size (and only -title its own weight), so an unstyled consumer
3490
- slot (a plain PersonChip/RecordChip name span with no font-size of
3491
- its own) fell through to the browser/body default, 16px/400. Set
3492
- the ambient font here so it cascades to any slot content that
3493
- doesn't override it -- -title/-due's own declarations still apply,
3494
- unchanged, they're just now redundant with this baseline rather than the only source of it. */
3495
- & .crisp-taskstable-cell { display: flex; align-items: center; min-width: 0; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); }
3496
- & .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: var(--crisp-radius-full); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s; }
3497
- & .crisp-taskstable-check:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 30%, transparent); }
3498
- & .crisp-taskstable-check:checked { background: var(--crisp-bg-brand-solid) 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"); }
3499
- & .crisp-taskstable-check:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
3500
- & .crisp-taskstable-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
3501
- & .crisp-taskstable-due { font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); white-space: nowrap; }
3502
- & .crisp-taskstable-due[data-overdue] { color: var(--crisp-fg-danger); }
3503
- & .crisp-taskstable-empty { padding: var(--crisp-space-8) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
3504
- }
3505
-
3506
- @media (prefers-reduced-motion: reduce) {
3507
- .crisp-taskstable, .crisp-taskstable * {
3508
- animation-duration: 0.01ms !important;
3509
- animation-iteration-count: 1 !important;
3510
- transition-duration: 0.01ms !important;
3511
- }
3512
- }
3513
-
3514
3281
  .crisp-themepicker {
3515
3282
  display: flex; gap: var(--crisp-space-2); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
3516
3283
  & .crisp-themepicker-option { box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); width: 224px; padding: var(--crisp-space-1); border: 1px solid var(--crisp-border-subtle); border-radius: 16px; background: var(--crisp-bg-surface); cursor: pointer; font-family: inherit; }
@@ -7,12 +7,29 @@
7
7
  & .crisp-tabletoolbar-search svg { flex-shrink: 0; }
8
8
  & .crisp-tabletoolbar-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
9
9
  & .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
10
- & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
10
+ & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
11
11
  & .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
12
12
  & .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
13
- & .crisp-tabletoolbar-tool--active { background: var(--crisp-bg-raised); }
13
+ /* crisp/#772: re-measured live on Sort with an actual sort applied -- an active trigger's own fill is white (bgSurface), the same as the
14
+ base .tool rule above now already sets; this override existed to
15
+ distinguish active from a base state that used to be transparent.
16
+ Kept explicit (not just deleted) so a future change to the base
17
+ rule's background can't silently change this one too. */
18
+ & .crisp-tabletoolbar-tool--active { background: var(--crisp-bg-surface); }
14
19
  & .crisp-tabletoolbar-tool--ghost { box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 3%, transparent); color: var(--crisp-fg-muted); }
15
20
  & .crisp-tabletoolbar-tool--ghost:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
21
+ /* crisp/#772 follow-up, re-measured live 2026-09-25: an EMPTY Sort/Filter
22
+ trigger (no sort/condition set) isn't a solid-ring chip at all -- it's
23
+ a dashed ::before (1px dashed, border-radius: inherit, absolutely
24
+ positioned inset: 0) over a barely-there fill, confirmed on Attio's own empty Filter chip (its ::before border computes to exactly "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger drops the dashed pseudo and picks up the base tool's own solid ring
25
+ instead (the --active modifier, unchanged) -- confirmed on Sort with
26
+ an actual sort applied. color-mix (not the raw rgba Attio computes
27
+ to) so both the border and the fill flip correctly in dark mode, the
28
+ same reasoning --ghost above already uses. Only wired into
29
+ TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. */
30
+ & .crisp-tabletoolbar-tool--dashed { position: relative; box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
31
+ & .crisp-tabletoolbar-tool--dashed::before { content: ""; position: absolute; inset: 0; border-radius: inherit; border: 1px dashed color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); pointer-events: none; }
32
+ & .crisp-tabletoolbar-tool--dashed:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
16
33
  & .crisp-tabletoolbar-toolgroup { position: relative; display: inline-flex; }
17
34
  & .crisp-tabletoolbar-divider { flex-shrink: 0; width: 1px; height: 20px; background: var(--crisp-border-subtle); }
18
35
  & .crisp-tabletoolbar-menu { position: absolute; top: calc(100% + var(--crisp-space-1)); left: 0; z-index: 30; min-width: 232px; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); display: flex; flex-direction: column; gap: var(--crisp-space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
@@ -122,7 +139,10 @@
122
139
  & .crisp-tabletoolbar-datepop-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
123
140
  & .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
124
141
 
125
- & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface-muted); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
142
+ & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
143
+
144
+ & .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
145
+ & .crisp-tabletoolbar-sorted-count { font-size: var(--crisp-text-sm); color: color-mix(in srgb, var(--crisp-fg-primary) 73%, transparent); }
126
146
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
127
147
  }
128
148
 
@@ -8,12 +8,29 @@
8
8
  & .crisp-tabletoolbar-search svg { flex-shrink: 0; }
9
9
  & .crisp-tabletoolbar-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
10
10
  & .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
11
- & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
11
+ & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
12
12
  & .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
13
13
  & .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
14
- & .crisp-tabletoolbar-tool--active { background: var(--crisp-bg-raised); }
14
+ /* crisp/#772: re-measured live on Sort with an actual sort applied -- an active trigger's own fill is white (bgSurface), the same as the
15
+ base .tool rule above now already sets; this override existed to
16
+ distinguish active from a base state that used to be transparent.
17
+ Kept explicit (not just deleted) so a future change to the base
18
+ rule's background can't silently change this one too. */
19
+ & .crisp-tabletoolbar-tool--active { background: var(--crisp-bg-surface); }
15
20
  & .crisp-tabletoolbar-tool--ghost { box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 3%, transparent); color: var(--crisp-fg-muted); }
16
21
  & .crisp-tabletoolbar-tool--ghost:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
22
+ /* crisp/#772 follow-up, re-measured live 2026-09-25: an EMPTY Sort/Filter
23
+ trigger (no sort/condition set) isn't a solid-ring chip at all -- it's
24
+ a dashed ::before (1px dashed, border-radius: inherit, absolutely
25
+ positioned inset: 0) over a barely-there fill, confirmed on Attio's own empty Filter chip (its ::before border computes to exactly "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger drops the dashed pseudo and picks up the base tool's own solid ring
26
+ instead (the --active modifier, unchanged) -- confirmed on Sort with
27
+ an actual sort applied. color-mix (not the raw rgba Attio computes
28
+ to) so both the border and the fill flip correctly in dark mode, the
29
+ same reasoning --ghost above already uses. Only wired into
30
+ TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. */
31
+ & .crisp-tabletoolbar-tool--dashed { position: relative; box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
32
+ & .crisp-tabletoolbar-tool--dashed::before { content: ""; position: absolute; inset: 0; border-radius: inherit; border: 1px dashed color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); pointer-events: none; }
33
+ & .crisp-tabletoolbar-tool--dashed:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
17
34
  & .crisp-tabletoolbar-toolgroup { position: relative; display: inline-flex; }
18
35
  & .crisp-tabletoolbar-divider { flex-shrink: 0; width: 1px; height: 20px; background: var(--crisp-border-subtle); }
19
36
  & .crisp-tabletoolbar-menu { position: absolute; top: calc(100% + var(--crisp-space-1)); left: 0; z-index: 30; min-width: 232px; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); display: flex; flex-direction: column; gap: var(--crisp-space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
@@ -123,7 +140,10 @@
123
140
  & .crisp-tabletoolbar-datepop-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
124
141
  & .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
125
142
 
126
- & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface-muted); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
143
+ & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
144
+
145
+ & .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
146
+ & .crisp-tabletoolbar-sorted-count { font-size: var(--crisp-text-sm); color: color-mix(in srgb, var(--crisp-fg-primary) 73%, transparent); }
127
147
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
128
148
  }
129
149
 
@@ -37,7 +37,12 @@ export type DataCellType = "text" | "entity" | "tags" | "status" | "date" | "dat
37
37
  * workspace -- this type is display-only for now; editing still falls
38
38
  * through to the plain-text editor every other non-number/date type
39
39
  * gets, not a dedicated one (see #597 for when that's measured). */
40
- | "email";
40
+ | "email"
41
+ /** A star row (crisp/#760) -- Attio's own "Rating" attribute type,
42
+ * confirmed live: 5 filled/empty 5-point stars, `maxRating` stars total
43
+ * (default 5). Read-only display without `editor: "rating"`; see that
44
+ * prop for the always-live editable version. */
45
+ | "rating";
41
46
  export type DataTableColumn<T> = {
42
47
  key: string;
43
48
  /** Truncates with an ellipsis when it's wider than the column (#534: a
@@ -63,6 +68,10 @@ export type DataTableColumn<T> = {
63
68
  };
64
69
  /** Currency symbol for `currency` columns (default "$"). */
65
70
  symbol?: string;
71
+ /** Star count for `type: "rating"` / `editor: "rating"` (default 5 --
72
+ * Attio's own scale wasn't independently varied beyond the default in
73
+ * the measured workspace, #760). */
74
+ maxRating?: number;
66
75
  /** Allow drag-to-resize on this column (default true). */
67
76
  resizable?: boolean;
68
77
  /** Tone overrides for `status`/`tags` values (else a stable colour per value). */
@@ -94,8 +103,26 @@ export type DataTableColumn<T> = {
94
103
  * empty-search state reads "No users" rather than `Select`'s own
95
104
  * generic "No results" — both still overridable the normal way.
96
105
  * Otherwise identical to `reference`: same `refOptions` shape, same
97
- * `onCreateReference`/`createLabel` "Create X" row. */
98
- editor?: "select" | "switch" | "reference" | "actor";
106
+ * `onCreateReference`/`createLabel` "Create X" row.
107
+ *
108
+ * `"rating"` (crisp/#760) is the other always-live exception, same
109
+ * category as `"switch"`: confirmed live, a single click on any star
110
+ * commits immediately (no double-click gate, no separate rest/edit
111
+ * display) — clicking the star that already equals the current value
112
+ * clears it to 0/empty rather than re-setting it. Reads/writes
113
+ * `maxRating` stars (default 5).
114
+ *
115
+ * `"checkbox"` (crisp/#761) is a THIRD, distinct boolean rendering from
116
+ * `"switch"` — confirmed live against Attio's own "Checkbox" attribute
117
+ * type (Settings → Data → Lists → Attributes → Create attribute), which
118
+ * renders a plain checked/unchecked square, not a toggle pill; `"switch"`
119
+ * was never actually measured against that surface (no cited source —
120
+ * see #761's own investigation) and stays as-is for a genuine toggle
121
+ * field. Always-live like `"switch"`/`"rating"`; renders crisp's own
122
+ * `Checkbox` component (already measured 16px/r6/brand-fill from the
123
+ * grid's own row-selection checkbox — this is the SAME visual, not a
124
+ * new one). */
125
+ editor?: "select" | "switch" | "reference" | "actor" | "rating" | "checkbox";
99
126
  /** Options for `editor: "select"` (value/label, an optional `color` a
100
127
  * caller's own `render` can read) — same shape as RecordsTable's
101
128
  * `Column.options` for its `status` picker. */
@@ -82,8 +82,22 @@ export declare const TableHead: React.ForwardRefExoticComponent<Omit<React.Detai
82
82
  } & React.RefAttributes<HTMLTableCellElement>>;
83
83
  export type TableCellProps = React.ComponentPropsWithoutRef<"td"> & {
84
84
  align?: TableCellAlign;
85
+ /** Renders `<th>` instead of `<td>` -- a row's own identity cell (its
86
+ * name), not a plain value it holds (crisp/#779, matching RecordsTable's
87
+ * own #231 fix: a screen reader crossing the row reads "Google,
88
+ * Employees, 182,000" instead of a bare "182,000"). Pass `scope="row"`
89
+ * alongside it. */
90
+ as?: "td" | "th";
91
+ scope?: "row" | "col" | "rowgroup" | "colgroup";
85
92
  };
86
93
  export declare const TableCell: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, "ref"> & {
87
94
  align?: TableCellAlign;
95
+ /** Renders `<th>` instead of `<td>` -- a row's own identity cell (its
96
+ * name), not a plain value it holds (crisp/#779, matching RecordsTable's
97
+ * own #231 fix: a screen reader crossing the row reads "Google,
98
+ * Employees, 182,000" instead of a bare "182,000"). Pass `scope="row"`
99
+ * alongside it. */
100
+ as?: "td" | "th";
101
+ scope?: "row" | "col" | "rowgroup" | "colgroup";
88
102
  } & React.RefAttributes<HTMLTableCellElement>>;
89
103
  export declare const TableCaption: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & React.RefAttributes<HTMLTableCaptionElement>>;