@crisp-ui-kit/crisp 0.55.2 → 0.55.4
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 +46 -3
- 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 +93 -79
- package/dist/datatable.layered.css +93 -79
- 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 +46 -3
- 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 +150 -95
- package/dist/styles.layered.css +150 -95
- 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/datatable.css
CHANGED
|
@@ -40,52 +40,64 @@
|
|
|
40
40
|
class + one element) -- a bare `& th` here only won by source
|
|
41
41
|
order, which flipped the moment table.recipe.ts's own CSS file happened to land after datatable's in the build (alphabetical:
|
|
42
42
|
datatable < table), silently reinstating 12px on every header cell
|
|
43
|
-
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.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
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
|
|
44
|
+
`th` here matches that one too, zeroing an inset nothing else
|
|
45
|
+
supplies -- the primary column's text sat flush left, one column's
|
|
46
|
+
cell no longer matching its own header or any sibling `<td>`. Only
|
|
47
|
+
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,
|
|
48
|
+
and needs the SAME base 12px (table.recipe.ts, #465) every other
|
|
49
|
+
cell already gets. */
|
|
50
|
+
& .crisp-table thead th { padding: 0; }
|
|
51
|
+
/* 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
|
|
52
|
+
-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
|
|
53
|
+
(correct everywhere else) is untouched. */
|
|
50
54
|
& th .crisp-menu { width: 100%; height: 100%; }
|
|
51
55
|
& .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
|
|
52
56
|
& .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
53
|
-
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
54
|
-
columnMenu/sortable at all) renders .crisp-datatable-th-inner as a
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
plain sort `button` both put >=1 more level between `th` and this
|
|
60
|
-
span, so their own 12px (already on the button) isn't doubled. */
|
|
57
|
+
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
58
|
+
(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
|
|
59
|
+
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
|
|
60
|
+
padding+icon+gap combinations -- Attio does not leave the inert
|
|
61
|
+
primary header flush left either. The `>` combinator targets only
|
|
62
|
+
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. */
|
|
61
63
|
& th > .crisp-datatable-th-inner { box-sizing: border-box; padding: 0 var(--crisp-space-3); }
|
|
62
|
-
|
|
64
|
+
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
65
|
+
owns the whole 246x37 area so a click anywhere in the cell opens the
|
|
66
|
+
menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
63
67
|
& tfoot td { padding: 0; }
|
|
64
|
-
/* Group heading row -- a view is grouped under a subtle label with the
|
|
65
|
-
|
|
66
|
-
& .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; }
|
|
68
|
+
/* Group heading row -- a view is grouped under a subtle label with the bucket's count beside it. */
|
|
69
|
+
& .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; }
|
|
67
70
|
& .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
68
71
|
& .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); }
|
|
69
|
-
|
|
72
|
+
& .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); }
|
|
70
73
|
& .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
|
|
71
74
|
& .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; }
|
|
72
75
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
73
76
|
& .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
74
|
-
/* #465: 12px per the comment above (and Attio's measured header cell
|
|
75
|
-
padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
|
|
76
|
-
own documented value. */
|
|
77
|
+
/* #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. */
|
|
77
78
|
& .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; }
|
|
78
|
-
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
80
|
+
the START, matching its own values only in that the VALUES right-align
|
|
81
|
+
-- Attio's own right-aligned header (measured live: "Twitter follower
|
|
82
|
+
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
|
|
83
|
+
(#406, reversing #393's own justify-content: flex-end here). The chevron's own margin-inline-start: auto below already pins IT to the
|
|
84
|
+
end of a flex-start row with no override needed -- that's what pins the trailing icon on Attio too. */
|
|
83
85
|
& .crisp-datatable-chevron { margin-inline-start: auto; flex-shrink: 0; color: var(--crisp-fg-muted); opacity: 0; transition: opacity .12s; }
|
|
84
86
|
& .crisp-datatable-sort:hover .crisp-datatable-chevron { opacity: 0.6; }
|
|
85
87
|
& .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: var(--crisp-fg-primary); }
|
|
86
88
|
/* sticky first column(s) + horizontal scroll shadow — RecordsTable's feel */
|
|
87
89
|
& th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: var(--crisp-bg-surface); }
|
|
88
|
-
|
|
90
|
+
/* `thead th[data-sticky]`, not a bare `th[data-sticky]` (crisp#848, same
|
|
91
|
+
bare-`th` family as #829/#833/#835): this z-index:3 was written for
|
|
92
|
+
the HEADER's own sticky corner cell (sticky column x sticky header), meant to win over everything else. Unscoped, it also matched the primary column's BODY cell -- a real `<th scope="row" data-sticky>`
|
|
93
|
+
since #779 -- giving every scrolled body row's own sticky cell a HIGHER z-index than the sticky FOOTER's (2), so it painted over the
|
|
94
|
+
footer instead of the footer showing through. Confirmed live on a
|
|
95
|
+
real bounded-height, 25-row table (GRC's Risk register): scrolled partway, `elementFromPoint` at the footer's own on-screen cell
|
|
96
|
+
resolved to a body row's `<th>`, not the footer's `<td>`, and that
|
|
97
|
+
`<th>`'s computed z-index read 3. Scoped to `thead`, a body row's
|
|
98
|
+
own sticky `<th>` now falls back to the base rule above (z-index 1,
|
|
99
|
+
correct -- the same as a plain sticky `<td>`), and the footer's own explicit z-index below is unaffected either way. */
|
|
100
|
+
& thead th[data-sticky] { z-index: 3; }
|
|
89
101
|
/* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
90
102
|
`tfoot td { z-index: 2 }`), which `td[data-sticky]`'s own higher-specificity `z-index: 1` would otherwise undercut -- keep it level with the row it's in. */
|
|
91
103
|
& tfoot td[data-sticky] { z-index: 2; }
|
|
@@ -134,68 +146,66 @@
|
|
|
134
146
|
& .crisp-datatable-refoption-avatar { flex-shrink: 0; }
|
|
135
147
|
& .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
|
|
136
148
|
& .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); }
|
|
137
|
-
/* #
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
assumes a fixed row height for its scroll math (owned by the grid
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
`.crisp-table-scroll`'s own `overflow: auto` if it grows past the visible viewport, same as the edit-error comment above already notes for any position:absolute escape -- unmeasured against Attio for this exact case, flagged rather than guessed. */
|
|
149
|
+
/* #826 -- the full-body loading state (a filter/sort re-query, or a
|
|
150
|
+
fresh page boot), measured live on Attio's Companies grid on both triggers: icon+text centred in the row-body area, 10px gap, 14px/500 weight/20px line-height, both icon and text in the SAME muted rgba(0,0,0,0.63) -- the same color-mix figure this file already uses for other muted text (e.g. -phone-dial). Distinct from the cold in-place row load (blank, no indicator) and the warm-navigation per-cell shimmer (#599) -- neither of those swaps the whole body. */
|
|
151
|
+
& .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; }
|
|
152
|
+
& .crisp-datatable-loading .crisp-spinner { border-top-color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
153
|
+
/* #579: click-to-expand overlay for a truncated cell -- a read-only, full-value card, settled live as click (not Attio's usual
|
|
154
|
+
hover-expand) and measured position: absolute, unlike this file's floating chrome (Menu/Select popovers) which portals and escapes the scroll container. Deliberately NOT the edit-error pattern above (grow the row, block-level, never clipped): a virtualized grid assumes a fixed row height for its scroll math (owned by the grid core, not this cell), so growing a row here would fight it. Anchored to the SAME column width the cell itself renders at (measured: Attio's own overlay came out only slightly wider than the
|
|
155
|
+
triggering cell's clientWidth -- the overshoot is this padding), wrapping onto as many lines as the value needs; it CAN be clipped by `.crisp-table-scroll`'s own `overflow: auto` if it grows past the
|
|
156
|
+
visible viewport, same as the edit-error comment above already
|
|
157
|
+
notes for any position:absolute escape -- unmeasured against Attio
|
|
158
|
+
for this exact case, flagged rather than guessed. */
|
|
148
159
|
& td[data-cell-expanded] { overflow: visible; z-index: 7; }
|
|
149
|
-
& .crisp-datatable-cell-overlay {
|
|
160
|
+
& .crisp-datatable-cell-overlay {
|
|
161
|
+
position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box;
|
|
162
|
+
padding: var(--crisp-space-2) var(--crisp-space-3); background: var(--crisp-bg-surface);
|
|
163
|
+
border: 1px solid var(--crisp-bg-brand-solid); border-radius: 4px;
|
|
164
|
+
font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium);
|
|
165
|
+
color: var(--crisp-fg-primary); white-space: normal; word-break: break-word; cursor: default;
|
|
166
|
+
}
|
|
150
167
|
/* fixed layout so column widths (and resize) are exact — like RecordsTable */
|
|
151
168
|
& table { table-layout: fixed; }
|
|
152
|
-
/* read-only/computed column marker (#596) -- sits just inside the
|
|
169
|
+
/* read-only/computed column marker (#596) -- sits just inside the
|
|
170
|
+
resize handle, same absolute-positioned-against-the-th approach the
|
|
171
|
+
handle itself uses, since th has zero padding and the button/inner
|
|
172
|
+
row fills the whole cell with no room left for a trailing sibling. */
|
|
153
173
|
& .crisp-datatable-readonly { position: absolute; top: 50%; inset-inline-end: 11px; transform: translateY(-50%); color: var(--crisp-fg-muted); pointer-events: none; z-index: 5; }
|
|
154
174
|
/* column resize grip */
|
|
155
175
|
& .crisp-datatable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
|
|
156
176
|
& .crisp-datatable-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; }
|
|
157
177
|
& .crisp-datatable-resize:hover::after, & .crisp-datatable-resize[data-resizing]::after { opacity: 1; }
|
|
158
|
-
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
178
|
+
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's own grid (the issue's own comment): the dragged header keeps full
|
|
179
|
+
opacity and the plain `pointer` cursor throughout (Attio draws no
|
|
180
|
+
ghost and no "grabbing" cursor of its own), so this adds nothing to
|
|
181
|
+
`[data-dragging]` itself -- the ONLY new paint is the drop-indicator
|
|
182
|
+
line, a 3px bar in the same measured brand blue the resize handle's own hover state (above) already uses, positioned on whichever edge of the hovered header the pointer is closer to. */
|
|
162
183
|
& th[data-dragging] { cursor: pointer; }
|
|
163
|
-
& th[data-drop-before]::before, & th[data-drop-after]::after {
|
|
164
|
-
content: ""; position: absolute; top: 0; width: 3px; height: 100%;
|
|
165
|
-
background: var(--crisp-bg-brand-solid); z-index: 6; pointer-events: none;
|
|
166
|
-
}
|
|
184
|
+
& th[data-drop-before]::before, & th[data-drop-after]::after { content: ""; position: absolute; top: 0; width: 3px; height: 100%; background: var(--crisp-bg-brand-solid); z-index: 6; pointer-events: none; }
|
|
167
185
|
& th[data-drop-before]::before { inset-inline-start: -1.5px; }
|
|
168
186
|
& th[data-drop-after]::after { inset-inline-end: -1.5px; }
|
|
169
187
|
/* typed cells — entity (avatar + name), colour-coded tags, numbers, dates */
|
|
170
188
|
& .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); }
|
|
171
|
-
/* crisp/#601 supersession follow-up -- the same flex-row shape
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
onOpenComments/onOpenPreview compose alongside ANY column's own content (a custom render, or a non-entity built-in type), not just type: "entity"'s own inline rendering. */
|
|
189
|
+
/* 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
|
|
190
|
+
content (a custom render, or a non-entity built-in type), not just
|
|
191
|
+
type: "entity"'s own inline rendering. */
|
|
175
192
|
& .crisp-datatable-cell-actions-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; width: 100%; }
|
|
176
|
-
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text,
|
|
177
|
-
|
|
178
|
-
colour. The previous :hover-gated, full-contrast rule here was itself
|
|
179
|
-
unmeasured and wrong in two ways at once. */
|
|
193
|
+
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text, plain hover vs rest) that Attio's underline is unconditional, not a
|
|
194
|
+
hover reveal -- identical at rest and on hover: text-decoration-color
|
|
195
|
+
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. */
|
|
180
196
|
& .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
|
|
181
197
|
& button.crisp-datatable-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%; }
|
|
182
|
-
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
rgba(0,0,0,0.04) background on the icon's OWN hover -- both expressed as color-mix against fgPrimary so they stay correct in dark mode instead of a literal black that would invert. */
|
|
198
|
+
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary column, revealed on ROW hover (the issue's own title says "row
|
|
199
|
+
hover", and a live check confirmed hovering well past the name --
|
|
200
|
+
not just the icons' own hit target -- still reveals them) or keyboard focus. Measured live: border-radius 6px, icon colour rgba(0,0,0,0.55) at rest, darkening to the full text colour with a rgba(0,0,0,0.04) background on the icon's OWN hover -- both
|
|
201
|
+
expressed as color-mix against fgPrimary so they stay correct in
|
|
202
|
+
dark mode instead of a literal black that would invert. */
|
|
188
203
|
& .crisp-datatable-entity-actions { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
189
204
|
& tr:hover .crisp-datatable-entity-actions, & .crisp-datatable-entity-actions:focus-within { opacity: 1; }
|
|
190
205
|
& .crisp-datatable-entity-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; }
|
|
191
206
|
& .crisp-datatable-entity-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
192
207
|
& .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
|
|
193
|
-
& .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
|
|
194
|
-
& .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
|
|
195
|
-
& .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
|
|
196
|
-
& .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
|
|
197
|
-
& .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
|
|
198
|
-
& .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
|
|
208
|
+
& .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); } & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); } & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); } & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); } & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); } & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
|
|
199
209
|
& .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
|
|
200
210
|
& .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
|
|
201
211
|
& .crisp-datatable-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); }
|
|
@@ -208,22 +218,26 @@
|
|
|
208
218
|
& .crisp-datatable-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)); }
|
|
209
219
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
210
220
|
& .crisp-datatable-muted { color: var(--crisp-fg-muted); }
|
|
211
|
-
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
212
|
-
|
|
221
|
+
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as TasksTable's own overdue due-date (crisp#462), plain text colour, no
|
|
222
|
+
fill/weight change. */
|
|
213
223
|
& .crisp-datatable-danger { color: var(--crisp-fg-danger); }
|
|
214
|
-
/* url/email cell types (#654) -- same measured values as RecordsTable's
|
|
215
|
-
own .crisp-recordstable-link, which this mirrors: no underline at
|
|
216
|
-
rest, underline on hover, own-colour text rather than a browser-blue
|
|
217
|
-
link. */
|
|
224
|
+
/* 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. */
|
|
218
225
|
& .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
219
226
|
& .crisp-datatable-link:hover { text-decoration: underline; }
|
|
220
|
-
/* phone cell type/editor (#765) -- measured live: the dial-code prefix
|
|
221
|
-
is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
|
|
222
|
-
value already measured elsewhere in this file. */
|
|
227
|
+
/* phone cell type/editor (#765) -- measured live: the dial-code prefix is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text value already measured elsewhere in this file. */
|
|
223
228
|
& .crisp-datatable-phone { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
224
229
|
& .crisp-datatable-phone-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
225
230
|
& .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); }
|
|
226
231
|
& .crisp-datatable-phone-editor input { flex: 1; min-width: 0; }
|
|
232
|
+
/* country-picker option row (#842) -- confirmed live: Attio's own popover
|
|
233
|
+
is plain text, no flag anywhere (not the option row, not the closed
|
|
234
|
+
trigger), name opaque + dial code muted rgba(0,0,0,0.63) -- the SAME
|
|
235
|
+
color-mix figure as -phone-dial above. The internal name/dial gap
|
|
236
|
+
wasn't independently measured this pass (Attio's own two <div>s gave
|
|
237
|
+
no exact number); reused space["1"], the same gap -phone already uses
|
|
238
|
+
for its own flag/dial/digits row. */
|
|
239
|
+
& .crisp-datatable-country-option { display: flex; align-items: center; gap: var(--crisp-space-1); }
|
|
240
|
+
& .crisp-datatable-country-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
227
241
|
/* multi-value phone (#816) -- confirmed live (a real custom "Multiple
|
|
228
242
|
values" Phone Number attribute, and the built-in People "Phone
|
|
229
243
|
numbers" field): the collapsed cell is a 4px-gap flex row of real
|
|
@@ -41,52 +41,64 @@
|
|
|
41
41
|
class + one element) -- a bare `& th` here only won by source
|
|
42
42
|
order, which flipped the moment table.recipe.ts's own CSS file happened to land after datatable's in the build (alphabetical:
|
|
43
43
|
datatable < table), silently reinstating 12px on every header cell
|
|
44
|
-
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.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
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
|
|
45
|
+
`th` here matches that one too, zeroing an inset nothing else
|
|
46
|
+
supplies -- the primary column's text sat flush left, one column's
|
|
47
|
+
cell no longer matching its own header or any sibling `<td>`. Only
|
|
48
|
+
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,
|
|
49
|
+
and needs the SAME base 12px (table.recipe.ts, #465) every other
|
|
50
|
+
cell already gets. */
|
|
51
|
+
& .crisp-table thead th { padding: 0; }
|
|
52
|
+
/* 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
|
|
53
|
+
-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
|
|
54
|
+
(correct everywhere else) is untouched. */
|
|
51
55
|
& th .crisp-menu { width: 100%; height: 100%; }
|
|
52
56
|
& .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
|
|
53
57
|
& .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
54
|
-
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
55
|
-
columnMenu/sortable at all) renders .crisp-datatable-th-inner as a
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
plain sort `button` both put >=1 more level between `th` and this
|
|
61
|
-
span, so their own 12px (already on the button) isn't doubled. */
|
|
58
|
+
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
59
|
+
(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
|
|
60
|
+
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
|
|
61
|
+
padding+icon+gap combinations -- Attio does not leave the inert
|
|
62
|
+
primary header flush left either. The `>` combinator targets only
|
|
63
|
+
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. */
|
|
62
64
|
& th > .crisp-datatable-th-inner { box-sizing: border-box; padding: 0 var(--crisp-space-3); }
|
|
63
|
-
|
|
65
|
+
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
66
|
+
owns the whole 246x37 area so a click anywhere in the cell opens the
|
|
67
|
+
menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
64
68
|
& tfoot td { padding: 0; }
|
|
65
|
-
/* Group heading row -- a view is grouped under a subtle label with the
|
|
66
|
-
|
|
67
|
-
& .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; }
|
|
69
|
+
/* Group heading row -- a view is grouped under a subtle label with the bucket's count beside it. */
|
|
70
|
+
& .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; }
|
|
68
71
|
& .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
69
72
|
& .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); }
|
|
70
|
-
|
|
73
|
+
& .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); }
|
|
71
74
|
& .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
|
|
72
75
|
& .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; }
|
|
73
76
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
74
77
|
& .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
75
|
-
/* #465: 12px per the comment above (and Attio's measured header cell
|
|
76
|
-
padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
|
|
77
|
-
own documented value. */
|
|
78
|
+
/* #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. */
|
|
78
79
|
& .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; }
|
|
79
|
-
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
81
|
+
the START, matching its own values only in that the VALUES right-align
|
|
82
|
+
-- Attio's own right-aligned header (measured live: "Twitter follower
|
|
83
|
+
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
|
|
84
|
+
(#406, reversing #393's own justify-content: flex-end here). The chevron's own margin-inline-start: auto below already pins IT to the
|
|
85
|
+
end of a flex-start row with no override needed -- that's what pins the trailing icon on Attio too. */
|
|
84
86
|
& .crisp-datatable-chevron { margin-inline-start: auto; flex-shrink: 0; color: var(--crisp-fg-muted); opacity: 0; transition: opacity .12s; }
|
|
85
87
|
& .crisp-datatable-sort:hover .crisp-datatable-chevron { opacity: 0.6; }
|
|
86
88
|
& .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: var(--crisp-fg-primary); }
|
|
87
89
|
/* sticky first column(s) + horizontal scroll shadow — RecordsTable's feel */
|
|
88
90
|
& th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: var(--crisp-bg-surface); }
|
|
89
|
-
|
|
91
|
+
/* `thead th[data-sticky]`, not a bare `th[data-sticky]` (crisp#848, same
|
|
92
|
+
bare-`th` family as #829/#833/#835): this z-index:3 was written for
|
|
93
|
+
the HEADER's own sticky corner cell (sticky column x sticky header), meant to win over everything else. Unscoped, it also matched the primary column's BODY cell -- a real `<th scope="row" data-sticky>`
|
|
94
|
+
since #779 -- giving every scrolled body row's own sticky cell a HIGHER z-index than the sticky FOOTER's (2), so it painted over the
|
|
95
|
+
footer instead of the footer showing through. Confirmed live on a
|
|
96
|
+
real bounded-height, 25-row table (GRC's Risk register): scrolled partway, `elementFromPoint` at the footer's own on-screen cell
|
|
97
|
+
resolved to a body row's `<th>`, not the footer's `<td>`, and that
|
|
98
|
+
`<th>`'s computed z-index read 3. Scoped to `thead`, a body row's
|
|
99
|
+
own sticky `<th>` now falls back to the base rule above (z-index 1,
|
|
100
|
+
correct -- the same as a plain sticky `<td>`), and the footer's own explicit z-index below is unaffected either way. */
|
|
101
|
+
& thead th[data-sticky] { z-index: 3; }
|
|
90
102
|
/* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
91
103
|
`tfoot td { z-index: 2 }`), which `td[data-sticky]`'s own higher-specificity `z-index: 1` would otherwise undercut -- keep it level with the row it's in. */
|
|
92
104
|
& tfoot td[data-sticky] { z-index: 2; }
|
|
@@ -135,68 +147,66 @@
|
|
|
135
147
|
& .crisp-datatable-refoption-avatar { flex-shrink: 0; }
|
|
136
148
|
& .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
|
|
137
149
|
& .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); }
|
|
138
|
-
/* #
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
assumes a fixed row height for its scroll math (owned by the grid
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
`.crisp-table-scroll`'s own `overflow: auto` if it grows past the visible viewport, same as the edit-error comment above already notes for any position:absolute escape -- unmeasured against Attio for this exact case, flagged rather than guessed. */
|
|
150
|
+
/* #826 -- the full-body loading state (a filter/sort re-query, or a
|
|
151
|
+
fresh page boot), measured live on Attio's Companies grid on both triggers: icon+text centred in the row-body area, 10px gap, 14px/500 weight/20px line-height, both icon and text in the SAME muted rgba(0,0,0,0.63) -- the same color-mix figure this file already uses for other muted text (e.g. -phone-dial). Distinct from the cold in-place row load (blank, no indicator) and the warm-navigation per-cell shimmer (#599) -- neither of those swaps the whole body. */
|
|
152
|
+
& .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; }
|
|
153
|
+
& .crisp-datatable-loading .crisp-spinner { border-top-color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
154
|
+
/* #579: click-to-expand overlay for a truncated cell -- a read-only, full-value card, settled live as click (not Attio's usual
|
|
155
|
+
hover-expand) and measured position: absolute, unlike this file's floating chrome (Menu/Select popovers) which portals and escapes the scroll container. Deliberately NOT the edit-error pattern above (grow the row, block-level, never clipped): a virtualized grid assumes a fixed row height for its scroll math (owned by the grid core, not this cell), so growing a row here would fight it. Anchored to the SAME column width the cell itself renders at (measured: Attio's own overlay came out only slightly wider than the
|
|
156
|
+
triggering cell's clientWidth -- the overshoot is this padding), wrapping onto as many lines as the value needs; it CAN be clipped by `.crisp-table-scroll`'s own `overflow: auto` if it grows past the
|
|
157
|
+
visible viewport, same as the edit-error comment above already
|
|
158
|
+
notes for any position:absolute escape -- unmeasured against Attio
|
|
159
|
+
for this exact case, flagged rather than guessed. */
|
|
149
160
|
& td[data-cell-expanded] { overflow: visible; z-index: 7; }
|
|
150
|
-
& .crisp-datatable-cell-overlay {
|
|
161
|
+
& .crisp-datatable-cell-overlay {
|
|
162
|
+
position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box;
|
|
163
|
+
padding: var(--crisp-space-2) var(--crisp-space-3); background: var(--crisp-bg-surface);
|
|
164
|
+
border: 1px solid var(--crisp-bg-brand-solid); border-radius: 4px;
|
|
165
|
+
font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium);
|
|
166
|
+
color: var(--crisp-fg-primary); white-space: normal; word-break: break-word; cursor: default;
|
|
167
|
+
}
|
|
151
168
|
/* fixed layout so column widths (and resize) are exact — like RecordsTable */
|
|
152
169
|
& table { table-layout: fixed; }
|
|
153
|
-
/* read-only/computed column marker (#596) -- sits just inside the
|
|
170
|
+
/* read-only/computed column marker (#596) -- sits just inside the
|
|
171
|
+
resize handle, same absolute-positioned-against-the-th approach the
|
|
172
|
+
handle itself uses, since th has zero padding and the button/inner
|
|
173
|
+
row fills the whole cell with no room left for a trailing sibling. */
|
|
154
174
|
& .crisp-datatable-readonly { position: absolute; top: 50%; inset-inline-end: 11px; transform: translateY(-50%); color: var(--crisp-fg-muted); pointer-events: none; z-index: 5; }
|
|
155
175
|
/* column resize grip */
|
|
156
176
|
& .crisp-datatable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
|
|
157
177
|
& .crisp-datatable-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; }
|
|
158
178
|
& .crisp-datatable-resize:hover::after, & .crisp-datatable-resize[data-resizing]::after { opacity: 1; }
|
|
159
|
-
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
179
|
+
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's own grid (the issue's own comment): the dragged header keeps full
|
|
180
|
+
opacity and the plain `pointer` cursor throughout (Attio draws no
|
|
181
|
+
ghost and no "grabbing" cursor of its own), so this adds nothing to
|
|
182
|
+
`[data-dragging]` itself -- the ONLY new paint is the drop-indicator
|
|
183
|
+
line, a 3px bar in the same measured brand blue the resize handle's own hover state (above) already uses, positioned on whichever edge of the hovered header the pointer is closer to. */
|
|
163
184
|
& th[data-dragging] { cursor: pointer; }
|
|
164
|
-
& th[data-drop-before]::before, & th[data-drop-after]::after {
|
|
165
|
-
content: ""; position: absolute; top: 0; width: 3px; height: 100%;
|
|
166
|
-
background: var(--crisp-bg-brand-solid); z-index: 6; pointer-events: none;
|
|
167
|
-
}
|
|
185
|
+
& th[data-drop-before]::before, & th[data-drop-after]::after { content: ""; position: absolute; top: 0; width: 3px; height: 100%; background: var(--crisp-bg-brand-solid); z-index: 6; pointer-events: none; }
|
|
168
186
|
& th[data-drop-before]::before { inset-inline-start: -1.5px; }
|
|
169
187
|
& th[data-drop-after]::after { inset-inline-end: -1.5px; }
|
|
170
188
|
/* typed cells — entity (avatar + name), colour-coded tags, numbers, dates */
|
|
171
189
|
& .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); }
|
|
172
|
-
/* crisp/#601 supersession follow-up -- the same flex-row shape
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
onOpenComments/onOpenPreview compose alongside ANY column's own content (a custom render, or a non-entity built-in type), not just type: "entity"'s own inline rendering. */
|
|
190
|
+
/* 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
|
|
191
|
+
content (a custom render, or a non-entity built-in type), not just
|
|
192
|
+
type: "entity"'s own inline rendering. */
|
|
176
193
|
& .crisp-datatable-cell-actions-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; width: 100%; }
|
|
177
|
-
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text,
|
|
178
|
-
|
|
179
|
-
colour. The previous :hover-gated, full-contrast rule here was itself
|
|
180
|
-
unmeasured and wrong in two ways at once. */
|
|
194
|
+
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text, plain hover vs rest) that Attio's underline is unconditional, not a
|
|
195
|
+
hover reveal -- identical at rest and on hover: text-decoration-color
|
|
196
|
+
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. */
|
|
181
197
|
& .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
|
|
182
198
|
& button.crisp-datatable-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%; }
|
|
183
|
-
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
rgba(0,0,0,0.04) background on the icon's OWN hover -- both expressed as color-mix against fgPrimary so they stay correct in dark mode instead of a literal black that would invert. */
|
|
199
|
+
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary column, revealed on ROW hover (the issue's own title says "row
|
|
200
|
+
hover", and a live check confirmed hovering well past the name --
|
|
201
|
+
not just the icons' own hit target -- still reveals them) or keyboard focus. Measured live: border-radius 6px, icon colour rgba(0,0,0,0.55) at rest, darkening to the full text colour with a rgba(0,0,0,0.04) background on the icon's OWN hover -- both
|
|
202
|
+
expressed as color-mix against fgPrimary so they stay correct in
|
|
203
|
+
dark mode instead of a literal black that would invert. */
|
|
189
204
|
& .crisp-datatable-entity-actions { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
190
205
|
& tr:hover .crisp-datatable-entity-actions, & .crisp-datatable-entity-actions:focus-within { opacity: 1; }
|
|
191
206
|
& .crisp-datatable-entity-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; }
|
|
192
207
|
& .crisp-datatable-entity-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
193
208
|
& .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
|
|
194
|
-
& .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
|
|
195
|
-
& .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
|
|
196
|
-
& .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
|
|
197
|
-
& .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
|
|
198
|
-
& .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
|
|
199
|
-
& .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
|
|
209
|
+
& .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); } & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); } & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); } & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); } & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); } & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
|
|
200
210
|
& .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
|
|
201
211
|
& .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
|
|
202
212
|
& .crisp-datatable-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); }
|
|
@@ -209,22 +219,26 @@
|
|
|
209
219
|
& .crisp-datatable-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)); }
|
|
210
220
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
211
221
|
& .crisp-datatable-muted { color: var(--crisp-fg-muted); }
|
|
212
|
-
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
213
|
-
|
|
222
|
+
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as TasksTable's own overdue due-date (crisp#462), plain text colour, no
|
|
223
|
+
fill/weight change. */
|
|
214
224
|
& .crisp-datatable-danger { color: var(--crisp-fg-danger); }
|
|
215
|
-
/* url/email cell types (#654) -- same measured values as RecordsTable's
|
|
216
|
-
own .crisp-recordstable-link, which this mirrors: no underline at
|
|
217
|
-
rest, underline on hover, own-colour text rather than a browser-blue
|
|
218
|
-
link. */
|
|
225
|
+
/* 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. */
|
|
219
226
|
& .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
220
227
|
& .crisp-datatable-link:hover { text-decoration: underline; }
|
|
221
|
-
/* phone cell type/editor (#765) -- measured live: the dial-code prefix
|
|
222
|
-
is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
|
|
223
|
-
value already measured elsewhere in this file. */
|
|
228
|
+
/* phone cell type/editor (#765) -- measured live: the dial-code prefix is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text value already measured elsewhere in this file. */
|
|
224
229
|
& .crisp-datatable-phone { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
225
230
|
& .crisp-datatable-phone-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
226
231
|
& .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); }
|
|
227
232
|
& .crisp-datatable-phone-editor input { flex: 1; min-width: 0; }
|
|
233
|
+
/* country-picker option row (#842) -- confirmed live: Attio's own popover
|
|
234
|
+
is plain text, no flag anywhere (not the option row, not the closed
|
|
235
|
+
trigger), name opaque + dial code muted rgba(0,0,0,0.63) -- the SAME
|
|
236
|
+
color-mix figure as -phone-dial above. The internal name/dial gap
|
|
237
|
+
wasn't independently measured this pass (Attio's own two <div>s gave
|
|
238
|
+
no exact number); reused space["1"], the same gap -phone already uses
|
|
239
|
+
for its own flag/dial/digits row. */
|
|
240
|
+
& .crisp-datatable-country-option { display: flex; align-items: center; gap: var(--crisp-space-1); }
|
|
241
|
+
& .crisp-datatable-country-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
228
242
|
/* multi-value phone (#816) -- confirmed live (a real custom "Multiple
|
|
229
243
|
values" Phone Number attribute, and the built-in People "Phone
|
|
230
244
|
numbers" field): the collapsed cell is a 4px-gap flex row of real
|
|
@@ -18,16 +18,32 @@ const config = defineRecipe({
|
|
|
18
18
|
radius, and datatable-grip and the embedded pickers zero theirs. An 8px
|
|
19
19
|
radius survived the chip-to-full-cell conversion and shipped rounded
|
|
20
20
|
until #282, so the spec check now guards it. */
|
|
21
|
-
/* The hit target is the WHOLE summary cell -- measured
|
|
21
|
+
/* The hit target is the WHOLE summary cell -- measured 246x36 with
|
|
22
22
|
padding 0 12px, not a content-sized chip. Clicking anywhere in the cell
|
|
23
|
-
opens the aggregation menu.
|
|
24
|
-
|
|
23
|
+
opens the aggregation menu.
|
|
24
|
+
No \`min-height\` (crisp#834, found reproducing the footer-row-38px-
|
|
25
|
+
not-36px bug in an isolated browser test, not table.recipe.ts's own
|
|
26
|
+
border/box-sizing, the hypothesis the issue itself flagged as
|
|
27
|
+
unconfirmed): the table cell's OWN \`height: tableRow\` (36px,
|
|
28
|
+
border-box) leaves 34px of content box once its 2px of top+bottom
|
|
29
|
+
border are counted, and \`min-height: tableRow\` here demanded 36px
|
|
30
|
+
of CONTENT height regardless -- overflowing the cell by 2px, which
|
|
31
|
+
auto-height table layout resolves by growing the whole row to fit,
|
|
32
|
+
landing at exactly the reported 38. \`height: 100%\` alone already
|
|
33
|
+
fills whatever the cell's real content box is (the doc comment above
|
|
34
|
+
this rule's own stated intent), with nothing left demanding more. */
|
|
35
|
+
& .crisp-columncalc-trigger { display: flex; align-items: center; gap: ${c.space["1"]}; width: 100%; height: 100%; margin: 0; padding: 0 ${c.space["3"]}; border: none; background: transparent; color: ${c.fgMuted}; font-family: inherit; font-size: ${c.text.lg}; font-weight: ${c.weight.medium}; white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
25
36
|
& .crisp-columncalc-trigger:hover { background: color-mix(in srgb, ${c.fgPrimary} 4%, transparent); color: ${c.fgPrimary}; }
|
|
26
37
|
& .crisp-columncalc-trigger svg { flex-shrink: 0; opacity: 0.7; }
|
|
27
38
|
& .crisp-columncalc-trigger[data-align="right"] { justify-content: flex-end; }
|
|
28
39
|
& .crisp-columncalc-placeholder { overflow: hidden; text-overflow: ellipsis; }
|
|
29
40
|
& .crisp-columncalc-value { color: ${c.fgPrimary}; font-variant-numeric: tabular-nums; }
|
|
30
|
-
|
|
41
|
+
/* crisp#837: re-measured live against Attio's real footer calc label --
|
|
42
|
+
14px (was 13px, \`c.text.md\`, fixed on the shared trigger rule above)
|
|
43
|
+
and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this
|
|
44
|
+
file's own -op label already should have used instead of the flatter
|
|
45
|
+
\`fgMuted\` token (a close but not measured match). */
|
|
46
|
+
& .crisp-columncalc-op { color: color-mix(in srgb, ${c.fgPrimary} 63%, transparent); }
|
|
31
47
|
& .crisp-columncalc-section { padding: ${c.space["1.5"]} ${c.space["2"]} ${c.space["1"]}; font-size: ${c.text.sm}; font-weight: ${c.weight.medium}; color: ${c.fgMuted}; }`,
|
|
32
48
|
variants: {},
|
|
33
49
|
defaultVariants: {},
|