@crisp-ui-kit/crisp 0.55.2 → 0.55.3
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.
- package/dist/cjs/components/columncalc/columncalc.recipe.js +20 -4
- package/dist/cjs/components/datatable/datatable.js +25 -16
- package/dist/cjs/components/datatable/datatable.recipe.js +30 -2
- package/dist/cjs/components/select/select.js +1 -1
- package/dist/cjs/components/table/table.recipe.js +20 -3
- package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +24 -3
- package/dist/columncalc.css +14 -4
- package/dist/columncalc.layered.css +14 -4
- package/dist/datatable.css +73 -76
- package/dist/datatable.layered.css +73 -76
- package/dist/esm/components/columncalc/columncalc.recipe.js +20 -4
- package/dist/esm/components/datatable/datatable.js +25 -16
- package/dist/esm/components/datatable/datatable.recipe.js +30 -2
- package/dist/esm/components/select/select.js +1 -1
- package/dist/esm/components/table/table.recipe.js +20 -3
- package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +24 -3
- package/dist/styles.css +130 -92
- package/dist/styles.layered.css +130 -92
- package/dist/table.css +11 -3
- package/dist/table.layered.css +11 -3
- package/dist/tabletoolbar.css +32 -9
- package/dist/tabletoolbar.layered.css +32 -9
- package/dist/types/components/datatable/datatable.d.ts +17 -1
- package/dist/types/components/select/select.d.ts +5 -0
- package/package.json +1 -1
package/dist/styles.layered.css
CHANGED
|
@@ -500,16 +500,26 @@
|
|
|
500
500
|
radius, and datatable-grip and the embedded pickers zero theirs. An 8px
|
|
501
501
|
radius survived the chip-to-full-cell conversion and shipped rounded
|
|
502
502
|
until #282, so the spec check now guards it. */
|
|
503
|
-
/* The hit target is the WHOLE summary cell -- measured
|
|
503
|
+
/* The hit target is the WHOLE summary cell -- measured 246x36 with
|
|
504
504
|
padding 0 12px, not a content-sized chip. Clicking anywhere in the cell
|
|
505
|
-
opens the aggregation menu.
|
|
506
|
-
|
|
505
|
+
opens the aggregation menu.
|
|
506
|
+
No `min-height` (crisp#834, found reproducing the footer-row-38px-
|
|
507
|
+
not-36px bug in an isolated browser test, not table.recipe.ts's own border/box-sizing, the hypothesis the issue itself flagged as unconfirmed): the table cell's OWN `height: tableRow` (36px,
|
|
508
|
+
border-box) leaves 34px of content box once its 2px of top+bottom
|
|
509
|
+
border are counted, and `min-height: tableRow` here demanded 36px
|
|
510
|
+
of CONTENT height regardless -- overflowing the cell by 2px, which
|
|
511
|
+
auto-height table layout resolves by growing the whole row to fit,
|
|
512
|
+
landing at exactly the reported 38. `height: 100%` alone already
|
|
513
|
+
fills whatever the cell's real content box is (the doc comment above this rule's own stated intent), with nothing left demanding more. */
|
|
514
|
+
& .crisp-columncalc-trigger { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
507
515
|
& .crisp-columncalc-trigger:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
508
516
|
& .crisp-columncalc-trigger svg { flex-shrink: 0; opacity: 0.7; }
|
|
509
517
|
& .crisp-columncalc-trigger[data-align="right"] { justify-content: flex-end; }
|
|
510
518
|
& .crisp-columncalc-placeholder { overflow: hidden; text-overflow: ellipsis; }
|
|
511
519
|
& .crisp-columncalc-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; }
|
|
512
|
-
|
|
520
|
+
/* crisp#837: re-measured live against Attio's real footer calc label -- 14px (was 13px, `c.text.md`, fixed on the shared trigger rule above) and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this file's own -op label already should have used instead of the flatter
|
|
521
|
+
`fgMuted` token (a close but not measured match). */
|
|
522
|
+
& .crisp-columncalc-op { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
513
523
|
& .crisp-columncalc-section { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
514
524
|
}
|
|
515
525
|
|
|
@@ -640,54 +650,58 @@
|
|
|
640
650
|
class + one element) -- a bare `& th` here only won by source
|
|
641
651
|
order, which flipped the moment table.recipe.ts's own CSS file happened to land after datatable's in the build (alphabetical:
|
|
642
652
|
datatable < table), silently reinstating 12px on every header cell
|
|
643
|
-
in the whole product and making every interactive column's button double it to 24px. Scoping through `.crisp-table` adds a second class to the selector (0,2,1 beats 0,1,1) so this can never lose a specificity tie to source order again.
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
653
|
+
in the whole product and making every interactive column's button double it to 24px. Scoping through `.crisp-table` adds a second class to the selector (0,2,1 beats 0,1,1) so this can never lose a specificity tie to source order again. `thead th`, not a bare `th` (crisp#829): #779 made the primary column's BODY cell a real `<th scope="row">` for a11y, and a bare
|
|
654
|
+
`th` here matches that one too, zeroing an inset nothing else
|
|
655
|
+
supplies -- the primary column's text sat flush left, one column's
|
|
656
|
+
cell no longer matching its own header or any sibling `<td>`. Only
|
|
657
|
+
the header row's own `<th>` needs zero padding (its sort BUTTON owns the inset); the body row's `<th scope="row">` has no button,
|
|
658
|
+
and needs the SAME base 12px (table.recipe.ts, #465) every other
|
|
659
|
+
cell already gets. */
|
|
660
|
+
& .crisp-table thead th { padding: 0; }
|
|
661
|
+
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger): Menu wraps its trigger in a flex div that sizes to its content, so a long header grew past the column instead of filling it -- with nothing left to squeeze, the label's own ellipsis CSS (below) had no properly
|
|
662
|
+
-sized box to truncate against, and the th's own overflow hard-clipped it with no "...". Fill the wrapper, scoped to th so Menu's default
|
|
663
|
+
(correct everywhere else) is untouched. */
|
|
650
664
|
& th .crisp-menu { width: 100%; height: 100%; }
|
|
651
665
|
& .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
|
|
652
666
|
& .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
653
|
-
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
654
|
-
columnMenu/sortable at all) renders .crisp-datatable-th-inner as a
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
plain sort `button` both put >=1 more level between `th` and this
|
|
660
|
-
span, so their own 12px (already on the button) isn't doubled. */
|
|
667
|
+
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
668
|
+
(the primary/entity column's now-inert path, or any column with no columnMenu/sortable at all) renders .crisp-datatable-th-inner as a DIRECT child of th instead of nested inside a button -- and loses the button's own 12px inset, drifting left of the td's 12px base inset. Measured live on Attio's own Companies grid: the header label
|
|
669
|
+
and the cell's own text land at the exact same x (335px from the viewport, both 40px from the column's left edge) via two different
|
|
670
|
+
padding+icon+gap combinations -- Attio does not leave the inert
|
|
671
|
+
primary header flush left either. The `>` combinator targets only
|
|
672
|
+
the button-less case: Menu's own wrapper (`.crisp-menu`) and the plain sort `button` both put >=1 more level between `th` and this span, so their own 12px (already on the button) isn't doubled. */
|
|
661
673
|
& th > .crisp-datatable-th-inner { box-sizing: border-box; padding: 0 var(--crisp-space-3); }
|
|
662
|
-
|
|
674
|
+
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
675
|
+
owns the whole 246x37 area so a click anywhere in the cell opens the
|
|
676
|
+
menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
663
677
|
& tfoot td { padding: 0; }
|
|
664
|
-
/* Group heading row -- a view is grouped under a subtle label with the
|
|
665
|
-
|
|
666
|
-
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
678
|
+
/* Group heading row -- a view is grouped under a subtle label with the bucket's count beside it. */
|
|
679
|
+
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
667
680
|
& .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
668
681
|
& .crisp-datatable-group-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
669
|
-
|
|
682
|
+
& .crisp-datatable-group { height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-3); background: var(--crisp-bg-subtle); border-bottom: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
670
683
|
& .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
|
|
671
684
|
& .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
|
|
672
685
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
673
686
|
& .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
674
|
-
/* #465: 12px per the comment above (and Attio's measured header cell
|
|
675
|
-
padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
|
|
676
|
-
own documented value. */
|
|
687
|
+
/* #465: 12px per the comment above (and Attio's measured header cell padding: 0 12px) -- was still c.space["2"] (8px), drifted from its own documented value. */
|
|
677
688
|
& .crisp-datatable-sort { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: none; font: inherit; letter-spacing: inherit; color: inherit; text-align: start; cursor: pointer; }
|
|
678
|
-
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
689
|
+
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
690
|
+
the START, matching its own values only in that the VALUES right-align
|
|
691
|
+
-- Attio's own right-aligned header (measured live: "Twitter follower
|
|
692
|
+
count") keeps the icon+label left and only the trailing column-menu icon sits pinned to the right edge, independent of the label's width
|
|
693
|
+
(#406, reversing #393's own justify-content: flex-end here). The chevron's own margin-inline-start: auto below already pins IT to the
|
|
694
|
+
end of a flex-start row with no override needed -- that's what pins the trailing icon on Attio too. */
|
|
683
695
|
& .crisp-datatable-chevron { margin-inline-start: auto; flex-shrink: 0; color: var(--crisp-fg-muted); opacity: 0; transition: opacity .12s; }
|
|
684
696
|
& .crisp-datatable-sort:hover .crisp-datatable-chevron { opacity: 0.6; }
|
|
685
697
|
& .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: var(--crisp-fg-primary); }
|
|
686
698
|
/* sticky first column(s) + horizontal scroll shadow — RecordsTable's feel */
|
|
687
699
|
& th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: var(--crisp-bg-surface); }
|
|
688
|
-
& th[data-sticky] { z-index: 3;
|
|
689
|
-
/* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
690
|
-
`tfoot td { z-index: 2 }
|
|
700
|
+
& th[data-sticky] { z-index: 3;
|
|
701
|
+
} /* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
702
|
+
`tfoot td { z-index: 2 }
|
|
703
|
+
`), which `td[data-sticky]`'s own higher-specificity
|
|
704
|
+
`z-index: 1` would otherwise undercut -- keep it level with the row it's in. */
|
|
691
705
|
& tfoot td[data-sticky] { z-index: 2; }
|
|
692
706
|
& tbody tr[data-selected] td[data-sticky] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
693
707
|
& tbody tr:hover td[data-sticky] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
|
|
@@ -704,36 +718,41 @@
|
|
|
704
718
|
& tbody tr[data-selected] td { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
705
719
|
& tbody tr[data-selected]:hover 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))); }
|
|
706
720
|
& .crisp-datatable-editable:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); cursor: text; }
|
|
707
|
-
/* crisp/#758: AI-enriched column marker, ported from RecordsTable's own
|
|
708
|
-
|
|
709
|
-
composited OVER whatever row-state background the cell already has
|
|
710
|
-
(hover, selected), which is why it's an ::after overlay and not a plain background. */
|
|
721
|
+
/* crisp/#758: AI-enriched column marker, ported from RecordsTable's own already-measured value -- a full-bleed #9b69ff (bgPurple) wash at 4%, composited OVER whatever row-state background the cell already has (hover, selected), which is why it's an ::after overlay and not a
|
|
722
|
+
plain background. */
|
|
711
723
|
& td[data-enriched]::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: color-mix(in srgb, var(--crisp-bg-purple) 4%, transparent); }
|
|
712
724
|
& .crisp-datatable-edit { width: 100%; height: 28px; margin: 0; padding: 0 var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); outline: none; vertical-align: middle; }
|
|
713
725
|
& .crisp-datatable-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
714
|
-
/* An async onEdit's in-flight state (#385) -- the field/picker dims and
|
|
715
|
-
stops accepting input rather than disappearing, so the just-typed or
|
|
716
|
-
just-chosen value stays visible while its commit is pending. Same
|
|
717
|
-
treatment Input already gives its own disabled state. */
|
|
726
|
+
/* An async onEdit's in-flight state (#385) -- the field/picker dims and stops accepting input rather than disappearing, so the just-typed or just-chosen value stays visible while its commit is pending. Same treatment Input already gives its own disabled state. */
|
|
718
727
|
& .crisp-datatable-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
719
728
|
& .crisp-datatable-edit-pending { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); color: var(--crisp-fg-muted); vertical-align: middle; }
|
|
720
|
-
/* The rejection's message, beside the cell's own content -- a sibling in
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
the row below, so it can never end up clipped by the scroll
|
|
724
|
-
container's overflow the way a position:fixed escape would need guarding against. */
|
|
729
|
+
/* The rejection's message, beside the cell's own content -- a sibling in the TableCell, never nested inside a column's own render output, so a
|
|
730
|
+
hover-only wrapper (a Tooltip, say) around a custom render can't hide it. Block-level: the row grows to fit it rather than floating over the row below, so it can never end up clipped by the scroll container's overflow the way a position:fixed escape would need
|
|
731
|
+
guarding against. */
|
|
725
732
|
& .crisp-datatable-edit-error { display: block; padding: var(--crisp-space-0-5) 0 0; font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
|
|
726
|
-
/* editor: "select"/"switch" -- always live, no separate edit mode, so
|
|
727
|
-
|
|
733
|
+
/* editor: "select"/"switch" -- always live, no separate edit mode, so
|
|
734
|
+
the cell IS the picker: same chromeless-fill treatment as
|
|
735
|
+
RecordsTable's own --picker cells (measured there already; DataTable shares RecordsTable's grid, Golden Rule 0). */
|
|
728
736
|
& .crisp-datatable-td--picker { padding: 0; }
|
|
729
737
|
& .crisp-datatable-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); }
|
|
730
738
|
& .crisp-datatable-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; height: 100%; min-height: 0; border-radius: 0; box-shadow: none; padding: 0; }
|
|
731
739
|
& .crisp-datatable-td--picker .crisp-datatable-edit-error { padding-inline-start: var(--crisp-space-2); }
|
|
732
|
-
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
740
|
+
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
741
|
+
"Create X" row when the consumer supplies one (#449) -- same measured
|
|
742
|
+
values as RecordsTable's own .crisp-recordstable-refoption*. */
|
|
733
743
|
& .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
734
744
|
& .crisp-datatable-refoption-avatar { flex-shrink: 0; }
|
|
735
745
|
& .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
|
|
736
746
|
& .crisp-datatable-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; color: var(--crisp-fg-muted); font-size: var(--crisp-text-lg); }
|
|
747
|
+
/* #826 -- the full-body loading state (a filter/sort re-query, or a fresh page boot), measured live on Attio's Companies grid on both
|
|
748
|
+
triggers: icon+text centred in the row-body area, 10px gap, 14px/500
|
|
749
|
+
weight/20px line-height, both icon and text in the SAME muted
|
|
750
|
+
rgba(0,0,0,0.63) -- the same color-mix figure this file already uses
|
|
751
|
+
for other muted text (e.g. -phone-dial). Distinct from the cold
|
|
752
|
+
in-place row load (blank, no indicator) and the warm-navigation
|
|
753
|
+
per-cell shimmer (#599) -- neither of those swaps the whole body. */
|
|
754
|
+
& .crisp-datatable-loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: var(--crisp-space-8) var(--crisp-space-3); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
755
|
+
& .crisp-datatable-loading .crisp-spinner { border-top-color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
737
756
|
/* #579: click-to-expand overlay for a truncated cell -- a read-only,
|
|
738
757
|
full-value card, settled live as click (not Attio's usual hover-expand) and measured position: absolute, unlike this file's
|
|
739
758
|
floating chrome (Menu/Select popovers) which portals and escapes the
|
|
@@ -824,54 +843,42 @@
|
|
|
824
843
|
& .crisp-datatable-phone-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
825
844
|
& .crisp-datatable-phone-editor { display: flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); }
|
|
826
845
|
& .crisp-datatable-phone-editor input { flex: 1; min-width: 0; }
|
|
846
|
+
/* country-picker option row (#842) -- confirmed live: Attio's own popover is plain text, no flag anywhere (not the option row, not the closed trigger), name opaque + dial code muted rgba(0,0,0,0.63) -- the SAME color-mix figure as -phone-dial above. The internal name/dial gap wasn't independently measured this pass (Attio's own two <div>s gave no exact number); reused space["1"], the same gap -phone already uses for its own flag/dial/digits row. */
|
|
847
|
+
& .crisp-datatable-country-option { display: flex; align-items: center; gap: var(--crisp-space-1); }
|
|
848
|
+
& .crisp-datatable-country-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
827
849
|
/* multi-value phone (#816) -- confirmed live (a real custom "Multiple
|
|
828
850
|
values" Phone Number attribute, and the built-in People "Phone
|
|
829
|
-
numbers" field): the collapsed cell is a 4px-gap flex row of real
|
|
830
|
-
tel: links in a measured link blue (~rgb(59,108,232) pixel-sampled;
|
|
831
|
-
reused as the closest already-tokened blue, brand600, rather than
|
|
832
|
-
adding a third blue token for a delta this small), underlined,
|
|
833
|
-
UNLIKE the single-value cell above (plain text, no link, no
|
|
834
|
-
underline) -- multi-value is the one shape Attio makes into a real
|
|
835
|
-
link. The cell hard-clips on overflow (no ellipsis -- confirmed
|
|
836
|
-
live, a second value can end mid-digit with no "..."). */
|
|
851
|
+
numbers" field): the collapsed cell is a 4px-gap flex row of real tel: links in a measured link blue (~rgb(59,108,232) pixel-sampled; reused as the closest already-tokened blue, brand600, rather than adding a third blue token for a delta this small), underlined, UNLIKE the single-value cell above (plain text, no link, no underline) -- multi-value is the one shape Attio makes into a real link. The cell hard-clips on overflow (no ellipsis -- confirmed live, a second value can end mid-digit with no "..."). */
|
|
837
852
|
& .crisp-datatable-phone-multi { display: inline-flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
|
|
838
853
|
& .crisp-datatable-phone-link { color: var(--crisp-bg-brand-solid); text-decoration: underline; white-space: nowrap; }
|
|
839
|
-
/* multi-value editor (#816) -- confirmed live: a stack of committed-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
DataPhoneEditor-shaped row -- that blank row is the only "add
|
|
843
|
-
another" affordance, there's no separate button for it. The copy/delete pair reuses .crisp-datatable-entity-action's own
|
|
844
|
-
hover-reveal chrome (not independently re-measured as its own hit
|
|
845
|
-
target this pass, only the 16px icon glyphs were). */
|
|
854
|
+
/* multi-value editor (#816) -- confirmed live: a stack of committed- value rows (32px = size.menuRow, 5px 8px padding, 8px gap between the grip/value/actions, 16px icons) above one ALWAYS-blank trailing DataPhoneEditor-shaped row -- that blank row is the only "add
|
|
855
|
+
another" affordance, there's no separate button for it. The
|
|
856
|
+
copy/delete pair reuses .crisp-datatable-entity-action's own hover-reveal chrome (not independently re-measured as its own hit target this pass, only the 16px icon glyphs were). */
|
|
846
857
|
& .crisp-datatable-phone-multi-editor { display: flex; flex-direction: column; }
|
|
847
858
|
& .crisp-datatable-phone-multi-row { display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-menuRow); padding: 5px var(--crisp-space-2); }
|
|
848
859
|
& .crisp-datatable-phone-multi-row .crisp-datatable-phone-link { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
849
860
|
& .crisp-datatable-phone-multi-grip { color: var(--crisp-fg-muted); flex-shrink: 0; cursor: grab; }
|
|
850
861
|
& .crisp-datatable-phone-multi-actions { display: flex; align-items: center; gap: var(--crisp-space-1); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
851
|
-
& .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions,
|
|
852
|
-
& .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
|
|
862
|
+
& .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions, & .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
|
|
853
863
|
& .crisp-datatable-phone-multi-action { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; font-family: inherit; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); cursor: pointer; flex-shrink: 0; }
|
|
854
864
|
& .crisp-datatable-phone-multi-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
855
865
|
/* datetime cell editor (#762) -- DatePickerField + TimePicker side by side. */
|
|
856
866
|
& .crisp-datatable-datetime-editor { display: flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); }
|
|
857
|
-
/* rating cell type/editor (#760) -- measured live: 16px stars on an
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
-- rgb(33,91,196) -- that's close to but NOT brand700/bgBrandSolidPressed (#1f5fd6); kept as its own literal rather than forced onto that token, since the two were measured stable and different. The read-only svg and the editable button's own inner svg both carry the
|
|
862
|
-
crisp-datatable-rating-star class on the svg itself (not the
|
|
863
|
-
button), so one set of fill rules covers both -- the button only
|
|
864
|
-
adds its own reset + cursor via a separate -btn class. */
|
|
867
|
+
/* 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
|
|
868
|
+
(#1f5fd6); kept as its own literal rather than forced onto that token,
|
|
869
|
+
since the two were measured stable and different. The read-only svg
|
|
870
|
+
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. */
|
|
865
871
|
& .crisp-datatable-rating { display: inline-flex; align-items: center; gap: 2px; }
|
|
866
872
|
& .crisp-datatable-rating-star { display: block; }
|
|
867
873
|
& .crisp-datatable-rating-star path { fill: rgba(0, 0, 0, 0.1); }
|
|
868
874
|
& .crisp-datatable-rating-star[data-filled] path { fill: var(--crisp-bg-brand-solid); }
|
|
869
875
|
& .crisp-datatable-rating-star[data-hovering] path { fill: #215bc4; }
|
|
870
876
|
& .crisp-datatable-rating-star-btn { display: inline-flex; padding: 0; margin: 0; border: none; background: none; font-family: inherit; cursor: pointer; }
|
|
871
|
-
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
(RecordsTable's reorderColumn) -- not a proprietary
|
|
877
|
+
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures a leading 20px grip column, a 16px grip icon, and the row's own
|
|
878
|
+
hairline doubling as the drop indicator (it tints toward the brand
|
|
879
|
+
colour as the active drop target). The affordance + geometry are
|
|
880
|
+
measured; the drag MECHANISM is crisp's existing house idiom -- HTML5 draggable + dataTransfer, the same one column reorder already uses (RecordsTable's reorderColumn) -- not a proprietary
|
|
881
|
+
pointer-events implementation. */
|
|
875
882
|
& .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
|
|
876
883
|
& .crisp-datatable-grip { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 100%; margin: 0; border: none; border-radius: 0; background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: grab; }
|
|
877
884
|
& .crisp-datatable-grip:active { cursor: grabbing; }
|
|
@@ -1868,8 +1875,16 @@
|
|
|
1868
1875
|
& th, & td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1869
1876
|
/* #554: sticky on the vertical axis, mirroring RecordsTable's own
|
|
1870
1877
|
`.crisp-recordstable-th`. z-index 2 sits above a plain body cell (auto)
|
|
1871
|
-
and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins.
|
|
1872
|
-
|
|
1878
|
+
and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins. `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
|
|
1879
|
+
column renders its BODY cell as a real `<th scope="row">` (#779, for
|
|
1880
|
+
a11y), and a bare `th` here matched that one too -- every property in
|
|
1881
|
+
this rule leaked onto it: `height: tableHeader` (40px) stretched the
|
|
1882
|
+
whole body row to 40px instead of 36 (#833, confirmed live on the
|
|
1883
|
+
showcase, every td in the row equalized to the one th); `color:
|
|
1884
|
+
color-mix(...63%...)` muted the primary column's own text below every sibling `<td>`'s full-opacity color (#835, re-measured live against
|
|
1885
|
+
Attio's own header labels -- including a genuinely computed one, "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no muting at all, so this drops the color-mix entirely rather than narrowing it); `position:sticky; top:0` tried to stick a BODY row to the scroll container's top; the extra `border-top` doubled that
|
|
1886
|
+
row's own grid line. `thead th` simply never matches `tbody th[scope=row]` at all, so none of this reaches it; the base `& th, & td` rule above (36px, one border-bottom, full opacity via `& table`'s own color) applies to it like every other cell. */
|
|
1887
|
+
& thead th { position: sticky; top: 0; z-index: 2; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-primary); user-select: none; }
|
|
1873
1888
|
& td { color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); }
|
|
1874
1889
|
& th:last-child, & td:last-child { border-inline-end: none; }
|
|
1875
1890
|
& tbody tr:last-child td { border-bottom: none; }
|
|
@@ -1888,7 +1903,7 @@
|
|
|
1888
1903
|
}
|
|
1889
1904
|
.crisp-table--surface_card {
|
|
1890
1905
|
border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-xl); overflow: hidden;
|
|
1891
|
-
& th { border-top: none; }
|
|
1906
|
+
& thead th { border-top: none; }
|
|
1892
1907
|
& tfoot td { border-bottom: none; }
|
|
1893
1908
|
}
|
|
1894
1909
|
.crisp-table--surface_bleed {
|
|
@@ -1912,7 +1927,9 @@
|
|
|
1912
1927
|
& .crisp-tabletoolbar-search svg { flex-shrink: 0; }
|
|
1913
1928
|
& .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; }
|
|
1914
1929
|
& .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
1915
|
-
|
|
1930
|
+
/* crisp/#830: every trigger label here (Sort, Filter, View settings, Import/Export -- all compose this one shared .tool rule) read the "md" text size, 13px. Re-measured on Attio's own trigger LEAF node
|
|
1931
|
+
(the button root itself inherits Attio's own 10px rem base and is a red herring, the same trap the original "10px font" layout-audit finding fell into): every label leaf is 14px/500/lh20, the "lg" text size. */
|
|
1932
|
+
& .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-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
|
|
1916
1933
|
& .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
|
|
1917
1934
|
& .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
1918
1935
|
/* 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
|
|
@@ -1931,8 +1948,17 @@
|
|
|
1931
1948
|
an actual sort applied. color-mix (not the raw rgba Attio computes
|
|
1932
1949
|
to) so both the border and the fill flip correctly in dark mode, the
|
|
1933
1950
|
same reasoning --ghost above already uses. Only wired into
|
|
1934
|
-
TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here.
|
|
1935
|
-
|
|
1951
|
+
TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. crisp/#844, correcting #831: the label colour was added here later, muting only the FILTER trigger (via a "--filter" modifier), on the assumption that was a Filter-specific tone distinct from Sort's.
|
|
1952
|
+
Re-measured live and that premise was wrong -- Sort's own resting label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5) as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
|
|
1953
|
+
"Sort's colour" in an earlier pass is a different thing entirely: the
|
|
1954
|
+
"Sorted by" PREFIX word inside an ACTIVE sort chip, #788 -- a
|
|
1955
|
+
compound-label treatment that only exists once a sort is applied, not
|
|
1956
|
+
a resting-state colour.) --dashed is currently only ever applied to
|
|
1957
|
+
Sort's and Filter's own empty triggers (never View settings/
|
|
1958
|
+
Import-Export, which stay full-strength always, confirmed live), so
|
|
1959
|
+
the mute belongs on --dashed itself, not gated behind a Filter-only
|
|
1960
|
+
modifier. */
|
|
1961
|
+
& .crisp-tabletoolbar-tool--dashed { position: relative; box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 50%, transparent); }
|
|
1936
1962
|
& .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; }
|
|
1937
1963
|
& .crisp-tabletoolbar-tool--dashed:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
|
|
1938
1964
|
& .crisp-tabletoolbar-toolgroup { position: relative; display: inline-flex; }
|
|
@@ -1972,7 +1998,11 @@
|
|
|
1972
1998
|
& .crisp-tabletoolbar-menu-sep { height: 1px; border: none; background: var(--crisp-border-subtle); margin: var(--crisp-space-0-5) 0; }
|
|
1973
1999
|
/* #592: the Filter field picker's nested-scope header (back control +
|
|
1974
2000
|
search, once drilled into a nestedColumns column) and a search
|
|
1975
|
-
result's own breadcrumb row ("Team › Twitter follower count",
|
|
2001
|
+
result's own breadcrumb row ("Team › Twitter follower count",
|
|
2002
|
+
surfaced by the SAME query matching a nested column). menu-back
|
|
2003
|
+
reuses the established 28px icon-only control pattern this file
|
|
2004
|
+
already uses twice (sort-remove, the kebab segment) rather than
|
|
2005
|
+
an independent measurement of Attio's own back arrow. The breadcrumb
|
|
1976
2006
|
colours ARE measured live: the parent segment muted at the same
|
|
1977
2007
|
exact color-mix 63% sort-learn above already uses, the
|
|
1978
2008
|
separator chevron and leaf segment both full fgPrimary (the
|
|
@@ -2016,9 +2046,15 @@
|
|
|
2016
2046
|
& .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
|
|
2017
2047
|
& .crisp-tabletoolbar-fcond-seg--field { border-radius: var(--crisp-radius-md) 0 0 var(--crisp-radius-md); font-weight: var(--crisp-weight-medium); max-width: 200px; }
|
|
2018
2048
|
& .crisp-tabletoolbar-fcond-seg--field svg { color: var(--crisp-fg-muted); }
|
|
2019
|
-
/* #592: a nested pick's field segment ("Team › Twitter follower
|
|
2020
|
-
|
|
2021
|
-
tabletoolbar.chrome.ts), each independently truncated. Attio's own
|
|
2049
|
+
/* #592: a nested pick's field segment ("Team › Twitter follower count") — measured live: BOTH path segments the same colour (chip
|
|
2050
|
+
context only; the picker's own menu rows keep the parent muted, see
|
|
2051
|
+
tabletoolbar.chrome.ts), each independently truncated. Attio's own
|
|
2052
|
+
layout gives the leaf segment priority (it stays fully readable
|
|
2053
|
+
longer, the parent truncates first) via a two-part min-content
|
|
2054
|
+
measurement this reproduces qualitatively with a flex-shrink
|
|
2055
|
+
differential rather than byte-for-byte (the exact px split Attio
|
|
2056
|
+
computes is content-length-dependent, not a fixed value) — not
|
|
2057
|
+
independently re-verified at other path-segment lengths. */
|
|
2022
2058
|
& .crisp-tabletoolbar-fcond-path { display: inline-flex; align-items: center; gap: 2px; min-width: 0; max-width: 178px; }
|
|
2023
2059
|
& .crisp-tabletoolbar-fcond-path-seg { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto; }
|
|
2024
2060
|
& .crisp-tabletoolbar-fcond-path-seg:first-child { flex: 0 1 auto; }
|
|
@@ -2028,8 +2064,10 @@
|
|
|
2028
2064
|
& .crisp-tabletoolbar-fcond-seg--kebab { background: var(--crisp-bg-surface); justify-content: center; width: 28px; padding: 0; border-radius: 0 var(--crisp-radius-md) var(--crisp-radius-md) 0; color: var(--crisp-fg-muted); }
|
|
2029
2065
|
& .crisp-tabletoolbar-fcond-seg--kebab:hover { color: var(--crisp-fg-primary); }
|
|
2030
2066
|
/* #754: the sort row's own field trigger, replacing a plain Select
|
|
2031
|
-
with the same nested-drill-down popover Filter's field picker
|
|
2032
|
-
|
|
2067
|
+
with the same nested-drill-down popover Filter's field picker
|
|
2068
|
+
already has — reuses Select's own already-measured trigger chrome
|
|
2069
|
+
verbatim (its class is scoped under Select's own root class, so it
|
|
2070
|
+
can't be reused as a bare class name outside an actual Select tree;
|
|
2033
2071
|
these values are copied, not re-measured). */
|
|
2034
2072
|
& .crisp-tabletoolbar-sort-field-picker { position: relative; display: inline-flex; flex: 1; min-width: 0; }
|
|
2035
2073
|
& .crisp-tabletoolbar-sort-field-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-menuRow); width: 100%; min-width: 0; margin: 0; padding: 0 var(--crisp-space-1-5) 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s ease, box-shadow .12s ease; }
|
package/dist/table.css
CHANGED
|
@@ -12,8 +12,16 @@
|
|
|
12
12
|
& th, & td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
13
13
|
/* #554: sticky on the vertical axis, mirroring RecordsTable's own
|
|
14
14
|
`.crisp-recordstable-th`. z-index 2 sits above a plain body cell (auto)
|
|
15
|
-
and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins.
|
|
16
|
-
|
|
15
|
+
and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins. `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
|
|
16
|
+
column renders its BODY cell as a real `<th scope="row">` (#779, for
|
|
17
|
+
a11y), and a bare `th` here matched that one too -- every property in
|
|
18
|
+
this rule leaked onto it: `height: tableHeader` (40px) stretched the
|
|
19
|
+
whole body row to 40px instead of 36 (#833, confirmed live on the
|
|
20
|
+
showcase, every td in the row equalized to the one th); `color:
|
|
21
|
+
color-mix(...63%...)` muted the primary column's own text below every sibling `<td>`'s full-opacity color (#835, re-measured live against
|
|
22
|
+
Attio's own header labels -- including a genuinely computed one, "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no muting at all, so this drops the color-mix entirely rather than narrowing it); `position:sticky; top:0` tried to stick a BODY row to the scroll container's top; the extra `border-top` doubled that
|
|
23
|
+
row's own grid line. `thead th` simply never matches `tbody th[scope=row]` at all, so none of this reaches it; the base `& th, & td` rule above (36px, one border-bottom, full opacity via `& table`'s own color) applies to it like every other cell. */
|
|
24
|
+
& thead th { position: sticky; top: 0; z-index: 2; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-primary); user-select: none; }
|
|
17
25
|
& td { color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); }
|
|
18
26
|
& th:last-child, & td:last-child { border-inline-end: none; }
|
|
19
27
|
& tbody tr:last-child td { border-bottom: none; }
|
|
@@ -32,7 +40,7 @@
|
|
|
32
40
|
}
|
|
33
41
|
.crisp-table--surface_card {
|
|
34
42
|
border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-xl); overflow: hidden;
|
|
35
|
-
& th { border-top: none; }
|
|
43
|
+
& thead th { border-top: none; }
|
|
36
44
|
& tfoot td { border-bottom: none; }
|
|
37
45
|
}
|
|
38
46
|
.crisp-table--surface_bleed {
|
package/dist/table.layered.css
CHANGED
|
@@ -13,8 +13,16 @@
|
|
|
13
13
|
& th, & td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
14
14
|
/* #554: sticky on the vertical axis, mirroring RecordsTable's own
|
|
15
15
|
`.crisp-recordstable-th`. z-index 2 sits above a plain body cell (auto)
|
|
16
|
-
and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins.
|
|
17
|
-
|
|
16
|
+
and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins. `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
|
|
17
|
+
column renders its BODY cell as a real `<th scope="row">` (#779, for
|
|
18
|
+
a11y), and a bare `th` here matched that one too -- every property in
|
|
19
|
+
this rule leaked onto it: `height: tableHeader` (40px) stretched the
|
|
20
|
+
whole body row to 40px instead of 36 (#833, confirmed live on the
|
|
21
|
+
showcase, every td in the row equalized to the one th); `color:
|
|
22
|
+
color-mix(...63%...)` muted the primary column's own text below every sibling `<td>`'s full-opacity color (#835, re-measured live against
|
|
23
|
+
Attio's own header labels -- including a genuinely computed one, "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no muting at all, so this drops the color-mix entirely rather than narrowing it); `position:sticky; top:0` tried to stick a BODY row to the scroll container's top; the extra `border-top` doubled that
|
|
24
|
+
row's own grid line. `thead th` simply never matches `tbody th[scope=row]` at all, so none of this reaches it; the base `& th, & td` rule above (36px, one border-bottom, full opacity via `& table`'s own color) applies to it like every other cell. */
|
|
25
|
+
& thead th { position: sticky; top: 0; z-index: 2; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-primary); user-select: none; }
|
|
18
26
|
& td { color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); }
|
|
19
27
|
& th:last-child, & td:last-child { border-inline-end: none; }
|
|
20
28
|
& tbody tr:last-child td { border-bottom: none; }
|
|
@@ -33,7 +41,7 @@
|
|
|
33
41
|
}
|
|
34
42
|
.crisp-table--surface_card {
|
|
35
43
|
border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-xl); overflow: hidden;
|
|
36
|
-
& th { border-top: none; }
|
|
44
|
+
& thead th { border-top: none; }
|
|
37
45
|
& tfoot td { border-bottom: none; }
|
|
38
46
|
}
|
|
39
47
|
.crisp-table--surface_bleed {
|
package/dist/tabletoolbar.css
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
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
|
-
|
|
10
|
+
/* crisp/#830: every trigger label here (Sort, Filter, View settings, Import/Export -- all compose this one shared .tool rule) read the "md" text size, 13px. Re-measured on Attio's own trigger LEAF node
|
|
11
|
+
(the button root itself inherits Attio's own 10px rem base and is a red herring, the same trap the original "10px font" layout-audit finding fell into): every label leaf is 14px/500/lh20, the "lg" text size. */
|
|
12
|
+
& .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-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
|
|
11
13
|
& .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
|
|
12
14
|
& .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
13
15
|
/* 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
|
|
@@ -26,8 +28,17 @@
|
|
|
26
28
|
an actual sort applied. color-mix (not the raw rgba Attio computes
|
|
27
29
|
to) so both the border and the fill flip correctly in dark mode, the
|
|
28
30
|
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
|
-
|
|
31
|
+
TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. crisp/#844, correcting #831: the label colour was added here later, muting only the FILTER trigger (via a "--filter" modifier), on the assumption that was a Filter-specific tone distinct from Sort's.
|
|
32
|
+
Re-measured live and that premise was wrong -- Sort's own resting label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5) as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
|
|
33
|
+
"Sort's colour" in an earlier pass is a different thing entirely: the
|
|
34
|
+
"Sorted by" PREFIX word inside an ACTIVE sort chip, #788 -- a
|
|
35
|
+
compound-label treatment that only exists once a sort is applied, not
|
|
36
|
+
a resting-state colour.) --dashed is currently only ever applied to
|
|
37
|
+
Sort's and Filter's own empty triggers (never View settings/
|
|
38
|
+
Import-Export, which stay full-strength always, confirmed live), so
|
|
39
|
+
the mute belongs on --dashed itself, not gated behind a Filter-only
|
|
40
|
+
modifier. */
|
|
41
|
+
& .crisp-tabletoolbar-tool--dashed { position: relative; box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 50%, transparent); }
|
|
31
42
|
& .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
43
|
& .crisp-tabletoolbar-tool--dashed:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
|
|
33
44
|
& .crisp-tabletoolbar-toolgroup { position: relative; display: inline-flex; }
|
|
@@ -67,7 +78,11 @@
|
|
|
67
78
|
& .crisp-tabletoolbar-menu-sep { height: 1px; border: none; background: var(--crisp-border-subtle); margin: var(--crisp-space-0-5) 0; }
|
|
68
79
|
/* #592: the Filter field picker's nested-scope header (back control +
|
|
69
80
|
search, once drilled into a nestedColumns column) and a search
|
|
70
|
-
result's own breadcrumb row ("Team › Twitter follower count",
|
|
81
|
+
result's own breadcrumb row ("Team › Twitter follower count",
|
|
82
|
+
surfaced by the SAME query matching a nested column). menu-back
|
|
83
|
+
reuses the established 28px icon-only control pattern this file
|
|
84
|
+
already uses twice (sort-remove, the kebab segment) rather than
|
|
85
|
+
an independent measurement of Attio's own back arrow. The breadcrumb
|
|
71
86
|
colours ARE measured live: the parent segment muted at the same
|
|
72
87
|
exact color-mix 63% sort-learn above already uses, the
|
|
73
88
|
separator chevron and leaf segment both full fgPrimary (the
|
|
@@ -111,9 +126,15 @@
|
|
|
111
126
|
& .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
|
|
112
127
|
& .crisp-tabletoolbar-fcond-seg--field { border-radius: var(--crisp-radius-md) 0 0 var(--crisp-radius-md); font-weight: var(--crisp-weight-medium); max-width: 200px; }
|
|
113
128
|
& .crisp-tabletoolbar-fcond-seg--field svg { color: var(--crisp-fg-muted); }
|
|
114
|
-
/* #592: a nested pick's field segment ("Team › Twitter follower
|
|
115
|
-
|
|
116
|
-
tabletoolbar.chrome.ts), each independently truncated. Attio's own
|
|
129
|
+
/* #592: a nested pick's field segment ("Team › Twitter follower count") — measured live: BOTH path segments the same colour (chip
|
|
130
|
+
context only; the picker's own menu rows keep the parent muted, see
|
|
131
|
+
tabletoolbar.chrome.ts), each independently truncated. Attio's own
|
|
132
|
+
layout gives the leaf segment priority (it stays fully readable
|
|
133
|
+
longer, the parent truncates first) via a two-part min-content
|
|
134
|
+
measurement this reproduces qualitatively with a flex-shrink
|
|
135
|
+
differential rather than byte-for-byte (the exact px split Attio
|
|
136
|
+
computes is content-length-dependent, not a fixed value) — not
|
|
137
|
+
independently re-verified at other path-segment lengths. */
|
|
117
138
|
& .crisp-tabletoolbar-fcond-path { display: inline-flex; align-items: center; gap: 2px; min-width: 0; max-width: 178px; }
|
|
118
139
|
& .crisp-tabletoolbar-fcond-path-seg { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto; }
|
|
119
140
|
& .crisp-tabletoolbar-fcond-path-seg:first-child { flex: 0 1 auto; }
|
|
@@ -123,8 +144,10 @@
|
|
|
123
144
|
& .crisp-tabletoolbar-fcond-seg--kebab { background: var(--crisp-bg-surface); justify-content: center; width: 28px; padding: 0; border-radius: 0 var(--crisp-radius-md) var(--crisp-radius-md) 0; color: var(--crisp-fg-muted); }
|
|
124
145
|
& .crisp-tabletoolbar-fcond-seg--kebab:hover { color: var(--crisp-fg-primary); }
|
|
125
146
|
/* #754: the sort row's own field trigger, replacing a plain Select
|
|
126
|
-
with the same nested-drill-down popover Filter's field picker
|
|
127
|
-
|
|
147
|
+
with the same nested-drill-down popover Filter's field picker
|
|
148
|
+
already has — reuses Select's own already-measured trigger chrome
|
|
149
|
+
verbatim (its class is scoped under Select's own root class, so it
|
|
150
|
+
can't be reused as a bare class name outside an actual Select tree;
|
|
128
151
|
these values are copied, not re-measured). */
|
|
129
152
|
& .crisp-tabletoolbar-sort-field-picker { position: relative; display: inline-flex; flex: 1; min-width: 0; }
|
|
130
153
|
& .crisp-tabletoolbar-sort-field-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-menuRow); width: 100%; min-width: 0; margin: 0; padding: 0 var(--crisp-space-1-5) 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s ease, box-shadow .12s ease; }
|