@crisp-ui-kit/crisp 0.52.1 → 0.52.2
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/product/recordpage/recordpage.js +86 -7
- package/dist/cjs/product/recordpage/recordpage.recipe.js +7 -0
- package/dist/esm/product/recordpage/recordpage.js +86 -7
- package/dist/esm/product/recordpage/recordpage.recipe.js +7 -0
- package/dist/recordpage.css +18 -1
- package/dist/recordpage.layered.css +18 -1
- package/dist/styles.css +18 -1
- package/dist/styles.layered.css +18 -1
- package/package.json +1 -1
|
@@ -125,6 +125,53 @@ exports.recordPageLabels = {
|
|
|
125
125
|
recordCreated: (name) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("b", { children: name }), " record was created"] })),
|
|
126
126
|
noEmailsWith: (name) => (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["No emails logged with ", name, " yet."] }),
|
|
127
127
|
};
|
|
128
|
+
/** `Select` owns its own closed-by-default `open` state with no prop or
|
|
129
|
+
* imperative way to start it open -- the only thing that opens it is a real
|
|
130
|
+
* click on its trigger button. Mounting one on click (rather than rendering
|
|
131
|
+
* it already open) leaves the reader with a second click to make before
|
|
132
|
+
* they can pick anything, so drive that click ourselves the moment it
|
|
133
|
+
* mounts. Mirrors `DataTable`'s own `useAutoOpenSelect` (#453) -- kept as
|
|
134
|
+
* its own copy here rather than a shared import, the same "duplicated per
|
|
135
|
+
* product surface" choice already made for `EditableOption`/
|
|
136
|
+
* `editableInputType` above. Guarded against firing twice (StrictMode
|
|
137
|
+
* double-invokes effects): `Select`'s own trigger toggles, so a second
|
|
138
|
+
* click would close what the first one opened. */
|
|
139
|
+
function useAutoOpenSelect() {
|
|
140
|
+
const ref = React.useRef(null);
|
|
141
|
+
const opened = React.useRef(false);
|
|
142
|
+
React.useEffect(() => {
|
|
143
|
+
if (opened.current)
|
|
144
|
+
return;
|
|
145
|
+
opened.current = true;
|
|
146
|
+
ref.current
|
|
147
|
+
?.querySelector(".crisp-select-trigger")
|
|
148
|
+
?.click();
|
|
149
|
+
}, []);
|
|
150
|
+
return ref;
|
|
151
|
+
}
|
|
152
|
+
/** `Select` closes its own popover on Escape but has no callback telling
|
|
153
|
+
* the FIELD to leave editing mode -- and DOM focus doesn't reliably end up
|
|
154
|
+
* inside the newly-opened popover either, so a focus-dependent React
|
|
155
|
+
* `onKeyDown` can't be trusted to see the key at all. Mirrors `Select`'s
|
|
156
|
+
* own "document-level fallback for Escape" (see select.tsx) and
|
|
157
|
+
* `DataTable`'s identical fix for the same problem (#453). */
|
|
158
|
+
function useEscapeExitsEditing(onCancel) {
|
|
159
|
+
React.useEffect(() => {
|
|
160
|
+
const onKey = (e) => {
|
|
161
|
+
if (e.key === "Escape")
|
|
162
|
+
onCancel();
|
|
163
|
+
};
|
|
164
|
+
document.addEventListener("keydown", onKey);
|
|
165
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
166
|
+
}, [onCancel]);
|
|
167
|
+
}
|
|
168
|
+
/** `editor: "select"`'s picker, its own component (not inline in the field
|
|
169
|
+
* loop) because it needs the two hooks above (#457). */
|
|
170
|
+
function RecordPageSelectEditor({ col, value, isPending, onCommit, onCancel, }) {
|
|
171
|
+
const ref = useAutoOpenSelect();
|
|
172
|
+
useEscapeExitsEditing(onCancel);
|
|
173
|
+
return ((0, jsx_runtime_1.jsxs)("span", { ref: ref, className: "crisp-recordpage-edit-picker", children: [(0, jsx_runtime_1.jsx)(select_1.Select, { variant: "ghost", "aria-label": `Edit ${col.label}`, value: value != null ? String(value) : undefined, disabled: isPending, options: col.editOptions ?? [], onValueChange: onCommit }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-recordpage-edit-pending" }))] }));
|
|
174
|
+
}
|
|
128
175
|
function TagsValue({ values }) {
|
|
129
176
|
const [expanded, setExpanded] = React.useState(false);
|
|
130
177
|
const overflow = values.length - 1;
|
|
@@ -135,6 +182,21 @@ function FieldValue({ col, row, labels, }) {
|
|
|
135
182
|
const v = row[col.key];
|
|
136
183
|
if (valueEmpty(v))
|
|
137
184
|
return (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-empty", children: labels.setAValue });
|
|
185
|
+
// `editor: "select"` at rest (#457) -- checked ahead of `col.type` since
|
|
186
|
+
// the editor is orthogonal to it. Same dot+label shape as RecordsTable's
|
|
187
|
+
// own measured status chip, but this component's own classes
|
|
188
|
+
// (`crisp-recordpage-status[-dot]`): RecordsTable's own pair is scoped
|
|
189
|
+
// under `.crisp-recordstable`'s recipe root, so reusing its classnames
|
|
190
|
+
// verbatim here would resolve to nothing. Shown when the matched option
|
|
191
|
+
// carries a `color`, same as every other status-shaped value in this
|
|
192
|
+
// codebase; a colourless option (or no match) falls back to plain text.
|
|
193
|
+
if (col.editor === "select") {
|
|
194
|
+
const opt = col.editOptions?.find((o) => o.value === v);
|
|
195
|
+
const text = opt?.label ?? String(v);
|
|
196
|
+
if (!opt?.color)
|
|
197
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: text });
|
|
198
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-status", children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-status-dot", style: { background: opt.color } }), text] }));
|
|
199
|
+
}
|
|
138
200
|
switch (col.type) {
|
|
139
201
|
case "tags":
|
|
140
202
|
return (0, jsx_runtime_1.jsx)(TagsValue, { values: v });
|
|
@@ -455,14 +517,31 @@ function RecordPage({ record, columns, collection = "Records", labels, onBack, o
|
|
|
455
517
|
const isPending = pendingKey === col.key;
|
|
456
518
|
const fieldError = error?.key === col.key ? error.message : null;
|
|
457
519
|
const label = ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-field-label", children: [col.icon ? ((0, jsx_runtime_1.jsx)(col.icon, { size: 15, strokeWidth: 1.75 })) : null, (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-field-label-text", children: col.label })] }));
|
|
458
|
-
//
|
|
459
|
-
// click-to-open, no separate edit/view mode
|
|
460
|
-
//
|
|
461
|
-
//
|
|
462
|
-
//
|
|
463
|
-
if (canEdit && col.editor) {
|
|
520
|
+
// `switch` is always its own live widget -- no
|
|
521
|
+
// click-to-open, no separate edit/view mode: flipping the
|
|
522
|
+
// toggle IS the commit gesture, and there's no
|
|
523
|
+
// meaningfully different "rest" display for a boolean
|
|
524
|
+
// (same exception `DataTable`'s own `editor` makes, #453).
|
|
525
|
+
if (canEdit && col.editor === "switch") {
|
|
526
|
+
const value = record[col.key];
|
|
527
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-field", children: [label, (0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-field-value", children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-edit-picker", children: [(0, jsx_runtime_1.jsx)(switch_1.Switch, { "aria-label": `Edit ${col.label}`, checked: value === true || value === "true", disabled: isPending, onCheckedChange: (checked) => commit(record.id, col.key, String(checked)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-recordpage-edit-pending" }))] }), fieldError && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-edit-error", children: fieldError }))] })] }, col.key));
|
|
528
|
+
}
|
|
529
|
+
// `select` opens crisp's own `Select` on a SINGLE click
|
|
530
|
+
// (#457, corrects #431/#385's original always-live
|
|
531
|
+
// copy of the same regression #453 fixed on `DataTable`)
|
|
532
|
+
// -- like every other editable type here, at rest it
|
|
533
|
+
// shows its value (see `FieldValue`'s own `col.editor
|
|
534
|
+
// === "select"` case) via the generic click-to-open
|
|
535
|
+
// branch below, and only mounts `Select` once
|
|
536
|
+
// `editingKey` matches. `DataTable`'s own double-click
|
|
537
|
+
// gate doesn't apply: `RecordPage`'s plain text/date
|
|
538
|
+
// fields already open on a single click (measured live
|
|
539
|
+
// for #431), so `select` matches that, not `DataTable`.
|
|
540
|
+
if (canEdit &&
|
|
541
|
+
editingKey === col.key &&
|
|
542
|
+
col.editor === "select") {
|
|
464
543
|
const value = record[col.key];
|
|
465
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-field", children: [label, (0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-field-value", children: [(0, jsx_runtime_1.
|
|
544
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-field", children: [label, (0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-field-value", children: [(0, jsx_runtime_1.jsx)(RecordPageSelectEditor, { col: col, value: value, isPending: isPending, onCommit: (v) => commit(record.id, col.key, v), onCancel: closeEditing }), fieldError && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-edit-error", children: fieldError }))] })] }, col.key));
|
|
466
545
|
}
|
|
467
546
|
if (canEdit && editingKey === col.key) {
|
|
468
547
|
const value = record[col.key];
|
|
@@ -108,6 +108,13 @@ const config = (0, core_1.defineRecipe)({
|
|
|
108
108
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
109
109
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: ${tokens_1.contract.fgMuted}; }
|
|
110
110
|
& .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: ${tokens_1.contract.space["0.5"]}; font-size: ${tokens_1.contract.text.sm}; color: ${tokens_1.contract.bgDanger}; }
|
|
111
|
+
/* #457: an \`editor: "select"\` field's at-rest chip -- same shape as
|
|
112
|
+
RecordsTable's own \`.crisp-recordstable-status[-dot]\` (already
|
|
113
|
+
measured against Attio there), but its own classes: that pair is
|
|
114
|
+
scoped under \`.crisp-recordstable\`'s own recipe root, so reusing the
|
|
115
|
+
classnames verbatim here would resolve to nothing. */
|
|
116
|
+
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; min-width: 0; }
|
|
117
|
+
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: ${tokens_1.contract.radius.full}; }
|
|
111
118
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: ${tokens_1.contract.space["1"]}; width: 100%; }
|
|
112
119
|
& .crisp-recordpage-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; }
|
|
113
120
|
& .crisp-recordpage-link { color: ${tokens_1.contract.fgPrimary}; text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
@@ -88,6 +88,53 @@ export const recordPageLabels = {
|
|
|
88
88
|
recordCreated: (name) => (_jsxs(_Fragment, { children: [_jsx("b", { children: name }), " record was created"] })),
|
|
89
89
|
noEmailsWith: (name) => _jsxs(_Fragment, { children: ["No emails logged with ", name, " yet."] }),
|
|
90
90
|
};
|
|
91
|
+
/** `Select` owns its own closed-by-default `open` state with no prop or
|
|
92
|
+
* imperative way to start it open -- the only thing that opens it is a real
|
|
93
|
+
* click on its trigger button. Mounting one on click (rather than rendering
|
|
94
|
+
* it already open) leaves the reader with a second click to make before
|
|
95
|
+
* they can pick anything, so drive that click ourselves the moment it
|
|
96
|
+
* mounts. Mirrors `DataTable`'s own `useAutoOpenSelect` (#453) -- kept as
|
|
97
|
+
* its own copy here rather than a shared import, the same "duplicated per
|
|
98
|
+
* product surface" choice already made for `EditableOption`/
|
|
99
|
+
* `editableInputType` above. Guarded against firing twice (StrictMode
|
|
100
|
+
* double-invokes effects): `Select`'s own trigger toggles, so a second
|
|
101
|
+
* click would close what the first one opened. */
|
|
102
|
+
function useAutoOpenSelect() {
|
|
103
|
+
const ref = React.useRef(null);
|
|
104
|
+
const opened = React.useRef(false);
|
|
105
|
+
React.useEffect(() => {
|
|
106
|
+
if (opened.current)
|
|
107
|
+
return;
|
|
108
|
+
opened.current = true;
|
|
109
|
+
ref.current
|
|
110
|
+
?.querySelector(".crisp-select-trigger")
|
|
111
|
+
?.click();
|
|
112
|
+
}, []);
|
|
113
|
+
return ref;
|
|
114
|
+
}
|
|
115
|
+
/** `Select` closes its own popover on Escape but has no callback telling
|
|
116
|
+
* the FIELD to leave editing mode -- and DOM focus doesn't reliably end up
|
|
117
|
+
* inside the newly-opened popover either, so a focus-dependent React
|
|
118
|
+
* `onKeyDown` can't be trusted to see the key at all. Mirrors `Select`'s
|
|
119
|
+
* own "document-level fallback for Escape" (see select.tsx) and
|
|
120
|
+
* `DataTable`'s identical fix for the same problem (#453). */
|
|
121
|
+
function useEscapeExitsEditing(onCancel) {
|
|
122
|
+
React.useEffect(() => {
|
|
123
|
+
const onKey = (e) => {
|
|
124
|
+
if (e.key === "Escape")
|
|
125
|
+
onCancel();
|
|
126
|
+
};
|
|
127
|
+
document.addEventListener("keydown", onKey);
|
|
128
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
129
|
+
}, [onCancel]);
|
|
130
|
+
}
|
|
131
|
+
/** `editor: "select"`'s picker, its own component (not inline in the field
|
|
132
|
+
* loop) because it needs the two hooks above (#457). */
|
|
133
|
+
function RecordPageSelectEditor({ col, value, isPending, onCommit, onCancel, }) {
|
|
134
|
+
const ref = useAutoOpenSelect();
|
|
135
|
+
useEscapeExitsEditing(onCancel);
|
|
136
|
+
return (_jsxs("span", { ref: ref, className: "crisp-recordpage-edit-picker", children: [_jsx(Select, { variant: "ghost", "aria-label": `Edit ${col.label}`, value: value != null ? String(value) : undefined, disabled: isPending, options: col.editOptions ?? [], onValueChange: onCommit }), isPending && (_jsx(Spinner, { size: 14, className: "crisp-recordpage-edit-pending" }))] }));
|
|
137
|
+
}
|
|
91
138
|
function TagsValue({ values }) {
|
|
92
139
|
const [expanded, setExpanded] = React.useState(false);
|
|
93
140
|
const overflow = values.length - 1;
|
|
@@ -98,6 +145,21 @@ function FieldValue({ col, row, labels, }) {
|
|
|
98
145
|
const v = row[col.key];
|
|
99
146
|
if (valueEmpty(v))
|
|
100
147
|
return _jsx("span", { className: "crisp-recordpage-empty", children: labels.setAValue });
|
|
148
|
+
// `editor: "select"` at rest (#457) -- checked ahead of `col.type` since
|
|
149
|
+
// the editor is orthogonal to it. Same dot+label shape as RecordsTable's
|
|
150
|
+
// own measured status chip, but this component's own classes
|
|
151
|
+
// (`crisp-recordpage-status[-dot]`): RecordsTable's own pair is scoped
|
|
152
|
+
// under `.crisp-recordstable`'s recipe root, so reusing its classnames
|
|
153
|
+
// verbatim here would resolve to nothing. Shown when the matched option
|
|
154
|
+
// carries a `color`, same as every other status-shaped value in this
|
|
155
|
+
// codebase; a colourless option (or no match) falls back to plain text.
|
|
156
|
+
if (col.editor === "select") {
|
|
157
|
+
const opt = col.editOptions?.find((o) => o.value === v);
|
|
158
|
+
const text = opt?.label ?? String(v);
|
|
159
|
+
if (!opt?.color)
|
|
160
|
+
return _jsx(_Fragment, { children: text });
|
|
161
|
+
return (_jsxs("span", { className: "crisp-recordpage-status", children: [_jsx("span", { className: "crisp-recordpage-status-dot", style: { background: opt.color } }), text] }));
|
|
162
|
+
}
|
|
101
163
|
switch (col.type) {
|
|
102
164
|
case "tags":
|
|
103
165
|
return _jsx(TagsValue, { values: v });
|
|
@@ -418,14 +480,31 @@ export function RecordPage({ record, columns, collection = "Records", labels, on
|
|
|
418
480
|
const isPending = pendingKey === col.key;
|
|
419
481
|
const fieldError = error?.key === col.key ? error.message : null;
|
|
420
482
|
const label = (_jsxs("span", { className: "crisp-recordpage-field-label", children: [col.icon ? (_jsx(col.icon, { size: 15, strokeWidth: 1.75 })) : null, _jsx("span", { className: "crisp-recordpage-field-label-text", children: col.label })] }));
|
|
421
|
-
//
|
|
422
|
-
// click-to-open, no separate edit/view mode
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
if (canEdit && col.editor) {
|
|
483
|
+
// `switch` is always its own live widget -- no
|
|
484
|
+
// click-to-open, no separate edit/view mode: flipping the
|
|
485
|
+
// toggle IS the commit gesture, and there's no
|
|
486
|
+
// meaningfully different "rest" display for a boolean
|
|
487
|
+
// (same exception `DataTable`'s own `editor` makes, #453).
|
|
488
|
+
if (canEdit && col.editor === "switch") {
|
|
489
|
+
const value = record[col.key];
|
|
490
|
+
return (_jsxs("div", { className: "crisp-recordpage-field", children: [label, _jsxs("span", { className: "crisp-recordpage-field-value", children: [_jsxs("span", { className: "crisp-recordpage-edit-picker", children: [_jsx(Switch, { "aria-label": `Edit ${col.label}`, checked: value === true || value === "true", disabled: isPending, onCheckedChange: (checked) => commit(record.id, col.key, String(checked)) }), isPending && (_jsx(Spinner, { size: 14, className: "crisp-recordpage-edit-pending" }))] }), fieldError && (_jsx("span", { className: "crisp-recordpage-edit-error", children: fieldError }))] })] }, col.key));
|
|
491
|
+
}
|
|
492
|
+
// `select` opens crisp's own `Select` on a SINGLE click
|
|
493
|
+
// (#457, corrects #431/#385's original always-live
|
|
494
|
+
// copy of the same regression #453 fixed on `DataTable`)
|
|
495
|
+
// -- like every other editable type here, at rest it
|
|
496
|
+
// shows its value (see `FieldValue`'s own `col.editor
|
|
497
|
+
// === "select"` case) via the generic click-to-open
|
|
498
|
+
// branch below, and only mounts `Select` once
|
|
499
|
+
// `editingKey` matches. `DataTable`'s own double-click
|
|
500
|
+
// gate doesn't apply: `RecordPage`'s plain text/date
|
|
501
|
+
// fields already open on a single click (measured live
|
|
502
|
+
// for #431), so `select` matches that, not `DataTable`.
|
|
503
|
+
if (canEdit &&
|
|
504
|
+
editingKey === col.key &&
|
|
505
|
+
col.editor === "select") {
|
|
427
506
|
const value = record[col.key];
|
|
428
|
-
return (_jsxs("div", { className: "crisp-recordpage-field", children: [label, _jsxs("span", { className: "crisp-recordpage-field-value", children: [
|
|
507
|
+
return (_jsxs("div", { className: "crisp-recordpage-field", children: [label, _jsxs("span", { className: "crisp-recordpage-field-value", children: [_jsx(RecordPageSelectEditor, { col: col, value: value, isPending: isPending, onCommit: (v) => commit(record.id, col.key, v), onCancel: closeEditing }), fieldError && (_jsx("span", { className: "crisp-recordpage-edit-error", children: fieldError }))] })] }, col.key));
|
|
429
508
|
}
|
|
430
509
|
if (canEdit && editingKey === col.key) {
|
|
431
510
|
const value = record[col.key];
|
|
@@ -105,6 +105,13 @@ const config = defineRecipe({
|
|
|
105
105
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
106
106
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: ${c.fgMuted}; }
|
|
107
107
|
& .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: ${c.space["0.5"]}; font-size: ${c.text.sm}; color: ${c.bgDanger}; }
|
|
108
|
+
/* #457: an \`editor: "select"\` field's at-rest chip -- same shape as
|
|
109
|
+
RecordsTable's own \`.crisp-recordstable-status[-dot]\` (already
|
|
110
|
+
measured against Attio there), but its own classes: that pair is
|
|
111
|
+
scoped under \`.crisp-recordstable\`'s own recipe root, so reusing the
|
|
112
|
+
classnames verbatim here would resolve to nothing. */
|
|
113
|
+
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: ${c.space["1.5"]}; min-width: 0; }
|
|
114
|
+
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: ${c.radius.full}; }
|
|
108
115
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: ${c.space["1"]}; width: 100%; }
|
|
109
116
|
& .crisp-recordpage-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; }
|
|
110
117
|
& .crisp-recordpage-link { color: ${c.fgPrimary}; text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
package/dist/recordpage.css
CHANGED
|
@@ -83,23 +83,33 @@
|
|
|
83
83
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
84
84
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
85
85
|
& .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
|
|
86
|
+
/* #457: an `editor: "select"` field's at-rest chip -- same shape as
|
|
87
|
+
RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
|
|
88
|
+
classnames verbatim here would resolve to nothing. */
|
|
89
|
+
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
90
|
+
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
|
|
86
91
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
|
|
87
92
|
& .crisp-recordpage-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; }
|
|
88
93
|
& .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
89
94
|
& .crisp-recordpage-link:hover { text-decoration: underline; }
|
|
90
95
|
& .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
96
|
+
|
|
91
97
|
& .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
|
|
98
|
+
|
|
92
99
|
& .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
93
100
|
& .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
|
|
94
101
|
& .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
|
|
95
102
|
& .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
|
|
96
|
-
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
103
|
+
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
104
|
+
column count, so the grid stays responsive (auto-fit) without per-cell
|
|
105
|
+
nth-child border hacks that break when the column count changes. */
|
|
97
106
|
& .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
|
|
98
107
|
& .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
|
|
99
108
|
& .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
|
|
100
109
|
& .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
|
|
101
110
|
& .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
102
111
|
& .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
|
|
112
|
+
|
|
103
113
|
& .crisp-recordpage-feed { display: flex; flex-direction: column; }
|
|
104
114
|
& .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
|
|
105
115
|
& .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
|
|
@@ -108,6 +118,7 @@
|
|
|
108
118
|
& .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
|
|
109
119
|
& .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
110
120
|
& .crisp-recordpage-feed-more:hover { text-decoration: underline; }
|
|
121
|
+
|
|
111
122
|
& .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
|
|
112
123
|
& .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
|
|
113
124
|
& .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
@@ -115,6 +126,7 @@
|
|
|
115
126
|
& .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
116
127
|
& .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
|
|
117
128
|
& .crisp-recordpage-addbtn svg { flex-shrink: 0; }
|
|
129
|
+
|
|
118
130
|
& .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
|
|
119
131
|
& .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
|
|
120
132
|
& .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
|
|
@@ -124,18 +136,23 @@
|
|
|
124
136
|
& .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
|
|
125
137
|
& .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
|
|
126
138
|
& .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
139
|
+
|
|
127
140
|
& .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
128
141
|
& .crisp-recordpage-note-body { flex: 1; min-width: 0; }
|
|
129
142
|
& .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
|
|
130
143
|
& .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
131
144
|
& .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
132
145
|
& .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
|
|
146
|
+
|
|
133
147
|
& .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
134
148
|
& .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
|
|
135
149
|
& .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
|
|
150
|
+
|
|
136
151
|
& .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
|
|
137
152
|
& .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
|
|
153
|
+
|
|
138
154
|
& .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
|
|
155
|
+
|
|
139
156
|
& .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
140
157
|
& .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
|
|
141
158
|
& .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
|
|
@@ -84,23 +84,33 @@
|
|
|
84
84
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
85
85
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
86
86
|
& .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
|
|
87
|
+
/* #457: an `editor: "select"` field's at-rest chip -- same shape as
|
|
88
|
+
RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
|
|
89
|
+
classnames verbatim here would resolve to nothing. */
|
|
90
|
+
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
91
|
+
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
|
|
87
92
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
|
|
88
93
|
& .crisp-recordpage-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; }
|
|
89
94
|
& .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
90
95
|
& .crisp-recordpage-link:hover { text-decoration: underline; }
|
|
91
96
|
& .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
97
|
+
|
|
92
98
|
& .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
|
|
99
|
+
|
|
93
100
|
& .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
94
101
|
& .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
|
|
95
102
|
& .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
|
|
96
103
|
& .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
|
|
97
|
-
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
104
|
+
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
105
|
+
column count, so the grid stays responsive (auto-fit) without per-cell
|
|
106
|
+
nth-child border hacks that break when the column count changes. */
|
|
98
107
|
& .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
|
|
99
108
|
& .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
|
|
100
109
|
& .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
|
|
101
110
|
& .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
|
|
102
111
|
& .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
103
112
|
& .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
|
|
113
|
+
|
|
104
114
|
& .crisp-recordpage-feed { display: flex; flex-direction: column; }
|
|
105
115
|
& .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
|
|
106
116
|
& .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
|
|
@@ -109,6 +119,7 @@
|
|
|
109
119
|
& .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
|
|
110
120
|
& .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
111
121
|
& .crisp-recordpage-feed-more:hover { text-decoration: underline; }
|
|
122
|
+
|
|
112
123
|
& .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
|
|
113
124
|
& .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
|
|
114
125
|
& .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
@@ -116,6 +127,7 @@
|
|
|
116
127
|
& .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
117
128
|
& .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
|
|
118
129
|
& .crisp-recordpage-addbtn svg { flex-shrink: 0; }
|
|
130
|
+
|
|
119
131
|
& .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
|
|
120
132
|
& .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
|
|
121
133
|
& .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
|
|
@@ -125,18 +137,23 @@
|
|
|
125
137
|
& .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
|
|
126
138
|
& .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
|
|
127
139
|
& .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
140
|
+
|
|
128
141
|
& .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
129
142
|
& .crisp-recordpage-note-body { flex: 1; min-width: 0; }
|
|
130
143
|
& .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
|
|
131
144
|
& .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
132
145
|
& .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
133
146
|
& .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
|
|
147
|
+
|
|
134
148
|
& .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
135
149
|
& .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
|
|
136
150
|
& .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
|
|
151
|
+
|
|
137
152
|
& .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
|
|
138
153
|
& .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
|
|
154
|
+
|
|
139
155
|
& .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
|
|
156
|
+
|
|
140
157
|
& .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
141
158
|
& .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
|
|
142
159
|
& .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
|
package/dist/styles.css
CHANGED
|
@@ -2163,23 +2163,33 @@
|
|
|
2163
2163
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2164
2164
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
2165
2165
|
& .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
|
|
2166
|
+
/* #457: an `editor: "select"` field's at-rest chip -- same shape as
|
|
2167
|
+
RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
|
|
2168
|
+
classnames verbatim here would resolve to nothing. */
|
|
2169
|
+
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
2170
|
+
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
|
|
2166
2171
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
|
|
2167
2172
|
& .crisp-recordpage-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; }
|
|
2168
2173
|
& .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
2169
2174
|
& .crisp-recordpage-link:hover { text-decoration: underline; }
|
|
2170
2175
|
& .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
2176
|
+
|
|
2171
2177
|
& .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
|
|
2178
|
+
|
|
2172
2179
|
& .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
2173
2180
|
& .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
|
|
2174
2181
|
& .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
|
|
2175
2182
|
& .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
|
|
2176
|
-
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
2183
|
+
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
2184
|
+
column count, so the grid stays responsive (auto-fit) without per-cell
|
|
2185
|
+
nth-child border hacks that break when the column count changes. */
|
|
2177
2186
|
& .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
|
|
2178
2187
|
& .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
|
|
2179
2188
|
& .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
|
|
2180
2189
|
& .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
|
|
2181
2190
|
& .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
2182
2191
|
& .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
|
|
2192
|
+
|
|
2183
2193
|
& .crisp-recordpage-feed { display: flex; flex-direction: column; }
|
|
2184
2194
|
& .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
|
|
2185
2195
|
& .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
|
|
@@ -2188,6 +2198,7 @@
|
|
|
2188
2198
|
& .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
|
|
2189
2199
|
& .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
2190
2200
|
& .crisp-recordpage-feed-more:hover { text-decoration: underline; }
|
|
2201
|
+
|
|
2191
2202
|
& .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
|
|
2192
2203
|
& .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
|
|
2193
2204
|
& .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
@@ -2195,6 +2206,7 @@
|
|
|
2195
2206
|
& .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
2196
2207
|
& .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
|
|
2197
2208
|
& .crisp-recordpage-addbtn svg { flex-shrink: 0; }
|
|
2209
|
+
|
|
2198
2210
|
& .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
|
|
2199
2211
|
& .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
|
|
2200
2212
|
& .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
|
|
@@ -2204,18 +2216,23 @@
|
|
|
2204
2216
|
& .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
|
|
2205
2217
|
& .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
|
|
2206
2218
|
& .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2219
|
+
|
|
2207
2220
|
& .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
2208
2221
|
& .crisp-recordpage-note-body { flex: 1; min-width: 0; }
|
|
2209
2222
|
& .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
|
|
2210
2223
|
& .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
2211
2224
|
& .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
2212
2225
|
& .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
|
|
2226
|
+
|
|
2213
2227
|
& .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
2214
2228
|
& .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
|
|
2215
2229
|
& .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
|
|
2230
|
+
|
|
2216
2231
|
& .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
|
|
2217
2232
|
& .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
|
|
2233
|
+
|
|
2218
2234
|
& .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
|
|
2235
|
+
|
|
2219
2236
|
& .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
2220
2237
|
& .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
|
|
2221
2238
|
& .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
|
package/dist/styles.layered.css
CHANGED
|
@@ -2164,23 +2164,33 @@
|
|
|
2164
2164
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2165
2165
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
2166
2166
|
& .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
|
|
2167
|
+
/* #457: an `editor: "select"` field's at-rest chip -- same shape as
|
|
2168
|
+
RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
|
|
2169
|
+
classnames verbatim here would resolve to nothing. */
|
|
2170
|
+
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
2171
|
+
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
|
|
2167
2172
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
|
|
2168
2173
|
& .crisp-recordpage-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; }
|
|
2169
2174
|
& .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
2170
2175
|
& .crisp-recordpage-link:hover { text-decoration: underline; }
|
|
2171
2176
|
& .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
2177
|
+
|
|
2172
2178
|
& .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
|
|
2179
|
+
|
|
2173
2180
|
& .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
2174
2181
|
& .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
|
|
2175
2182
|
& .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
|
|
2176
2183
|
& .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
|
|
2177
|
-
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
2184
|
+
/* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
|
|
2185
|
+
column count, so the grid stays responsive (auto-fit) without per-cell
|
|
2186
|
+
nth-child border hacks that break when the column count changes. */
|
|
2178
2187
|
& .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
|
|
2179
2188
|
& .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
|
|
2180
2189
|
& .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
|
|
2181
2190
|
& .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
|
|
2182
2191
|
& .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
2183
2192
|
& .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
|
|
2193
|
+
|
|
2184
2194
|
& .crisp-recordpage-feed { display: flex; flex-direction: column; }
|
|
2185
2195
|
& .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
|
|
2186
2196
|
& .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
|
|
@@ -2189,6 +2199,7 @@
|
|
|
2189
2199
|
& .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
|
|
2190
2200
|
& .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
2191
2201
|
& .crisp-recordpage-feed-more:hover { text-decoration: underline; }
|
|
2202
|
+
|
|
2192
2203
|
& .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
|
|
2193
2204
|
& .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
|
|
2194
2205
|
& .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
@@ -2196,6 +2207,7 @@
|
|
|
2196
2207
|
& .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
2197
2208
|
& .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
|
|
2198
2209
|
& .crisp-recordpage-addbtn svg { flex-shrink: 0; }
|
|
2210
|
+
|
|
2199
2211
|
& .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
|
|
2200
2212
|
& .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
|
|
2201
2213
|
& .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
|
|
@@ -2205,18 +2217,23 @@
|
|
|
2205
2217
|
& .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
|
|
2206
2218
|
& .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
|
|
2207
2219
|
& .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2220
|
+
|
|
2208
2221
|
& .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
2209
2222
|
& .crisp-recordpage-note-body { flex: 1; min-width: 0; }
|
|
2210
2223
|
& .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
|
|
2211
2224
|
& .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
2212
2225
|
& .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
2213
2226
|
& .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
|
|
2227
|
+
|
|
2214
2228
|
& .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
|
|
2215
2229
|
& .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
|
|
2216
2230
|
& .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
|
|
2231
|
+
|
|
2217
2232
|
& .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
|
|
2218
2233
|
& .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
|
|
2234
|
+
|
|
2219
2235
|
& .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
|
|
2236
|
+
|
|
2220
2237
|
& .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
2221
2238
|
& .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
|
|
2222
2239
|
& .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
|