@crisp-ui-kit/crisp 0.55.3 → 0.55.5
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/datatable/datatable.recipe.js +24 -2
- package/dist/cjs/components/table/table.recipe.js +17 -0
- package/dist/datatable.css +112 -90
- package/dist/datatable.layered.css +112 -90
- package/dist/esm/components/datatable/datatable.recipe.js +24 -2
- package/dist/esm/components/table/table.recipe.js +17 -0
- package/dist/styles.css +124 -90
- package/dist/styles.layered.css +124 -90
- package/dist/table.css +12 -0
- package/dist/table.layered.css +12 -0
- package/package.json +1 -1
|
@@ -135,7 +135,22 @@ const config = (0, core_1.defineRecipe)({
|
|
|
135
135
|
& .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: ${tokens_1.contract.fgPrimary}; }
|
|
136
136
|
/* sticky first column(s) + horizontal scroll shadow — RecordsTable's feel */
|
|
137
137
|
& th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: ${tokens_1.contract.bgSurface}; }
|
|
138
|
-
|
|
138
|
+
/* \`thead th[data-sticky]\`, not a bare \`th[data-sticky]\` (crisp#848, same
|
|
139
|
+
bare-\`th\` family as #829/#833/#835): this z-index:3 was written for
|
|
140
|
+
the HEADER's own sticky corner cell (sticky column x sticky header),
|
|
141
|
+
meant to win over everything else. Unscoped, it also matched the
|
|
142
|
+
primary column's BODY cell -- a real \`<th scope="row" data-sticky>\`
|
|
143
|
+
since #779 -- giving every scrolled body row's own sticky cell a
|
|
144
|
+
HIGHER z-index than the sticky FOOTER's (2), so it painted over the
|
|
145
|
+
footer instead of the footer showing through. Confirmed live on a
|
|
146
|
+
real bounded-height, 25-row table (GRC's Risk register): scrolled
|
|
147
|
+
partway, \`elementFromPoint\` at the footer's own on-screen cell
|
|
148
|
+
resolved to a body row's \`<th>\`, not the footer's \`<td>\`, and that
|
|
149
|
+
\`<th>\`'s computed z-index read 3. Scoped to \`thead\`, a body row's
|
|
150
|
+
own sticky \`<th>\` now falls back to the base rule above (z-index 1,
|
|
151
|
+
correct -- the same as a plain sticky \`<td>\`), and the footer's own
|
|
152
|
+
explicit z-index below is unaffected either way. */
|
|
153
|
+
& thead th[data-sticky] { z-index: 3; }
|
|
139
154
|
/* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
140
155
|
\`tfoot td { z-index: 2 }\`), which \`td[data-sticky]\`'s own higher-specificity
|
|
141
156
|
\`z-index: 1\` would otherwise undercut -- keep it level with the row it's in. */
|
|
@@ -267,7 +282,14 @@ const config = (0, core_1.defineRecipe)({
|
|
|
267
282
|
is rgba(0,0,0,0.09), a 9% tint, not the name's own full-contrast text
|
|
268
283
|
colour. The previous :hover-gated, full-contrast rule here was itself
|
|
269
284
|
unmeasured and wrong in two ways at once. */
|
|
270
|
-
|
|
285
|
+
/* crisp#851 -- Attio's own entity/record names are measured at
|
|
286
|
+
font-weight 500, distinct from a plain-text primary column's 400
|
|
287
|
+
(table.recipe.ts's own \`tbody th\` default). This was never its own
|
|
288
|
+
explicit style -- it silently rode on a since-fixed header-rule leak
|
|
289
|
+
(#833/#835/#848) that happened to apply the same 500 to every
|
|
290
|
+
primary-column body cell regardless of type. Made explicit here so
|
|
291
|
+
fixing that leak doesn't also (wrongly) drop entity names to 400. */
|
|
292
|
+
& .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: ${tokens_1.contract.weight.medium}; text-decoration: underline; text-decoration-color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 9%, transparent); }
|
|
271
293
|
& 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%; }
|
|
272
294
|
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary
|
|
273
295
|
column, revealed on ROW hover (the issue's own title says "row
|
|
@@ -48,6 +48,23 @@ const config = (0, core_1.defineRecipe)({
|
|
|
48
48
|
\`& table\`'s own color) applies to it like every other cell. */
|
|
49
49
|
& thead th { position: sticky; top: 0; z-index: 2; height: ${tokens_1.contract.size.tableHeader}; background: ${tokens_1.contract.bgSurface}; border-top: 1px solid ${tokens_1.contract.borderSubtle}; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; letter-spacing: -0.14px; color: ${tokens_1.contract.fgPrimary}; user-select: none; }
|
|
50
50
|
& td { color: ${tokens_1.contract.fgPrimary}; background: ${tokens_1.contract.bgSurface}; }
|
|
51
|
+
/* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the
|
|
52
|
+
header rule above to \`thead th\` correctly stopped it leaking onto
|
|
53
|
+
the primary column's body cell (a real \`<th scope="row">\` since
|
|
54
|
+
#779), but that same leaked rule's \`font-weight: ${tokens_1.contract.weight.medium}\`
|
|
55
|
+
was the ONLY thing overriding the browser's own UA stylesheet default
|
|
56
|
+
for \`<th>\` (\`font-weight: bold; text-align: center\`) on that cell --
|
|
57
|
+
once the leak stopped, a plain-text primary column fell through to
|
|
58
|
+
bold+centred instead of matching its sibling \`<td>\`s (\`400\`/start,
|
|
59
|
+
Attio's own plain-text primary cell). \`text-align\` was already safe
|
|
60
|
+
(the base \`& th, & td\` rule's own \`text-align: start\` above is
|
|
61
|
+
author-origin and always beats the UA stylesheet regardless of
|
|
62
|
+
specificity) but is restated here explicitly, defensively -- cheap,
|
|
63
|
+
and removes any doubt. \`type: "entity"\` primary columns are a
|
|
64
|
+
separate case (Attio's own entity/record names are 500, not 400) --
|
|
65
|
+
see \`.crisp-datatable-entity-name\`'s own new explicit weight in
|
|
66
|
+
datatable.recipe.ts, which wins here by class specificity. */
|
|
67
|
+
& tbody th { font-weight: ${tokens_1.contract.weight.regular}; text-align: start; }
|
|
51
68
|
& th:last-child, & td:last-child { border-inline-end: none; }
|
|
52
69
|
& tbody tr:last-child td { border-bottom: none; }
|
|
53
70
|
/* #554: sticky to the bottom, mirroring \`.crisp-recordstable-sum\`. */
|
package/dist/datatable.css
CHANGED
|
@@ -87,11 +87,19 @@
|
|
|
87
87
|
& .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: var(--crisp-fg-primary); }
|
|
88
88
|
/* sticky first column(s) + horizontal scroll shadow — RecordsTable's feel */
|
|
89
89
|
& th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: var(--crisp-bg-surface); }
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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; }
|
|
101
|
+
/* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
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. */
|
|
95
103
|
& tfoot td[data-sticky] { z-index: 2; }
|
|
96
104
|
& tbody tr[data-selected] td[data-sticky] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
97
105
|
& tbody tr:hover td[data-sticky] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
|
|
@@ -108,103 +116,101 @@
|
|
|
108
116
|
& tbody tr[data-selected] td { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
109
117
|
& 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))); }
|
|
110
118
|
& .crisp-datatable-editable:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); cursor: text; }
|
|
111
|
-
/* crisp/#758: AI-enriched column marker, ported from RecordsTable's own
|
|
112
|
-
|
|
119
|
+
/* crisp/#758: AI-enriched column marker, ported from RecordsTable's own
|
|
120
|
+
already-measured value -- a full-bleed #9b69ff (bgPurple) wash at 4%,
|
|
121
|
+
composited OVER whatever row-state background the cell already has
|
|
122
|
+
(hover, selected), which is why it's an ::after overlay and not a plain background. */
|
|
113
123
|
& td[data-enriched]::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: color-mix(in srgb, var(--crisp-bg-purple) 4%, transparent); }
|
|
114
124
|
& .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; }
|
|
115
125
|
& .crisp-datatable-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
116
|
-
/* An async onEdit's in-flight state (#385) -- the field/picker dims and
|
|
126
|
+
/* An async onEdit's in-flight state (#385) -- the field/picker dims and
|
|
127
|
+
stops accepting input rather than disappearing, so the just-typed or
|
|
128
|
+
just-chosen value stays visible while its commit is pending. Same
|
|
129
|
+
treatment Input already gives its own disabled state. */
|
|
117
130
|
& .crisp-datatable-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
118
131
|
& .crisp-datatable-edit-pending { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); color: var(--crisp-fg-muted); vertical-align: middle; }
|
|
119
|
-
/* The rejection's message, beside the cell's own content -- a sibling in
|
|
120
|
-
hover-only wrapper (a Tooltip, say) around a custom render can't hide
|
|
121
|
-
|
|
132
|
+
/* The rejection's message, beside the cell's own content -- a sibling in
|
|
133
|
+
the TableCell, never nested inside a column's own render output, so a hover-only wrapper (a Tooltip, say) around a custom render can't hide
|
|
134
|
+
it. Block-level: the row grows to fit it rather than floating over
|
|
135
|
+
the row below, so it can never end up clipped by the scroll
|
|
136
|
+
container's overflow the way a position:fixed escape would need guarding against. */
|
|
122
137
|
& .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); }
|
|
123
|
-
/* editor: "select"/"switch" -- always live, no separate edit mode, so
|
|
124
|
-
|
|
125
|
-
RecordsTable's own --picker cells (measured there already; DataTable shares RecordsTable's grid, Golden Rule 0). */
|
|
138
|
+
/* editor: "select"/"switch" -- always live, no separate edit mode, so the cell IS the picker: same chromeless-fill treatment as RecordsTable's own --picker cells (measured there already; DataTable
|
|
139
|
+
shares RecordsTable's grid, Golden Rule 0). */
|
|
126
140
|
& .crisp-datatable-td--picker { padding: 0; }
|
|
127
141
|
& .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); }
|
|
128
142
|
& .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; }
|
|
129
143
|
& .crisp-datatable-td--picker .crisp-datatable-edit-error { padding-inline-start: var(--crisp-space-2); }
|
|
130
|
-
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
131
|
-
"Create X" row when the consumer supplies one (#449) -- same measured
|
|
132
|
-
values as RecordsTable's own .crisp-recordstable-refoption*. */
|
|
144
|
+
/* reference picker: a leading 16px avatar per option, plus a trailing "Create X" row when the consumer supplies one (#449) -- same measured values as RecordsTable's own .crisp-recordstable-refoption*. */
|
|
133
145
|
& .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
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
|
-
/* #826 -- the full-body loading state (a filter/sort re-query, or a
|
|
138
|
-
triggers: icon+text centred in the row-body area, 10px gap, 14px/500
|
|
139
|
-
weight/20px line-height, both icon and text in the SAME muted
|
|
140
|
-
rgba(0,0,0,0.63) -- the same color-mix figure this file already uses
|
|
141
|
-
for other muted text (e.g. -phone-dial). Distinct from the cold
|
|
142
|
-
in-place row load (blank, no indicator) and the warm-navigation
|
|
143
|
-
per-cell shimmer (#599) -- neither of those swaps the whole body. */
|
|
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. */
|
|
144
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; }
|
|
145
152
|
& .crisp-datatable-loading .crisp-spinner { border-top-color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
146
|
-
/* #579: click-to-expand overlay for a truncated cell -- a read-only,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
core, not this cell), so growing a row here would fight it. Anchored
|
|
153
|
-
to the SAME column width the cell itself renders at (measured:
|
|
154
|
-
Attio's own overlay came out only slightly wider than the triggering cell's clientWidth -- the overshoot is this padding),
|
|
155
|
-
wrapping onto as many lines as the value needs; it CAN be clipped by
|
|
156
|
-
`.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. */
|
|
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. */
|
|
157
159
|
& td[data-cell-expanded] { overflow: visible; z-index: 7; }
|
|
158
|
-
& .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
|
+
}
|
|
159
167
|
/* fixed layout so column widths (and resize) are exact — like RecordsTable */
|
|
160
168
|
& table { table-layout: fixed; }
|
|
161
|
-
/* 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. */
|
|
162
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; }
|
|
163
174
|
/* column resize grip */
|
|
164
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; }
|
|
165
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; }
|
|
166
177
|
& .crisp-datatable-resize:hover::after, & .crisp-datatable-resize[data-resizing]::after { opacity: 1; }
|
|
167
|
-
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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. */
|
|
171
183
|
& th[data-dragging] { cursor: pointer; }
|
|
172
|
-
& th[data-drop-before]::before, & th[data-drop-after]::after {
|
|
173
|
-
content: ""; position: absolute; top: 0; width: 3px; height: 100%;
|
|
174
|
-
background: var(--crisp-bg-brand-solid); z-index: 6; pointer-events: none;
|
|
175
|
-
}
|
|
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; }
|
|
176
185
|
& th[data-drop-before]::before { inset-inline-start: -1.5px; }
|
|
177
186
|
& th[data-drop-after]::after { inset-inline-end: -1.5px; }
|
|
178
187
|
/* typed cells — entity (avatar + name), colour-coded tags, numbers, dates */
|
|
179
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); }
|
|
180
|
-
/* crisp/#601 supersession follow-up -- the same flex-row shape
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
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. */
|
|
184
192
|
& .crisp-datatable-cell-actions-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; width: 100%; }
|
|
185
|
-
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text,
|
|
186
|
-
|
|
187
|
-
colour. The previous :hover-gated, full-contrast rule here was itself
|
|
188
|
-
|
|
189
|
-
|
|
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. */ /* crisp#851 -- Attio's own entity/record names are measured at
|
|
196
|
+
font-weight 500, distinct from a plain-text primary column's 400 (table.recipe.ts's own `tbody th` default). This was never its own
|
|
197
|
+
explicit style -- it silently rode on a since-fixed header-rule leak
|
|
198
|
+
(#833/#835/#848) that happened to apply the same 500 to every
|
|
199
|
+
primary-column body cell regardless of type. Made explicit here so
|
|
200
|
+
fixing that leak doesn't also (wrongly) drop entity names to 400. */
|
|
201
|
+
& .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--crisp-weight-medium); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
|
|
190
202
|
& 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%; }
|
|
191
|
-
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
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. */
|
|
203
|
+
/* 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
|
|
204
|
+
hover", and a live check confirmed hovering well past the name --
|
|
205
|
+
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
|
|
206
|
+
expressed as color-mix against fgPrimary so they stay correct in
|
|
207
|
+
dark mode instead of a literal black that would invert. */
|
|
197
208
|
& .crisp-datatable-entity-actions { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
198
209
|
& tr:hover .crisp-datatable-entity-actions, & .crisp-datatable-entity-actions:focus-within { opacity: 1; }
|
|
199
210
|
& .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; }
|
|
200
211
|
& .crisp-datatable-entity-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
201
212
|
& .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); }
|
|
202
|
-
& .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
|
|
203
|
-
& .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
|
|
204
|
-
& .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
|
|
205
|
-
& .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
|
|
206
|
-
& .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
|
|
207
|
-
& .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
|
|
213
|
+
& .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); }
|
|
208
214
|
& .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
|
|
209
215
|
& .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
|
|
210
216
|
& .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); }
|
|
@@ -217,58 +223,74 @@
|
|
|
217
223
|
& .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)); }
|
|
218
224
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
219
225
|
& .crisp-datatable-muted { color: var(--crisp-fg-muted); }
|
|
220
|
-
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
221
|
-
|
|
226
|
+
/* 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
|
|
227
|
+
fill/weight change. */
|
|
222
228
|
& .crisp-datatable-danger { color: var(--crisp-fg-danger); }
|
|
223
|
-
/* url/email cell types (#654) -- same measured values as RecordsTable's
|
|
224
|
-
own .crisp-recordstable-link, which this mirrors: no underline at
|
|
225
|
-
rest, underline on hover, own-colour text rather than a browser-blue
|
|
226
|
-
link. */
|
|
229
|
+
/* 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. */
|
|
227
230
|
& .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
228
231
|
& .crisp-datatable-link:hover { text-decoration: underline; }
|
|
229
|
-
/* phone cell type/editor (#765) -- measured live: the dial-code prefix
|
|
230
|
-
is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
|
|
231
|
-
value already measured elsewhere in this file. */
|
|
232
|
+
/* 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. */
|
|
232
233
|
& .crisp-datatable-phone { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
233
234
|
& .crisp-datatable-phone-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
234
235
|
& .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); }
|
|
235
236
|
& .crisp-datatable-phone-editor input { flex: 1; min-width: 0; }
|
|
236
|
-
/* country-picker option row (#842) -- confirmed live: Attio's own popover
|
|
237
|
+
/* country-picker option row (#842) -- confirmed live: Attio's own popover
|
|
238
|
+
is plain text, no flag anywhere (not the option row, not the closed
|
|
239
|
+
trigger), name opaque + dial code muted rgba(0,0,0,0.63) -- the SAME
|
|
240
|
+
color-mix figure as -phone-dial above. The internal name/dial gap
|
|
241
|
+
wasn't independently measured this pass (Attio's own two <div>s gave
|
|
242
|
+
no exact number); reused space["1"], the same gap -phone already uses
|
|
243
|
+
for its own flag/dial/digits row. */
|
|
237
244
|
& .crisp-datatable-country-option { display: flex; align-items: center; gap: var(--crisp-space-1); }
|
|
238
245
|
& .crisp-datatable-country-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
239
246
|
/* multi-value phone (#816) -- confirmed live (a real custom "Multiple
|
|
240
247
|
values" Phone Number attribute, and the built-in People "Phone
|
|
241
|
-
numbers" field): the collapsed cell is a 4px-gap flex row of real
|
|
248
|
+
numbers" field): the collapsed cell is a 4px-gap flex row of real
|
|
249
|
+
tel: links in a measured link blue (~rgb(59,108,232) pixel-sampled;
|
|
250
|
+
reused as the closest already-tokened blue, brand600, rather than
|
|
251
|
+
adding a third blue token for a delta this small), underlined,
|
|
252
|
+
UNLIKE the single-value cell above (plain text, no link, no
|
|
253
|
+
underline) -- multi-value is the one shape Attio makes into a real
|
|
254
|
+
link. The cell hard-clips on overflow (no ellipsis -- confirmed
|
|
255
|
+
live, a second value can end mid-digit with no "..."). */
|
|
242
256
|
& .crisp-datatable-phone-multi { display: inline-flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
|
|
243
257
|
& .crisp-datatable-phone-link { color: var(--crisp-bg-brand-solid); text-decoration: underline; white-space: nowrap; }
|
|
244
|
-
/* multi-value editor (#816) -- confirmed live: a stack of committed-
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
/* multi-value editor (#816) -- confirmed live: a stack of committed-
|
|
259
|
+
value rows (32px = size.menuRow, 5px 8px padding, 8px gap between
|
|
260
|
+
the grip/value/actions, 16px icons) above one ALWAYS-blank trailing
|
|
261
|
+
DataPhoneEditor-shaped row -- that blank row is the only "add
|
|
262
|
+
another" affordance, there's no separate button for it. The copy/delete pair reuses .crisp-datatable-entity-action's own
|
|
263
|
+
hover-reveal chrome (not independently re-measured as its own hit
|
|
264
|
+
target this pass, only the 16px icon glyphs were). */
|
|
247
265
|
& .crisp-datatable-phone-multi-editor { display: flex; flex-direction: column; }
|
|
248
266
|
& .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); }
|
|
249
267
|
& .crisp-datatable-phone-multi-row .crisp-datatable-phone-link { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
250
268
|
& .crisp-datatable-phone-multi-grip { color: var(--crisp-fg-muted); flex-shrink: 0; cursor: grab; }
|
|
251
269
|
& .crisp-datatable-phone-multi-actions { display: flex; align-items: center; gap: var(--crisp-space-1); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
252
|
-
& .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions,
|
|
270
|
+
& .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions,
|
|
271
|
+
& .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
|
|
253
272
|
& .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; }
|
|
254
273
|
& .crisp-datatable-phone-multi-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
255
274
|
/* datetime cell editor (#762) -- DatePickerField + TimePicker side by side. */
|
|
256
275
|
& .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); }
|
|
257
|
-
/* rating cell type/editor (#760) -- measured live: 16px stars on an
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
276
|
+
/* rating cell type/editor (#760) -- measured live: 16px stars on an
|
|
277
|
+
18px pitch (a 2px gap), an empty star at rgba(0,0,0,0.1), a
|
|
278
|
+
committed/filled star at brand600 (--crisp-bg-brand-solid, an exact
|
|
279
|
+
match to the measured #266df0), and a distinct hover-preview colour
|
|
280
|
+
-- 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
|
|
281
|
+
crisp-datatable-rating-star class on the svg itself (not the
|
|
282
|
+
button), so one set of fill rules covers both -- the button only
|
|
283
|
+
adds its own reset + cursor via a separate -btn class. */
|
|
261
284
|
& .crisp-datatable-rating { display: inline-flex; align-items: center; gap: 2px; }
|
|
262
285
|
& .crisp-datatable-rating-star { display: block; }
|
|
263
286
|
& .crisp-datatable-rating-star path { fill: rgba(0, 0, 0, 0.1); }
|
|
264
287
|
& .crisp-datatable-rating-star[data-filled] path { fill: var(--crisp-bg-brand-solid); }
|
|
265
288
|
& .crisp-datatable-rating-star[data-hovering] path { fill: #215bc4; }
|
|
266
289
|
& .crisp-datatable-rating-star-btn { display: inline-flex; padding: 0; margin: 0; border: none; background: none; font-family: inherit; cursor: pointer; }
|
|
267
|
-
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
|
|
268
|
-
hairline doubling as the drop indicator (it tints toward the brand
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
pointer-events implementation. */
|
|
290
|
+
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
|
|
291
|
+
a leading 20px grip column, a 16px grip icon, and the row's own hairline doubling as the drop indicator (it tints toward the brand colour as the active drop target). The affordance + geometry are measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
|
|
292
|
+
draggable + dataTransfer, the same one column reorder already uses
|
|
293
|
+
(RecordsTable's reorderColumn) -- not a proprietary pointer-events implementation. */
|
|
272
294
|
& .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
|
|
273
295
|
& .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; }
|
|
274
296
|
& .crisp-datatable-grip:active { cursor: grabbing; }
|