@crisp-ui-kit/crisp 0.57.1 → 0.57.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authshell.css +9 -4
- package/dist/authshell.layered.css +9 -4
- package/dist/badge.css +3 -3
- package/dist/badge.layered.css +3 -3
- package/dist/board.css +28 -8
- package/dist/board.layered.css +28 -8
- package/dist/bottomsheet.css +26 -0
- package/dist/bottomsheet.d.ts +7 -0
- package/dist/bottomsheet.layered.css +28 -0
- package/dist/button.css +10 -6
- package/dist/button.d.ts +2 -2
- package/dist/button.layered.css +10 -6
- package/dist/checkbox.css +7 -3
- package/dist/checkbox.layered.css +7 -3
- package/dist/chip.css +16 -1
- package/dist/chip.d.ts +3 -1
- package/dist/chip.layered.css +16 -1
- package/dist/chipgroup.css +5 -0
- package/dist/chipgroup.d.ts +7 -0
- package/dist/chipgroup.layered.css +7 -0
- package/dist/cjs/components/badge/badge.recipe.js +22 -8
- package/dist/cjs/components/bottomsheet/bottomsheet.js +90 -0
- package/dist/cjs/components/bottomsheet/bottomsheet.recipe.js +77 -0
- package/dist/cjs/components/bottomsheet/index.js +9 -0
- package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
- package/dist/cjs/components/button/button.recipe.js +67 -15
- package/dist/cjs/components/checkbox/checkbox.recipe.js +61 -9
- package/dist/cjs/components/chip/chip.js +14 -2
- package/dist/cjs/components/chip/chip.recipe.js +72 -2
- package/dist/cjs/components/chipgroup/chipgroup.js +51 -0
- package/dist/cjs/components/chipgroup/chipgroup.recipe.js +36 -0
- package/dist/cjs/components/chipgroup/index.js +7 -0
- package/dist/cjs/components/datatable/datatable.js +5 -1
- package/dist/cjs/components/datatable/datatable.recipe.js +21 -6
- package/dist/cjs/components/datepickerfield/datepickerfield.js +2 -2
- package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +16 -3
- package/dist/cjs/components/dialog/dialog.recipe.js +21 -10
- package/dist/cjs/components/emptystate/emptystate.recipe.js +7 -2
- package/dist/cjs/components/fileupload/fileupload.js +21 -4
- package/dist/cjs/components/input/index.js +2 -1
- package/dist/cjs/components/input/input.js +31 -1
- package/dist/cjs/components/input/input.recipe.js +16 -9
- package/dist/cjs/components/menu/menu.js +18 -2
- package/dist/cjs/components/menu/menu.recipe.js +21 -7
- package/dist/cjs/components/menusheet/index.js +9 -0
- package/dist/cjs/components/menusheet/menusheet.js +133 -0
- package/dist/cjs/components/menusheet/menusheet.recipe.js +103 -0
- package/dist/cjs/components/multiselect/multiselect.js +1 -1
- package/dist/cjs/components/multiselect/multiselect.recipe.js +33 -9
- package/dist/cjs/components/select/select.js +1 -1
- package/dist/cjs/components/select/select.recipe.js +38 -12
- package/dist/cjs/components/snackbar/index.js +8 -0
- package/dist/cjs/components/snackbar/snackbar.js +121 -0
- package/dist/cjs/components/snackbar/snackbar.recipe.js +71 -0
- package/dist/cjs/components/table/table.recipe.js +7 -1
- package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +37 -12
- package/dist/cjs/components/tabs/tabs.js +10 -4
- package/dist/cjs/components/tabs/tabs.recipe.js +23 -6
- package/dist/cjs/components/textarea/textarea.recipe.js +11 -8
- package/dist/cjs/core/floating-portal.js +7 -4
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/product/authshell/authshell.recipe.js +5 -1
- package/dist/cjs/product/command/command.recipe.js +4 -1
- package/dist/cjs/product/comments/comments.js +7 -2
- package/dist/cjs/product/comments/comments.recipe.js +25 -7
- package/dist/cjs/product/inbox/inbox.js +11 -3
- package/dist/cjs/product/memberssettings/index.js +6 -0
- package/dist/cjs/product/memberssettings/memberssettings.js +99 -0
- package/dist/cjs/product/memberssettings/memberssettings.recipe.js +83 -0
- package/dist/cjs/product/notificationssettings/index.js +5 -0
- package/dist/cjs/product/notificationssettings/notificationssettings.js +19 -0
- package/dist/cjs/product/notificationssettings/notificationssettings.recipe.js +44 -0
- package/dist/cjs/product/recordpage/index.js +2 -1
- package/dist/cjs/product/recordpage/recordpage.js +106 -9
- package/dist/cjs/product/recordpage/recordpage.recipe.js +68 -6
- package/dist/cjs/product/workspacegeneralsettings/index.js +5 -0
- package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.js +21 -0
- package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +51 -0
- package/dist/cjs/tokens/contract.js +1 -0
- package/dist/cjs/tokens/elevation.js +8 -5
- package/dist/cjs/tokens/palette.js +28 -8
- package/dist/cjs/tokens/scale.js +44 -2
- package/dist/cjs/tokens/semantic.js +2 -0
- package/dist/columncalc.css +15 -7
- package/dist/columncalc.layered.css +15 -7
- package/dist/command.css +23 -19
- package/dist/command.layered.css +23 -19
- package/dist/comments.css +28 -19
- package/dist/comments.d.ts +2 -2
- package/dist/comments.layered.css +28 -19
- package/dist/datatable.css +171 -71
- package/dist/datatable.layered.css +171 -71
- package/dist/datepicker.css +13 -41
- package/dist/datepicker.layered.css +13 -41
- package/dist/datepickerfield.css +12 -3
- package/dist/datepickerfield.d.ts +2 -2
- package/dist/datepickerfield.layered.css +12 -3
- package/dist/dialog.css +12 -7
- package/dist/dialog.layered.css +12 -7
- package/dist/emptystate.css +5 -3
- package/dist/emptystate.layered.css +5 -3
- package/dist/esm/components/badge/badge.recipe.js +22 -8
- package/dist/esm/components/bottomsheet/bottomsheet.js +52 -0
- package/dist/esm/components/bottomsheet/bottomsheet.recipe.js +74 -0
- package/dist/esm/components/bottomsheet/index.js +2 -0
- package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
- package/dist/esm/components/button/button.recipe.js +68 -16
- package/dist/esm/components/checkbox/checkbox.recipe.js +61 -9
- package/dist/esm/components/chip/chip.js +14 -2
- package/dist/esm/components/chip/chip.recipe.js +72 -2
- package/dist/esm/components/chipgroup/chipgroup.js +15 -0
- package/dist/esm/components/chipgroup/chipgroup.recipe.js +33 -0
- package/dist/esm/components/chipgroup/index.js +2 -0
- package/dist/esm/components/datatable/datatable.js +5 -1
- package/dist/esm/components/datatable/datatable.recipe.js +21 -6
- package/dist/esm/components/datepickerfield/datepickerfield.js +2 -2
- package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +16 -3
- package/dist/esm/components/dialog/dialog.recipe.js +22 -11
- package/dist/esm/components/emptystate/emptystate.recipe.js +7 -2
- package/dist/esm/components/fileupload/fileupload.js +20 -5
- package/dist/esm/components/input/index.js +1 -1
- package/dist/esm/components/input/input.js +30 -0
- package/dist/esm/components/input/input.recipe.js +17 -10
- package/dist/esm/components/menu/menu.js +18 -2
- package/dist/esm/components/menu/menu.recipe.js +21 -7
- package/dist/esm/components/menusheet/index.js +2 -0
- package/dist/esm/components/menusheet/menusheet.js +95 -0
- package/dist/esm/components/menusheet/menusheet.recipe.js +100 -0
- package/dist/esm/components/multiselect/multiselect.js +1 -1
- package/dist/esm/components/multiselect/multiselect.recipe.js +33 -9
- package/dist/esm/components/select/select.js +1 -1
- package/dist/esm/components/select/select.recipe.js +38 -12
- package/dist/esm/components/snackbar/index.js +2 -0
- package/dist/esm/components/snackbar/snackbar.js +84 -0
- package/dist/esm/components/snackbar/snackbar.recipe.js +68 -0
- package/dist/esm/components/table/table.recipe.js +7 -1
- package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +37 -12
- package/dist/esm/components/tabs/tabs.js +10 -4
- package/dist/esm/components/tabs/tabs.recipe.js +23 -6
- package/dist/esm/components/textarea/textarea.recipe.js +12 -9
- package/dist/esm/core/floating-portal.js +7 -4
- package/dist/esm/index.js +7 -0
- package/dist/esm/product/authshell/authshell.recipe.js +5 -1
- package/dist/esm/product/command/command.recipe.js +4 -1
- package/dist/esm/product/comments/comments.js +7 -2
- package/dist/esm/product/comments/comments.recipe.js +25 -7
- package/dist/esm/product/inbox/inbox.js +11 -3
- package/dist/esm/product/memberssettings/index.js +1 -0
- package/dist/esm/product/memberssettings/memberssettings.js +62 -0
- package/dist/esm/product/memberssettings/memberssettings.recipe.js +80 -0
- package/dist/esm/product/notificationssettings/index.js +1 -0
- package/dist/esm/product/notificationssettings/notificationssettings.js +16 -0
- package/dist/esm/product/notificationssettings/notificationssettings.recipe.js +41 -0
- package/dist/esm/product/recordpage/index.js +1 -1
- package/dist/esm/product/recordpage/recordpage.js +106 -10
- package/dist/esm/product/recordpage/recordpage.recipe.js +68 -6
- package/dist/esm/product/workspacegeneralsettings/index.js +1 -0
- package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.js +18 -0
- package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +48 -0
- package/dist/esm/tokens/contract.js +2 -1
- package/dist/esm/tokens/elevation.js +8 -5
- package/dist/esm/tokens/palette.js +28 -8
- package/dist/esm/tokens/scale.js +43 -1
- package/dist/esm/tokens/semantic.js +2 -0
- package/dist/fileupload.css +3 -1
- package/dist/fileupload.layered.css +3 -1
- package/dist/input.css +6 -4
- package/dist/input.layered.css +6 -4
- package/dist/listpage.css +3 -1
- package/dist/listpage.layered.css +3 -1
- package/dist/memberssettings.css +67 -0
- package/dist/memberssettings.d.ts +7 -0
- package/dist/memberssettings.layered.css +69 -0
- package/dist/menu.css +2 -2
- package/dist/menu.layered.css +2 -2
- package/dist/menusheet.css +36 -0
- package/dist/menusheet.d.ts +7 -0
- package/dist/menusheet.layered.css +38 -0
- package/dist/multiselect.css +13 -6
- package/dist/multiselect.layered.css +13 -6
- package/dist/native/tokens.d.ts +2 -1
- package/dist/native/tokens.js +20 -3
- package/dist/notificationssettings.css +22 -0
- package/dist/notificationssettings.d.ts +7 -0
- package/dist/notificationssettings.layered.css +24 -0
- package/dist/objectsettings.css +4 -4
- package/dist/objectsettings.layered.css +4 -4
- package/dist/recordpage.css +90 -23
- package/dist/recordpage.layered.css +90 -23
- package/dist/recordpanel.css +35 -16
- package/dist/recordpanel.layered.css +35 -16
- package/dist/resizablepanel.css +8 -5
- package/dist/resizablepanel.layered.css +8 -5
- package/dist/richtext.css +24 -8
- package/dist/richtext.layered.css +24 -8
- package/dist/savedviews.css +9 -2
- package/dist/savedviews.layered.css +9 -2
- package/dist/select.css +25 -5
- package/dist/select.layered.css +25 -5
- package/dist/settingsshell.css +2 -3
- package/dist/settingsshell.layered.css +2 -3
- package/dist/slider.css +6 -27
- package/dist/slider.layered.css +6 -27
- package/dist/snackbar.css +24 -0
- package/dist/snackbar.d.ts +7 -0
- package/dist/snackbar.layered.css +26 -0
- package/dist/statcard.css +3 -1
- package/dist/statcard.layered.css +3 -1
- package/dist/styles.css +911 -354
- package/dist/styles.layered.css +911 -354
- package/dist/table.css +35 -12
- package/dist/table.layered.css +35 -12
- package/dist/tabletoolbar.css +35 -24
- package/dist/tabletoolbar.layered.css +35 -24
- package/dist/tabs.css +18 -4
- package/dist/tabs.layered.css +18 -4
- package/dist/textarea.css +2 -6
- package/dist/textarea.layered.css +2 -6
- package/dist/themepicker.css +2 -1
- package/dist/themepicker.layered.css +2 -1
- package/dist/tokens.css +13 -2
- package/dist/tokens.json +20 -3
- package/dist/types/components/bottomsheet/bottomsheet.d.ts +35 -0
- package/dist/types/components/bottomsheet/bottomsheet.recipe.d.ts +3 -0
- package/dist/types/components/bottomsheet/index.d.ts +2 -0
- package/dist/types/components/breadcrumb/breadcrumb.d.ts +9 -1
- package/dist/types/components/button/button.d.ts +2 -0
- package/dist/types/components/button/button.recipe.d.ts +24 -6
- package/dist/types/components/checkbox/checkbox.recipe.d.ts +28 -5
- package/dist/types/components/chip/chip.d.ts +22 -0
- package/dist/types/components/chip/chip.recipe.d.ts +49 -1
- package/dist/types/components/chipgroup/chipgroup.d.ts +14 -0
- package/dist/types/components/chipgroup/chipgroup.recipe.d.ts +5 -0
- package/dist/types/components/chipgroup/index.d.ts +2 -0
- package/dist/types/components/datatable/datatable.d.ts +19 -0
- package/dist/types/components/datepickerfield/datepickerfield.d.ts +4 -1
- package/dist/types/components/datepickerfield/datepickerfield.recipe.d.ts +18 -3
- package/dist/types/components/fileupload/fileupload.d.ts +26 -0
- package/dist/types/components/input/index.d.ts +1 -1
- package/dist/types/components/input/input.d.ts +72 -0
- package/dist/types/components/menusheet/index.d.ts +2 -0
- package/dist/types/components/menusheet/menusheet.d.ts +42 -0
- package/dist/types/components/menusheet/menusheet.recipe.d.ts +3 -0
- package/dist/types/components/snackbar/index.d.ts +2 -0
- package/dist/types/components/snackbar/snackbar.d.ts +36 -0
- package/dist/types/components/snackbar/snackbar.recipe.d.ts +5 -0
- package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +28 -1
- package/dist/types/components/tabs/tabs.d.ts +11 -1
- package/dist/types/core/floating-portal.d.ts +6 -5
- package/dist/types/index.d.ts +7 -0
- package/dist/types/product/comments/comments.d.ts +9 -3
- package/dist/types/product/comments/comments.recipe.d.ts +12 -2
- package/dist/types/product/inbox/inbox.d.ts +13 -1
- package/dist/types/product/memberssettings/index.d.ts +1 -0
- package/dist/types/product/memberssettings/memberssettings.d.ts +85 -0
- package/dist/types/product/memberssettings/memberssettings.recipe.d.ts +3 -0
- package/dist/types/product/notificationssettings/index.d.ts +1 -0
- package/dist/types/product/notificationssettings/notificationssettings.d.ts +37 -0
- package/dist/types/product/notificationssettings/notificationssettings.recipe.d.ts +3 -0
- package/dist/types/product/recordpage/index.d.ts +1 -1
- package/dist/types/product/recordpage/recordpage.d.ts +99 -2
- package/dist/types/product/workspacegeneralsettings/index.d.ts +1 -0
- package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.d.ts +48 -0
- package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.recipe.d.ts +3 -0
- package/dist/types/tokens/contract.d.ts +4 -1
- package/dist/types/tokens/elevation.d.ts +8 -5
- package/dist/types/tokens/palette.d.ts +9 -1
- package/dist/types/tokens/scale.d.ts +11 -1
- package/dist/types/tokens/semantic.d.ts +2 -0
- package/dist/wheelpicker.css +4 -2
- package/dist/wheelpicker.layered.css +4 -2
- package/dist/workspacegeneralsettings.css +30 -0
- package/dist/workspacegeneralsettings.d.ts +7 -0
- package/dist/workspacegeneralsettings.layered.css +32 -0
- package/package.json +36 -1
package/dist/styles.layered.css
CHANGED
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
--crisp-ring-switch: #d9dade;
|
|
46
46
|
--crisp-bg-tile-active: #ffffff;
|
|
47
47
|
--crisp-shadow-tile-active: rgba(0,0,0,0.04);
|
|
48
|
-
--crisp-bg-scrim: rgba(0,0,0,0.
|
|
48
|
+
--crisp-bg-scrim: rgba(0,0,0,0.45);
|
|
49
|
+
--crisp-bg-overlay-strong: #00000074;
|
|
50
|
+
--crisp-stroke-group-divider: #00000010;
|
|
49
51
|
--crisp-fg-alert-description: rgba(0,0,0,0.63);
|
|
50
52
|
--crisp-bg-overlay-frost: #ffffff;
|
|
51
53
|
--crisp-shadow-overlay1: rgba(28,40,64,0.12);
|
|
@@ -117,6 +119,8 @@
|
|
|
117
119
|
--crisp-bg-tile-active: #101112;
|
|
118
120
|
--crisp-shadow-tile-active: rgba(0,0,0,0);
|
|
119
121
|
--crisp-bg-scrim: rgba(0,0,0,0.55);
|
|
122
|
+
--crisp-bg-overlay-strong: #00000074;
|
|
123
|
+
--crisp-stroke-group-divider: #ffffff17;
|
|
120
124
|
--crisp-fg-alert-description: rgba(255,255,255,0.6);
|
|
121
125
|
--crisp-bg-overlay-frost: #1c1d1f;
|
|
122
126
|
--crisp-shadow-overlay1: rgba(0,0,0,0.48);
|
|
@@ -182,13 +186,14 @@
|
|
|
182
186
|
--crisp-space-2-5: 10px;
|
|
183
187
|
--crisp-space-3-5: 14px;
|
|
184
188
|
--crisp-radius-xs: 4px;
|
|
185
|
-
--crisp-radius-chip:
|
|
189
|
+
--crisp-radius-chip: 999px;
|
|
186
190
|
--crisp-radius-sm: 6px;
|
|
187
191
|
--crisp-radius-md: 8px;
|
|
188
192
|
--crisp-radius-lg: 9px;
|
|
189
193
|
--crisp-radius-xl: 12px;
|
|
190
194
|
--crisp-radius-2xl: 16px;
|
|
191
195
|
--crisp-radius-3xl: 20px;
|
|
196
|
+
--crisp-radius-4xl: 24px;
|
|
192
197
|
--crisp-radius-full: 999px;
|
|
193
198
|
--crisp-size-icon: 16px;
|
|
194
199
|
--crisp-size-chip: 22px;
|
|
@@ -212,6 +217,12 @@
|
|
|
212
217
|
--crisp-weight-semibold: 600;
|
|
213
218
|
--crisp-weight-bold: 700;
|
|
214
219
|
--crisp-font-sans: "VK Sans Display", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
220
|
+
--crisp-tracking-18: -0.36px;
|
|
221
|
+
--crisp-tracking-20: -0.4px;
|
|
222
|
+
--crisp-tracking-24: -0.48px;
|
|
223
|
+
--crisp-tracking-26: -0.52px;
|
|
224
|
+
--crisp-tracking-28: -0.56px;
|
|
225
|
+
--crisp-tracking-32: -0.64px;
|
|
215
226
|
}
|
|
216
227
|
|
|
217
228
|
@layer crisp-components {
|
|
@@ -313,13 +324,13 @@
|
|
|
313
324
|
background: var(--crisp-bg-purple-soft); color: var(--crisp-fg-purple-soft); box-shadow: inset 0 0 0 1px var(--crisp-ring-purple-soft);
|
|
314
325
|
}
|
|
315
326
|
.crisp-badge--size_small {
|
|
316
|
-
height: 16px; padding-inline: var(--crisp-space-1); font-size: var(--crisp-text-sm); line-height: 16px; border-radius: var(--crisp-radius-
|
|
327
|
+
height: 16px; padding-inline: var(--crisp-space-1); font-size: var(--crisp-text-sm); line-height: 16px; border-radius: var(--crisp-radius-xs);
|
|
317
328
|
}
|
|
318
329
|
.crisp-badge--size_medium {
|
|
319
|
-
height: 20px; padding-inline: var(--crisp-space-1); font-size: var(--crisp-text-sm); line-height: 16px; gap: 3px; border-radius: var(--crisp-radius-
|
|
330
|
+
height: 20px; padding-inline: var(--crisp-space-1); font-size: var(--crisp-text-sm); line-height: 16px; gap: 3px; border-radius: var(--crisp-radius-xs);
|
|
320
331
|
}
|
|
321
332
|
.crisp-badge--size_large {
|
|
322
|
-
height: var(--crisp-size-chip); padding-block: var(--crisp-space-px); padding-inline-start: var(--crisp-space-1); padding-inline-end: var(--crisp-space-1-5); font-size: var(--crisp-text-lg); letter-spacing: -0.1px; border-radius: var(--crisp-radius-
|
|
333
|
+
height: var(--crisp-size-chip); padding-block: var(--crisp-space-px); padding-inline-start: var(--crisp-space-1); padding-inline-end: var(--crisp-space-1-5); font-size: var(--crisp-text-lg); letter-spacing: -0.1px; border-radius: var(--crisp-radius-sm);
|
|
323
334
|
}
|
|
324
335
|
.crisp-badge--variant_soft {
|
|
325
336
|
|
|
@@ -367,6 +378,33 @@
|
|
|
367
378
|
}
|
|
368
379
|
}
|
|
369
380
|
|
|
381
|
+
.crisp-bottomsheet {
|
|
382
|
+
display: contents; font-family: var(--crisp-font-sans);
|
|
383
|
+
& .crisp-bottomsheet-backdrop { position: fixed; inset: 0; z-index: 60; background: var(--crisp-bg-overlay-strong); /* bottom-sheet.yaml:99 backdrop.color = $color.bg.overlay -- a different, darker, theme-constant scrim than the Dialog bgScrim token, see its own comment */ opacity: 1; transition: opacity 300ms cubic-bezier(0,0,.15,1); /* bottom-sheet.yaml:100-102 enterDuration/enterTimingFunction */ @starting-style { opacity: 0; } }
|
|
384
|
+
& .crisp-bottomsheet-positioner { position: fixed; inset: 0; z-index: 61; display: flex; align-items: flex-end; justify-content: center; }
|
|
385
|
+
& .crisp-bottomsheet-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; box-sizing: border-box; display: flex; flex-direction: column; overflow: hidden; width: 100%; max-width: 480px; /* bottom-sheet.yaml:110 content.maxWidth */ max-height: 85vh; background: var(--crisp-bg-surface); /* bottom-sheet.yaml:109 content.color = $color.bg.layer-floating */ border-radius: var(--crisp-radius-4xl) var(--crisp-radius-4xl) 0 0; /* bottom-sheet.yaml:111 content.topCornerRadius = $radius.r6 (24px), bottom flush with the viewport */ transform: translateY(0); transition: transform 300ms cubic-bezier(.03,.4,.1,1); /* bottom-sheet.yaml:112-113 content.enterDuration/enterTimingFunction (enter-expressive) */ @starting-style { transform: translateY(100%); } }
|
|
386
|
+
& .crisp-bottomsheet-header { position: relative; display: flex; flex-direction: column; gap: var(--crisp-space-2); /* bottom-sheet.yaml:120 header.gap = $dimension.x2 (8px) */ padding-top: var(--crisp-space-6); padding-bottom: var(--crisp-space-4); /* bottom-sheet.yaml:121-122 header.paddingTop/paddingBottom = $dimension.x6/x4 (24px/16px) */ flex-shrink: 0; }
|
|
387
|
+
& .crisp-bottomsheet-title { color: var(--crisp-fg-primary); /* bottom-sheet.yaml:130 title.color = $color.fg.neutral */ font-size: 22px; line-height: 30px; font-weight: var(--crisp-weight-bold); /* bottom-sheet.yaml:131-133 title.fontSize/lineHeight/fontWeight = $font-size.t8/$line-height.t8/bold */ padding-inline: var(--crisp-space-4); /* default (headerAlignment=left, no close button): bottom-sheet.yaml:150-152 */ }
|
|
388
|
+
&[data-header-align="left"][data-has-close] .crisp-bottomsheet-title { padding-inline-start: var(--crisp-space-4); padding-inline-end: 56px; }
|
|
389
|
+
/* bottom-sheet.yaml:141-144 */
|
|
390
|
+
&[data-header-align="center"] .crisp-bottomsheet-title { text-align: center; }
|
|
391
|
+
&[data-header-align="center"][data-has-close] .crisp-bottomsheet-title { padding-inline: 56px; }
|
|
392
|
+
/* bottom-sheet.yaml:154-157 */
|
|
393
|
+
& .crisp-bottomsheet-description { color: var(--crisp-fg-muted); /* bottom-sheet.yaml:138 description.color = $color.fg.neutral-muted */ font-size: var(--crisp-text-xl); line-height: 22px; font-weight: var(--crisp-weight-regular); /* bottom-sheet.yaml:139-141 description.fontSize/lineHeight/fontWeight = $font-size.t5/$line-height.t5/regular */ padding-inline: var(--crisp-space-4); /* bottom-sheet.yaml:142 description.paddingX = global-gutter (16px) */ }
|
|
394
|
+
& .crisp-bottomsheet-close { position: absolute; top: var(--crisp-space-6); inset-inline-end: var(--crisp-space-4); /* bottom-sheet.yaml:145-146 closeButton.fromTop/fromRight = $dimension.x6/x4 (24px/16px) */ display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; }
|
|
395
|
+
& .crisp-bottomsheet-close:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
|
|
396
|
+
& .crisp-bottomsheet-body { flex: 1; min-height: 0; overflow-y: auto; padding-inline: var(--crisp-space-4); /* bottom-sheet.yaml:126 body.paddingX = global-gutter (16px) -- no vertical padding in the spec */ }
|
|
397
|
+
& .crisp-bottomsheet-footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--crisp-space-3); flex-shrink: 0; padding-inline: var(--crisp-space-4); padding-top: var(--crisp-space-3); padding-bottom: var(--crisp-space-4); /* bottom-sheet.yaml:127-129 footer.paddingX/paddingTop/paddingBottom = global-gutter/x3/x4 (16px/12px/16px) */ }
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
@media (prefers-reduced-motion: reduce) {
|
|
401
|
+
.crisp-bottomsheet, .crisp-bottomsheet * {
|
|
402
|
+
animation-duration: 0.01ms !important;
|
|
403
|
+
animation-iteration-count: 1 !important;
|
|
404
|
+
transition-duration: 0.01ms !important;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
370
408
|
.crisp-breadcrumb {
|
|
371
409
|
display: flex; align-items: center; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg);
|
|
372
410
|
& .crisp-breadcrumb-item { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); box-sizing: border-box; height: 24px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-md); color: var(--crisp-fg-muted); text-decoration: none; white-space: nowrap; }
|
|
@@ -407,35 +445,39 @@
|
|
|
407
445
|
.crisp-button {
|
|
408
446
|
display: inline-flex; align-items: center; justify-content: center; gap: var(--crisp-space-1-5); font-family: var(--crisp-font-sans); font-weight: var(--crisp-weight-medium); letter-spacing: -0.07px; line-height: 20px; white-space: nowrap; border: none; cursor: pointer; transition: background-color .2s, box-shadow .2s, color .2s;
|
|
409
447
|
&:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
448
|
+
&:active { transform: scale(0.98); }
|
|
410
449
|
}
|
|
411
450
|
.crisp-button--intent_primary {
|
|
412
|
-
background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow:
|
|
451
|
+
background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: none;
|
|
413
452
|
&:hover { filter: brightness(0.96); }
|
|
414
453
|
&:active { filter: brightness(0.92); }
|
|
415
454
|
}
|
|
416
455
|
.crisp-button--intent_neutral {
|
|
417
|
-
background: var(--crisp-bg-
|
|
418
|
-
&:hover { background: var(--crisp-
|
|
456
|
+
background: var(--crisp-bg-neutral-weak); color: var(--crisp-fg-primary); box-shadow: none;
|
|
457
|
+
&:hover { background: var(--crisp-border-subtle); }
|
|
419
458
|
}
|
|
420
459
|
.crisp-button--intent_danger {
|
|
421
|
-
background: var(--crisp-bg-danger-solid); color: var(--crisp-fg-on-brand); box-shadow:
|
|
460
|
+
background: var(--crisp-bg-danger-solid); color: var(--crisp-fg-on-brand); box-shadow: none;
|
|
422
461
|
&:hover { filter: brightness(0.96); }
|
|
423
462
|
&:active { filter: brightness(0.92); }
|
|
424
463
|
}
|
|
425
464
|
.crisp-button--intent_ghost {
|
|
426
|
-
background: transparent; color: var(--crisp-fg-
|
|
465
|
+
background: transparent; color: var(--crisp-fg-primary); box-shadow: none;
|
|
427
466
|
&:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
428
467
|
}
|
|
429
468
|
.crisp-button--size_sm {
|
|
430
469
|
height: 24px; padding-inline: var(--crisp-space-1-5); font-size: var(--crisp-text-md); border-radius: var(--crisp-radius-md);
|
|
431
470
|
}
|
|
471
|
+
.crisp-button--size_xs {
|
|
472
|
+
height: 20px; padding-inline: var(--crisp-space-1-5); font-size: 10px; font-weight: var(--crisp-weight-regular); line-height: 15px; letter-spacing: normal; border-radius: var(--crisp-radius-sm); gap: var(--crisp-space-1);
|
|
473
|
+
}
|
|
432
474
|
.crisp-button--size_md {
|
|
433
475
|
height: 28px; padding-inline: var(--crisp-space-2); font-size: var(--crisp-text-lg); border-radius: var(--crisp-radius-md);
|
|
434
476
|
&[data-icon-start] { padding-inline-start: var(--crisp-space-1-5); }
|
|
435
477
|
&[data-icon-end] { padding-inline-end: var(--crisp-space-1-5); }
|
|
436
478
|
}
|
|
437
479
|
.crisp-button--size_lg {
|
|
438
|
-
height: 40px; padding-inline: 14px; font-size: var(--crisp-text-lg); border-radius:
|
|
480
|
+
height: 40px; padding-inline: 14px; font-size: var(--crisp-text-lg); border-radius: var(--crisp-radius-xl);
|
|
439
481
|
}
|
|
440
482
|
.crisp-button--shape_text {
|
|
441
483
|
|
|
@@ -513,12 +555,16 @@
|
|
|
513
555
|
}
|
|
514
556
|
|
|
515
557
|
.crisp-checkbox {
|
|
516
|
-
appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border:
|
|
517
|
-
&:hover {
|
|
518
|
-
&:checked, &:indeterminate { background: var(--crisp-bg-brand-solid) center / 10px no-repeat;
|
|
558
|
+
appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xs); background: var(--crisp-bg-surface); cursor: pointer; transition: background-color .12s, border-color .12s;
|
|
559
|
+
&:hover { border-color: color-mix(in srgb, var(--crisp-fg-primary) 30%, transparent); }
|
|
560
|
+
&:checked, &:indeterminate { background: var(--crisp-bg-brand-solid) center / 10px no-repeat; border-color: transparent; }
|
|
519
561
|
&:checked { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
|
|
520
562
|
&:indeterminate { background-image: linear-gradient(var(--crisp-fg-on-brand), var(--crisp-fg-on-brand)); background-size: 8px 2px; }
|
|
521
563
|
&:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
|
|
564
|
+
&:disabled { background: var(--crisp-bg-neutral-weak); border-color: var(--crisp-border-subtle); cursor: not-allowed; }
|
|
565
|
+
&:checked:disabled, &:indeterminate:disabled { background: var(--crisp-bg-neutral-weak) center / 10px no-repeat; border-color: var(--crisp-border-subtle); }
|
|
566
|
+
&:checked:disabled { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
|
|
567
|
+
&:indeterminate:disabled { background-image: linear-gradient(var(--crisp-fg-on-brand), var(--crisp-fg-on-brand)); background-size: 8px 2px; }
|
|
522
568
|
}
|
|
523
569
|
|
|
524
570
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -533,7 +579,7 @@
|
|
|
533
579
|
display: inline-flex; align-items: center; gap: 3px; height: var(--crisp-size-chip); min-width: 0; max-width: 100%; padding-inline: 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;
|
|
534
580
|
}
|
|
535
581
|
.crisp-chip--truncate_true {
|
|
536
|
-
& .crisp-chip-label { min-width: 0; overflow:
|
|
582
|
+
& .crisp-chip-label { min-width: 0; overflow: clip; text-overflow: ellipsis; white-space: nowrap; display: block; }
|
|
537
583
|
}
|
|
538
584
|
.crisp-chip--truncate_false {
|
|
539
585
|
|
|
@@ -562,34 +608,63 @@
|
|
|
562
608
|
.crisp-chip--tone_orange {
|
|
563
609
|
background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent);
|
|
564
610
|
}
|
|
611
|
+
.crisp-chip--appearance_filled {
|
|
612
|
+
|
|
613
|
+
}
|
|
614
|
+
.crisp-chip--appearance_outline {
|
|
615
|
+
background: transparent;
|
|
616
|
+
}
|
|
617
|
+
.crisp-chip--selected_true {
|
|
618
|
+
background: var(--crisp-bg-neutral-inverted); color: var(--crisp-fg-on-neutral-inverted); box-shadow: none;
|
|
619
|
+
}
|
|
620
|
+
.crisp-chip--selected_false {
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
.crisp-chip--compound_0 {
|
|
624
|
+
box-shadow: inset 0 0 0 1px var(--crisp-border-default);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.crisp-chipgroup {
|
|
628
|
+
display: flex; flex-wrap: nowrap; align-items: center; gap: var(--crisp-space-1-5); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; -ms-overflow-style: none;
|
|
629
|
+
&::-webkit-scrollbar { display: none; }
|
|
630
|
+
& > * { flex-shrink: 0; scroll-snap-align: start; }
|
|
631
|
+
}
|
|
565
632
|
|
|
566
633
|
.crisp-columncalc {
|
|
567
|
-
display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would
|
|
634
|
+
display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would
|
|
635
|
+
shrink the button back to its text. Make the wrapper fill too, so the
|
|
636
|
+
whole cell stays clickable. */
|
|
568
637
|
& .crisp-menu { width: 100%; height: 100%; }
|
|
569
|
-
/* No radius: the trigger fills the cell, so rounding its own corners
|
|
638
|
+
/* No radius: the trigger fills the cell, so rounding its own corners
|
|
639
|
+
leaves the cell's background showing through at the four corners as
|
|
570
640
|
soon as the hover tint paints. Everything else that fills a grid cell
|
|
571
641
|
agrees -- recordstable-sum-btn, the same summary trigger, declares no
|
|
572
642
|
radius, and datatable-grip and the embedded pickers zero theirs. An 8px
|
|
573
643
|
radius survived the chip-to-full-cell conversion and shipped rounded
|
|
574
|
-
until #282, so the spec check now guards it. */
|
|
575
|
-
/* The hit target is the WHOLE summary cell -- measured 246x36 with
|
|
644
|
+
until #282, so the spec check now guards it. */ /* The hit target is the WHOLE summary cell -- measured 246x36 with
|
|
576
645
|
padding 0 12px, not a content-sized chip. Clicking anywhere in the cell
|
|
577
646
|
opens the aggregation menu.
|
|
578
647
|
No `min-height` (crisp#834, found reproducing the footer-row-38px-
|
|
579
|
-
not-36px bug in an isolated browser test, not table.recipe.ts's own
|
|
648
|
+
not-36px bug in an isolated browser test, not table.recipe.ts's own
|
|
649
|
+
border/box-sizing, the hypothesis the issue itself flagged as
|
|
650
|
+
unconfirmed): the table cell's OWN `height: tableRow` (36px,
|
|
580
651
|
border-box) leaves 34px of content box once its 2px of top+bottom
|
|
581
652
|
border are counted, and `min-height: tableRow` here demanded 36px
|
|
582
653
|
of CONTENT height regardless -- overflowing the cell by 2px, which
|
|
583
654
|
auto-height table layout resolves by growing the whole row to fit,
|
|
584
655
|
landing at exactly the reported 38. `height: 100%` alone already
|
|
585
|
-
fills whatever the cell's real content box is (the doc comment above
|
|
656
|
+
fills whatever the cell's real content box is (the doc comment above
|
|
657
|
+
this rule's own stated intent), with nothing left demanding more. */
|
|
586
658
|
& .crisp-columncalc-trigger { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
587
659
|
& .crisp-columncalc-trigger:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
588
660
|
& .crisp-columncalc-trigger svg { flex-shrink: 0; opacity: 0.7; }
|
|
589
661
|
& .crisp-columncalc-trigger[data-align="right"] { justify-content: flex-end; }
|
|
590
662
|
& .crisp-columncalc-placeholder { overflow: hidden; text-overflow: ellipsis; }
|
|
591
663
|
& .crisp-columncalc-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; }
|
|
592
|
-
/* crisp#837: re-measured live against Attio's real footer calc label --
|
|
664
|
+
/* crisp#837: re-measured live against Attio's real footer calc label --
|
|
665
|
+
14px (was 13px, `c.text.md`, fixed on the shared trigger rule above)
|
|
666
|
+
and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this
|
|
667
|
+
file's own -op label already should have used instead of the flatter
|
|
593
668
|
`fgMuted` token (a close but not measured match). */
|
|
594
669
|
& .crisp-columncalc-op { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
595
670
|
& .crisp-columncalc-section { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
@@ -681,9 +756,13 @@
|
|
|
681
756
|
}
|
|
682
757
|
|
|
683
758
|
.crisp-datatable {
|
|
684
|
-
display: flex; flex-direction: column; gap: var(--crisp-space-2-5); font-family: var(--crisp-font-sans); /* The toolbar carried no horizontal inset of its own, so its content
|
|
685
|
-
(
|
|
686
|
-
|
|
759
|
+
display: flex; flex-direction: column; gap: var(--crisp-space-2-5); font-family: var(--crisp-font-sans); /* The toolbar carried no horizontal inset of its own, so its content
|
|
760
|
+
(search box, sort/filter chips) sat flush at the table's outer edge
|
|
761
|
+
(x=0) while the header row's own th/td padding (table.recipe.ts,
|
|
762
|
+
#465) starts every column's text at 12px -- one row down, the SAME
|
|
763
|
+
grid's own header cell already begins at that inset. c.space["3"]
|
|
764
|
+
here just matches the row directly below it, measured live against
|
|
765
|
+
Attio (the sort/filter row's search chip lines up with the first
|
|
687
766
|
column header's text, not the grid's raw edge). */
|
|
688
767
|
& .crisp-datatable-toolbar { display: flex; align-items: center; gap: var(--crisp-space-2); min-height: 49px; border-top: 1px solid var(--crisp-border-subtle); padding: 0 var(--crisp-space-3); }
|
|
689
768
|
& .crisp-datatable-search { position: relative; flex: 1; max-width: 280px; display: inline-flex; align-items: center; }
|
|
@@ -693,10 +772,7 @@
|
|
|
693
772
|
& .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
694
773
|
& .crisp-datatable-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
695
774
|
/* announced, never drawn */
|
|
696
|
-
& .crisp-datatable-live {
|
|
697
|
-
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
698
|
-
overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
|
|
699
|
-
}
|
|
775
|
+
& .crisp-datatable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
700
776
|
/* crisp/#645: visually-hidden-but-focusable, not visually-hidden-and-
|
|
701
777
|
inert like .crisp-datatable-live above -- same clip-rect shape,
|
|
702
778
|
this one just needs to actually hold DOM focus so a native
|
|
@@ -704,7 +780,8 @@
|
|
|
704
780
|
in datatable.tsx). resize: none keeps a stray native textarea handle
|
|
705
781
|
from ever being drawable, even though it's clipped to 1px anyway. */
|
|
706
782
|
& .crisp-datatable-clipboard-proxy { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; resize: none; }
|
|
707
|
-
/* single active cell (crisp/#645 follow-up -- this had no styling of its
|
|
783
|
+
/* single active cell (crisp/#645 follow-up -- this had no styling of its
|
|
784
|
+
own at all before, a gap against Golden Rule 0: RecordsTable's own
|
|
708
785
|
measured value, .crisp-recordstable-td[data-selected], brought
|
|
709
786
|
across unchanged now that a visible anchor actually matters for the
|
|
710
787
|
Shift+Click range below). */
|
|
@@ -713,57 +790,91 @@
|
|
|
713
790
|
tint formula already used twice below (tbody tr[data-selected] td)
|
|
714
791
|
for the same reason a selected group of rows gets one: a selected
|
|
715
792
|
GROUP of cells is the same kind of state, just cell-scoped instead of
|
|
716
|
-
row-scoped. Not independently re-measured against Attio's own range
|
|
793
|
+
row-scoped. Not independently re-measured against Attio's own range
|
|
794
|
+
highlight (out of scope this slice -- flagged on crisp#645). */
|
|
717
795
|
& td[data-in-range] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
718
|
-
/* The header cell has no padding of its own -- the button owns the
|
|
796
|
+
/* The header cell has no padding of its own -- the button owns the
|
|
797
|
+
full cell so the whole header is clickable (its own inset is 12px).
|
|
798
|
+
Mirrors the summary-row fix.
|
|
799
|
+
`& .crisp-table th`, not bare `& th` (found while re-checking #691's
|
|
719
800
|
own fix live): DataTable's root nests `Table`'s own wrapper, whose
|
|
720
801
|
`table.recipe.ts` carries `& th, & td { padding: 0 12px }` at the
|
|
721
802
|
SAME specificity (.crisp-table th vs .crisp-datatable th, both one
|
|
722
803
|
class + one element) -- a bare `& th` here only won by source
|
|
723
|
-
order, which flipped the moment table.recipe.ts's own CSS file
|
|
804
|
+
order, which flipped the moment table.recipe.ts's own CSS file
|
|
805
|
+
happened to land after datatable's in the build (alphabetical:
|
|
724
806
|
datatable < table), silently reinstating 12px on every header cell
|
|
725
|
-
in the whole product and making every interactive column's button
|
|
807
|
+
in the whole product and making every interactive column's button
|
|
808
|
+
double it to 24px. Scoping through `.crisp-table` adds a second
|
|
809
|
+
class to the selector (0,2,1 beats 0,1,1) so this can never lose a
|
|
810
|
+
specificity tie to source order again.
|
|
811
|
+
`thead th`, not a bare `th` (crisp#829): #779 made the primary
|
|
812
|
+
column's BODY cell a real `<th scope="row">` for a11y, and a bare
|
|
726
813
|
`th` here matches that one too, zeroing an inset nothing else
|
|
727
814
|
supplies -- the primary column's text sat flush left, one column's
|
|
728
815
|
cell no longer matching its own header or any sibling `<td>`. Only
|
|
729
|
-
the header row's own `<th>` needs zero padding (its sort BUTTON
|
|
816
|
+
the header row's own `<th>` needs zero padding (its sort BUTTON
|
|
817
|
+
owns the inset); the body row's `<th scope="row">` has no button,
|
|
730
818
|
and needs the SAME base 12px (table.recipe.ts, #465) every other
|
|
731
819
|
cell already gets. */
|
|
732
820
|
& .crisp-table thead th { padding: 0; }
|
|
733
|
-
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
|
|
734
|
-
|
|
821
|
+
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
|
|
822
|
+
Menu wraps its trigger in a flex div that sizes to its content, so a
|
|
823
|
+
long header grew past the column instead of filling it -- with nothing
|
|
824
|
+
left to squeeze, the label's own ellipsis CSS (below) had no properly
|
|
825
|
+
-sized box to truncate against, and the th's own overflow hard-clipped
|
|
826
|
+
it with no "...". Fill the wrapper, scoped to th so Menu's default
|
|
735
827
|
(correct everywhere else) is untouched. */
|
|
736
828
|
& th .crisp-menu { width: 100%; height: 100%; }
|
|
737
829
|
& .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
|
|
738
830
|
& .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
739
831
|
/* crisp/#605 follow-up: a header with neither a Menu nor a sort button
|
|
740
|
-
(the primary/entity column's now-inert path, or any column with no
|
|
741
|
-
|
|
832
|
+
(the primary/entity column's now-inert path, or any column with no
|
|
833
|
+
columnMenu/sortable at all) renders .crisp-datatable-th-inner as a
|
|
834
|
+
DIRECT child of th instead of nested inside a button -- and loses
|
|
835
|
+
the button's own 12px inset, drifting left of the td's 12px base
|
|
836
|
+
inset. Measured live on Attio's own Companies grid: the header label
|
|
837
|
+
and the cell's own text land at the exact same x (335px from the
|
|
838
|
+
viewport, both 40px from the column's left edge) via two different
|
|
742
839
|
padding+icon+gap combinations -- Attio does not leave the inert
|
|
743
840
|
primary header flush left either. The `>` combinator targets only
|
|
744
|
-
the button-less case: Menu's own wrapper (`.crisp-menu`) and the
|
|
841
|
+
the button-less case: Menu's own wrapper (`.crisp-menu`) and the
|
|
842
|
+
plain sort `button` both put >=1 more level between `th` and this
|
|
843
|
+
span, so their own 12px (already on the button) isn't doubled. */
|
|
745
844
|
& th > .crisp-datatable-th-inner { box-sizing: border-box; padding: 0 var(--crisp-space-3); }
|
|
746
|
-
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
845
|
+
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
747
846
|
owns the whole 246x37 area so a click anywhere in the cell opens the
|
|
748
847
|
menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
749
848
|
& tfoot td { padding: 0; }
|
|
750
|
-
/* Group heading row -- a view is grouped under a subtle label with the
|
|
751
|
-
|
|
849
|
+
/* Group heading row -- a view is grouped under a subtle label with the
|
|
850
|
+
bucket's count beside it. */
|
|
851
|
+
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
752
852
|
& .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
753
853
|
& .crisp-datatable-group-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
754
|
-
|
|
854
|
+
& .crisp-datatable-group { height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-3); background: var(--crisp-bg-subtle); border-bottom: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
755
855
|
& .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
|
|
756
856
|
& .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
|
|
757
857
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
758
|
-
|
|
759
|
-
|
|
858
|
+
/* #719: overflow: clip, not hidden, on every truncation rule below --
|
|
859
|
+
hidden still honours a programmatic scrollLeft assignment (found via
|
|
860
|
+
a screenshot tool that pans anything with scrollWidth > clientWidth),
|
|
861
|
+
blanking or fragmenting the visible text even though real user
|
|
862
|
+
scrolling was already blocked. clip renders the ellipsis identically
|
|
863
|
+
and leaves no scroll position to move. */
|
|
864
|
+
& .crisp-datatable-th-label { overflow: clip; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
865
|
+
/* #465: 12px per the comment above (and Attio's measured header cell
|
|
866
|
+
padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
|
|
867
|
+
own documented value. */
|
|
760
868
|
& .crisp-datatable-sort { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: none; font: inherit; letter-spacing: inherit; color: inherit; text-align: start; cursor: pointer; }
|
|
761
869
|
/* A right-aligned column's header keeps its field-icon + label packed at
|
|
762
870
|
the START, matching its own values only in that the VALUES right-align
|
|
763
871
|
-- Attio's own right-aligned header (measured live: "Twitter follower
|
|
764
|
-
count") keeps the icon+label left and only the trailing column-menu
|
|
765
|
-
|
|
766
|
-
|
|
872
|
+
count") keeps the icon+label left and only the trailing column-menu
|
|
873
|
+
icon sits pinned to the right edge, independent of the label's width
|
|
874
|
+
(#406, reversing #393's own justify-content: flex-end here). The
|
|
875
|
+
chevron's own margin-inline-start: auto below already pins IT to the
|
|
876
|
+
end of a flex-start row with no override needed -- that's what pins
|
|
877
|
+
the trailing icon on Attio too. */
|
|
767
878
|
& .crisp-datatable-chevron { margin-inline-start: auto; flex-shrink: 0; color: var(--crisp-fg-muted); opacity: 0; transition: opacity .12s; }
|
|
768
879
|
& .crisp-datatable-sort:hover .crisp-datatable-chevron { opacity: 0.6; }
|
|
769
880
|
& .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: var(--crisp-fg-primary); }
|
|
@@ -771,17 +882,23 @@
|
|
|
771
882
|
& th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: var(--crisp-bg-surface); }
|
|
772
883
|
/* `thead th[data-sticky]`, not a bare `th[data-sticky]` (crisp#848, same
|
|
773
884
|
bare-`th` family as #829/#833/#835): this z-index:3 was written for
|
|
774
|
-
the HEADER's own sticky corner cell (sticky column x sticky header),
|
|
775
|
-
|
|
885
|
+
the HEADER's own sticky corner cell (sticky column x sticky header),
|
|
886
|
+
meant to win over everything else. Unscoped, it also matched the
|
|
887
|
+
primary column's BODY cell -- a real `<th scope="row" data-sticky>`
|
|
888
|
+
since #779 -- giving every scrolled body row's own sticky cell a
|
|
889
|
+
HIGHER z-index than the sticky FOOTER's (2), so it painted over the
|
|
776
890
|
footer instead of the footer showing through. Confirmed live on a
|
|
777
|
-
real bounded-height, 25-row table (GRC's Risk register): scrolled
|
|
891
|
+
real bounded-height, 25-row table (GRC's Risk register): scrolled
|
|
892
|
+
partway, `elementFromPoint` at the footer's own on-screen cell
|
|
778
893
|
resolved to a body row's `<th>`, not the footer's `<td>`, and that
|
|
779
894
|
`<th>`'s computed z-index read 3. Scoped to `thead`, a body row's
|
|
780
895
|
own sticky `<th>` now falls back to the base rule above (z-index 1,
|
|
781
|
-
correct -- the same as a plain sticky `<td>`), and the footer's own
|
|
896
|
+
correct -- the same as a plain sticky `<td>`), and the footer's own
|
|
897
|
+
explicit z-index below is unaffected either way. */
|
|
782
898
|
& thead th[data-sticky] { z-index: 3; }
|
|
783
899
|
/* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
|
|
784
|
-
`tfoot td { z-index: 2 }`), which `td[data-sticky]`'s own higher-specificity
|
|
900
|
+
`tfoot td { z-index: 2 }`), which `td[data-sticky]`'s own higher-specificity
|
|
901
|
+
`z-index: 1` would otherwise undercut -- keep it level with the row it's in. */
|
|
785
902
|
& tfoot td[data-sticky] { z-index: 2; }
|
|
786
903
|
& tbody tr[data-selected] td[data-sticky] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
787
904
|
& tbody tr:hover td[data-sticky] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
|
|
@@ -801,7 +918,8 @@
|
|
|
801
918
|
/* crisp/#758: AI-enriched column marker, ported from RecordsTable's own
|
|
802
919
|
already-measured value -- a full-bleed #9b69ff (bgPurple) wash at 4%,
|
|
803
920
|
composited OVER whatever row-state background the cell already has
|
|
804
|
-
(hover, selected), which is why it's an ::after overlay and not a
|
|
921
|
+
(hover, selected), which is why it's an ::after overlay and not a
|
|
922
|
+
plain background. */
|
|
805
923
|
& td[data-enriched]::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: color-mix(in srgb, var(--crisp-bg-purple) 4%, transparent); }
|
|
806
924
|
& .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; }
|
|
807
925
|
& .crisp-datatable-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
@@ -812,40 +930,56 @@
|
|
|
812
930
|
& .crisp-datatable-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
813
931
|
& .crisp-datatable-edit-pending { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); color: var(--crisp-fg-muted); vertical-align: middle; }
|
|
814
932
|
/* The rejection's message, beside the cell's own content -- a sibling in
|
|
815
|
-
the TableCell, never nested inside a column's own render output, so a
|
|
933
|
+
the TableCell, never nested inside a column's own render output, so a
|
|
934
|
+
hover-only wrapper (a Tooltip, say) around a custom render can't hide
|
|
816
935
|
it. Block-level: the row grows to fit it rather than floating over
|
|
817
936
|
the row below, so it can never end up clipped by the scroll
|
|
818
|
-
container's overflow the way a position:fixed escape would need
|
|
937
|
+
container's overflow the way a position:fixed escape would need
|
|
938
|
+
guarding against. */
|
|
819
939
|
& .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); }
|
|
820
|
-
/* editor: "select"/"switch" -- always live, no separate edit mode, so
|
|
940
|
+
/* editor: "select"/"switch" -- always live, no separate edit mode, so
|
|
941
|
+
the cell IS the picker: same chromeless-fill treatment as
|
|
942
|
+
RecordsTable's own --picker cells (measured there already; DataTable
|
|
821
943
|
shares RecordsTable's grid, Golden Rule 0). */
|
|
822
944
|
& .crisp-datatable-td--picker { padding: 0; }
|
|
823
945
|
& .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); }
|
|
824
946
|
& .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; }
|
|
825
947
|
& .crisp-datatable-td--picker .crisp-datatable-edit-error { padding-inline-start: var(--crisp-space-2); }
|
|
826
|
-
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
827
|
-
|
|
948
|
+
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
949
|
+
"Create X" row when the consumer supplies one (#449) -- same measured
|
|
950
|
+
values as RecordsTable's own .crisp-recordstable-refoption*. */
|
|
951
|
+
& .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: clip; text-overflow: ellipsis; }
|
|
828
952
|
& .crisp-datatable-refoption-avatar { flex-shrink: 0; }
|
|
829
953
|
& .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
|
|
830
954
|
& .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); }
|
|
831
955
|
/* #826 -- the full-body loading state (a filter/sort re-query, or a
|
|
832
|
-
fresh page boot), measured live on Attio's Companies grid on both
|
|
956
|
+
fresh page boot), measured live on Attio's Companies grid on both
|
|
957
|
+
triggers: icon+text centred in the row-body area, 10px gap, 14px/500
|
|
958
|
+
weight/20px line-height, both icon and text in the SAME muted
|
|
959
|
+
rgba(0,0,0,0.63) -- the same color-mix figure this file already uses
|
|
960
|
+
for other muted text (e.g. -phone-dial). Distinct from the cold
|
|
961
|
+
in-place row load (blank, no indicator) and the warm-navigation
|
|
962
|
+
per-cell shimmer (#599) -- neither of those swaps the whole body. */
|
|
833
963
|
& .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; }
|
|
834
964
|
& .crisp-datatable-loading .crisp-spinner { border-top-color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
835
|
-
/* #579: click-to-expand overlay for a truncated cell -- a read-only,
|
|
836
|
-
|
|
837
|
-
|
|
965
|
+
/* #579: click-to-expand overlay for a truncated cell -- a read-only,
|
|
966
|
+
full-value card, settled live as click (not Attio's usual
|
|
967
|
+
hover-expand) and measured position: absolute, unlike this file's
|
|
968
|
+
floating chrome (Menu/Select popovers) which portals and escapes the
|
|
969
|
+
scroll container. Deliberately NOT the edit-error pattern above
|
|
970
|
+
(grow the row, block-level, never clipped): a virtualized grid
|
|
971
|
+
assumes a fixed row height for its scroll math (owned by the grid
|
|
972
|
+
core, not this cell), so growing a row here would fight it. Anchored
|
|
973
|
+
to the SAME column width the cell itself renders at (measured:
|
|
974
|
+
Attio's own overlay came out only slightly wider than the
|
|
975
|
+
triggering cell's clientWidth -- the overshoot is this padding),
|
|
976
|
+
wrapping onto as many lines as the value needs; it CAN be clipped by
|
|
977
|
+
`.crisp-table-scroll`'s own `overflow: auto` if it grows past the
|
|
838
978
|
visible viewport, same as the edit-error comment above already
|
|
839
979
|
notes for any position:absolute escape -- unmeasured against Attio
|
|
840
980
|
for this exact case, flagged rather than guessed. */
|
|
841
981
|
& td[data-cell-expanded] { overflow: visible; z-index: 7; }
|
|
842
|
-
& .crisp-datatable-cell-overlay {
|
|
843
|
-
position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box;
|
|
844
|
-
padding: var(--crisp-space-2) var(--crisp-space-3); background: var(--crisp-bg-surface);
|
|
845
|
-
border: 1px solid var(--crisp-bg-brand-solid); border-radius: 4px;
|
|
846
|
-
font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium);
|
|
847
|
-
color: var(--crisp-fg-primary); white-space: normal; word-break: break-word; cursor: default;
|
|
848
|
-
}
|
|
982
|
+
& .crisp-datatable-cell-overlay { position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box; padding: var(--crisp-space-2) var(--crisp-space-3); background: var(--crisp-bg-surface); border: 1px solid var(--crisp-bg-brand-solid); border-radius: 4px; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); white-space: normal; word-break: break-word; cursor: default; }
|
|
849
983
|
/* fixed layout so column widths (and resize) are exact — like RecordsTable */
|
|
850
984
|
& table { table-layout: fixed; }
|
|
851
985
|
/* read-only/computed column marker (#596) -- sits just inside the
|
|
@@ -857,42 +991,70 @@
|
|
|
857
991
|
& .crisp-datatable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
|
|
858
992
|
& .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; }
|
|
859
993
|
& .crisp-datatable-resize:hover::after, & .crisp-datatable-resize[data-resizing]::after { opacity: 1; }
|
|
860
|
-
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's
|
|
994
|
+
/* crisp/#731 -- column drag-to-reorder. Measured live against Attio's
|
|
995
|
+
own grid (the issue's own comment): the dragged header keeps full
|
|
861
996
|
opacity and the plain `pointer` cursor throughout (Attio draws no
|
|
862
997
|
ghost and no "grabbing" cursor of its own), so this adds nothing to
|
|
863
998
|
`[data-dragging]` itself -- the ONLY new paint is the drop-indicator
|
|
864
|
-
line, a 3px bar in the same measured brand blue the resize handle's
|
|
999
|
+
line, a 3px bar in the same measured brand blue the resize handle's
|
|
1000
|
+
own hover state (above) already uses, positioned on whichever edge of
|
|
1001
|
+
the hovered header the pointer is closer to. */
|
|
865
1002
|
& th[data-dragging] { cursor: pointer; }
|
|
866
1003
|
& 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; }
|
|
867
1004
|
& th[data-drop-before]::before { inset-inline-start: -1.5px; }
|
|
868
1005
|
& th[data-drop-after]::after { inset-inline-end: -1.5px; }
|
|
869
1006
|
/* typed cells — entity (avatar + name), colour-coded tags, numbers, dates */
|
|
870
1007
|
& .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); }
|
|
871
|
-
/* crisp/#601 supersession follow-up -- the same flex-row shape
|
|
1008
|
+
/* crisp/#601 supersession follow-up -- the same flex-row shape
|
|
1009
|
+
.crisp-datatable-entity gives its own avatar+name+actions, but
|
|
1010
|
+
structural only (no entity-specific colour/weight): lets
|
|
1011
|
+
onOpenComments/onOpenPreview compose alongside ANY column's own
|
|
872
1012
|
content (a custom render, or a non-entity built-in type), not just
|
|
873
1013
|
type: "entity"'s own inline rendering. */
|
|
874
1014
|
& .crisp-datatable-cell-actions-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; width: 100%; }
|
|
875
|
-
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text,
|
|
1015
|
+
/* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text,
|
|
1016
|
+
plain hover vs rest) that Attio's underline is unconditional, not a
|
|
876
1017
|
hover reveal -- identical at rest and on hover: text-decoration-color
|
|
877
|
-
is rgba(0,0,0,0.09), a 9% tint, not the name's own full-contrast text
|
|
878
|
-
|
|
1018
|
+
is rgba(0,0,0,0.09), a 9% tint, not the name's own full-contrast text
|
|
1019
|
+
colour. The previous :hover-gated, full-contrast rule here was itself
|
|
1020
|
+
unmeasured and wrong in two ways at once. */ /* crisp#851 -- Attio's own entity/record names are measured at
|
|
1021
|
+
font-weight 500, distinct from a plain-text primary column's 400
|
|
1022
|
+
(table.recipe.ts's own `tbody th` default). This was never its own
|
|
879
1023
|
explicit style -- it silently rode on a since-fixed header-rule leak
|
|
880
1024
|
(#833/#835/#848) that happened to apply the same 500 to every
|
|
881
1025
|
primary-column body cell regardless of type. Made explicit here so
|
|
882
1026
|
fixing that leak doesn't also (wrongly) drop entity names to 400. */
|
|
883
|
-
& .crisp-datatable-entity-name { overflow:
|
|
884
|
-
|
|
885
|
-
|
|
1027
|
+
& .crisp-datatable-entity-name { overflow: clip; 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); }
|
|
1028
|
+
/* #893: shared by the button (onEntityClick, a different record) and
|
|
1029
|
+
the anchor (href, the row's own record) -- was button-only, which
|
|
1030
|
+
silently left a real <a> unstyled the day #893 added one. */
|
|
1031
|
+
& .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%; }
|
|
1032
|
+
/* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary
|
|
1033
|
+
column, revealed on ROW hover (the issue's own title says "row
|
|
886
1034
|
hover", and a live check confirmed hovering well past the name --
|
|
887
|
-
not just the icons' own hit target -- still reveals them) or
|
|
1035
|
+
not just the icons' own hit target -- still reveals them) or
|
|
1036
|
+
keyboard focus. Measured live: border-radius 6px, icon colour
|
|
1037
|
+
rgba(0,0,0,0.55) at rest, darkening to the full text colour with a
|
|
1038
|
+
rgba(0,0,0,0.04) background on the icon's OWN hover -- both
|
|
888
1039
|
expressed as color-mix against fgPrimary so they stay correct in
|
|
889
1040
|
dark mode instead of a literal black that would invert. */
|
|
890
1041
|
& .crisp-datatable-entity-actions { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
891
1042
|
& tr:hover .crisp-datatable-entity-actions, & .crisp-datatable-entity-actions:focus-within { opacity: 1; }
|
|
892
1043
|
& .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; }
|
|
893
1044
|
& .crisp-datatable-entity-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
894
|
-
|
|
895
|
-
|
|
1045
|
+
/* #892: the default shape's radius was a stray literal (radius.sm, 6px)
|
|
1046
|
+
-- Attio's own real company/object avatar measures 30%, which is
|
|
1047
|
+
Avatar's own already-shipped shape="rounded" value, not a new number.
|
|
1048
|
+
shape="circle" reuses Avatar's own shape="circle" value (radius.full)
|
|
1049
|
+
the same way, measured live on a real Attio person avatar. */
|
|
1050
|
+
& .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: 30%; 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); }
|
|
1051
|
+
& .crisp-datatable-avatar[data-shape="circle"] { border-radius: var(--crisp-radius-full); }
|
|
1052
|
+
& .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
|
|
1053
|
+
& .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
|
|
1054
|
+
& .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
|
|
1055
|
+
& .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
|
|
1056
|
+
& .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
|
|
1057
|
+
& .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
|
|
896
1058
|
& .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
|
|
897
1059
|
& .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
|
|
898
1060
|
& .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); }
|
|
@@ -905,13 +1067,19 @@
|
|
|
905
1067
|
& .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)); }
|
|
906
1068
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
907
1069
|
& .crisp-datatable-muted { color: var(--crisp-fg-muted); }
|
|
908
|
-
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
1070
|
+
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
1071
|
+
TasksTable's own overdue due-date (crisp#462), plain text colour, no
|
|
909
1072
|
fill/weight change. */
|
|
910
1073
|
& .crisp-datatable-danger { color: var(--crisp-fg-danger); }
|
|
911
|
-
/* url/email cell types (#654) -- same measured values as RecordsTable's
|
|
912
|
-
|
|
1074
|
+
/* url/email cell types (#654) -- same measured values as RecordsTable's
|
|
1075
|
+
own .crisp-recordstable-link, which this mirrors: no underline at
|
|
1076
|
+
rest, underline on hover, own-colour text rather than a browser-blue
|
|
1077
|
+
link. */
|
|
1078
|
+
& .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: clip; text-overflow: ellipsis; }
|
|
913
1079
|
& .crisp-datatable-link:hover { text-decoration: underline; }
|
|
914
|
-
/* phone cell type/editor (#765) -- measured live: the dial-code prefix
|
|
1080
|
+
/* phone cell type/editor (#765) -- measured live: the dial-code prefix
|
|
1081
|
+
is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
|
|
1082
|
+
value already measured elsewhere in this file. */
|
|
915
1083
|
& .crisp-datatable-phone { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
916
1084
|
& .crisp-datatable-phone-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
917
1085
|
& .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); }
|
|
@@ -941,7 +1109,8 @@
|
|
|
941
1109
|
value rows (32px = size.menuRow, 5px 8px padding, 8px gap between
|
|
942
1110
|
the grip/value/actions, 16px icons) above one ALWAYS-blank trailing
|
|
943
1111
|
DataPhoneEditor-shaped row -- that blank row is the only "add
|
|
944
|
-
another" affordance, there's no separate button for it. The
|
|
1112
|
+
another" affordance, there's no separate button for it. The
|
|
1113
|
+
copy/delete pair reuses .crisp-datatable-entity-action's own
|
|
945
1114
|
hover-reveal chrome (not independently re-measured as its own hit
|
|
946
1115
|
target this pass, only the 16px icon glyphs were). */
|
|
947
1116
|
& .crisp-datatable-phone-multi-editor { display: flex; flex-direction: column; }
|
|
@@ -949,8 +1118,7 @@
|
|
|
949
1118
|
& .crisp-datatable-phone-multi-row .crisp-datatable-phone-link { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
950
1119
|
& .crisp-datatable-phone-multi-grip { color: var(--crisp-fg-muted); flex-shrink: 0; cursor: grab; }
|
|
951
1120
|
& .crisp-datatable-phone-multi-actions { display: flex; align-items: center; gap: var(--crisp-space-1); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
|
|
952
|
-
& .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions,
|
|
953
|
-
& .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
|
|
1121
|
+
& .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions, & .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
|
|
954
1122
|
& .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; }
|
|
955
1123
|
& .crisp-datatable-phone-multi-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
956
1124
|
/* datetime cell editor (#762) -- DatePickerField + TimePicker side by side. */
|
|
@@ -959,7 +1127,10 @@
|
|
|
959
1127
|
18px pitch (a 2px gap), an empty star at rgba(0,0,0,0.1), a
|
|
960
1128
|
committed/filled star at brand600 (--crisp-bg-brand-solid, an exact
|
|
961
1129
|
match to the measured #266df0), and a distinct hover-preview colour
|
|
962
|
-
-- rgb(33,91,196) -- that's close to but NOT brand700/bgBrandSolidPressed
|
|
1130
|
+
-- rgb(33,91,196) -- that's close to but NOT brand700/bgBrandSolidPressed
|
|
1131
|
+
(#1f5fd6); kept as its own literal rather than forced onto that token,
|
|
1132
|
+
since the two were measured stable and different. The read-only svg
|
|
1133
|
+
and the editable button's own inner svg both carry the
|
|
963
1134
|
crisp-datatable-rating-star class on the svg itself (not the
|
|
964
1135
|
button), so one set of fill rules covers both -- the button only
|
|
965
1136
|
adds its own reset + cursor via a separate -btn class. */
|
|
@@ -970,9 +1141,13 @@
|
|
|
970
1141
|
& .crisp-datatable-rating-star[data-hovering] path { fill: #215bc4; }
|
|
971
1142
|
& .crisp-datatable-rating-star-btn { display: inline-flex; padding: 0; margin: 0; border: none; background: none; font-family: inherit; cursor: pointer; }
|
|
972
1143
|
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
|
|
973
|
-
a leading 20px grip column, a 16px grip icon, and the row's own
|
|
1144
|
+
a leading 20px grip column, a 16px grip icon, and the row's own
|
|
1145
|
+
hairline doubling as the drop indicator (it tints toward the brand
|
|
1146
|
+
colour as the active drop target). The affordance + geometry are
|
|
1147
|
+
measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
|
|
974
1148
|
draggable + dataTransfer, the same one column reorder already uses
|
|
975
|
-
(RecordsTable's reorderColumn) -- not a proprietary
|
|
1149
|
+
(RecordsTable's reorderColumn) -- not a proprietary
|
|
1150
|
+
pointer-events implementation. */
|
|
976
1151
|
& .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
|
|
977
1152
|
& .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; }
|
|
978
1153
|
& .crisp-datatable-grip:active { cursor: grabbing; }
|
|
@@ -1006,36 +1181,22 @@
|
|
|
1006
1181
|
measurement -- accessibility wins over the seed reference.
|
|
1007
1182
|
neutralMuted clears it, 6.62:1 light / 14.71:1 dark (dark was
|
|
1008
1183
|
already fine at 9.43:1). */
|
|
1009
|
-
& .crisp-datepicker-weekday {
|
|
1010
|
-
display: flex; align-items: center; justify-content: center;
|
|
1011
|
-
height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-muted);
|
|
1012
|
-
font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium);
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1184
|
+
& .crisp-datepicker-weekday { display: flex; align-items: center; justify-content: center; height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-muted); font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium); }
|
|
1015
1185
|
& .crisp-datepicker-months { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; min-width: 0; }
|
|
1016
1186
|
& .crisp-datepicker-months[data-wheel-open] { visibility: hidden; }
|
|
1017
1187
|
& .crisp-datepicker-month { min-width: 0; }
|
|
1018
|
-
& .crisp-datepicker-month-label {
|
|
1019
|
-
display: flex; align-items: center; height: 24px;
|
|
1020
|
-
color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px;
|
|
1021
|
-
font-weight: var(--crisp-weight-medium);
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1188
|
+
& .crisp-datepicker-month-label { display: flex; align-items: center; height: 24px; color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
|
|
1024
1189
|
& .crisp-datepicker-grid { display: grid; min-width: 0; }
|
|
1025
1190
|
& .crisp-datepicker-week-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
|
1026
|
-
|
|
1027
|
-
& .crisp-datepicker-cell {
|
|
1028
|
-
position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell);
|
|
1029
|
-
isolation: isolate;
|
|
1030
|
-
}
|
|
1191
|
+
& .crisp-datepicker-cell { position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell); isolation: isolate; }
|
|
1031
1192
|
& .crisp-datepicker-empty-cell { min-height: var(--crisp-size-calendarCell); }
|
|
1032
|
-
|
|
1033
1193
|
/* The bridge joining days inside a completed range.
|
|
1034
1194
|
The endpoints do NOT carry data-in-range -- only the interior days do --
|
|
1035
1195
|
so these are three independent rules, not a base plus two modifiers. A
|
|
1036
1196
|
modifier that sets only inset-inline-start never generates a pseudo
|
|
1037
1197
|
element on an endpoint, which leaves a half-cell of white between the
|
|
1038
|
-
endpoint's pill and the run of grey beside it. Each rule declares its
|
|
1198
|
+
endpoint's pill and the run of grey beside it. Each rule declares its
|
|
1199
|
+
own content. */
|
|
1039
1200
|
& .crisp-datepicker-cell[data-range-complete][data-in-range]::before { content: ""; position: absolute; z-index: -1; inset-inline: 0; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
|
|
1040
1201
|
& .crisp-datepicker-cell[data-range-complete][data-range-start]:not([data-range-end])::before { content: ""; position: absolute; z-index: -1; inset-inline-start: 50%; inset-inline-end: 0; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
|
|
1041
1202
|
& .crisp-datepicker-cell[data-range-complete][data-range-end]:not([data-range-start])::before { content: ""; position: absolute; z-index: -1; inset-inline-start: 0; inset-inline-end: 50%; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
|
|
@@ -1051,33 +1212,19 @@
|
|
|
1051
1212
|
& .crisp-datepicker-date:disabled { color: var(--crisp-fg-disabled); cursor: not-allowed; }
|
|
1052
1213
|
& .crisp-datepicker-date:focus-visible::after { content: ""; position: absolute; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); left: 50%; width: var(--crisp-size-calendarPill); height: var(--crisp-size-calendarPill); transform: translateX(-50%); border-radius: var(--crisp-radius-md); outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; }
|
|
1053
1214
|
& .crisp-datepicker-date-content { position: relative; z-index: 1; display: flex; width: 100%; min-height: var(--crisp-size-calendarCell); min-width: 0; box-sizing: border-box; flex-direction: column; align-items: center; gap: 3px; padding-top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); color: inherit; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); font-variant-numeric: tabular-nums; }
|
|
1054
|
-
/* The numeral is its own 42px flex box so it centres on the 42px pill.
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1215
|
+
/* The numeral is its own 42px flex box so it centres on the 42px pill.
|
|
1216
|
+
Without this the content column top-aligns the glyph and the pill reads
|
|
1217
|
+
as offset — the cell is 48px, the pill 42px inset 3px, and only a
|
|
1218
|
+
42px-tall numeral box shares the pill's centre line. */
|
|
1219
|
+
& .crisp-datepicker-date-content > [data-date-picker-day] { display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0; align-items: center; justify-content: center; }
|
|
1060
1220
|
/* the year/month wheel, laid over the grid it replaces */
|
|
1061
|
-
& .crisp-datepicker-wheel-container {
|
|
1062
|
-
position: absolute; z-index: 1; inset-inline: 0;
|
|
1063
|
-
top: var(--crisp-size-menuRow); bottom: 0;
|
|
1064
|
-
display: flex; align-items: center; overflow: hidden;
|
|
1065
|
-
background: var(--crisp-bg-surface);
|
|
1066
|
-
}
|
|
1221
|
+
& .crisp-datepicker-wheel-container { position: absolute; z-index: 1; inset-inline: 0; top: var(--crisp-size-menuRow); bottom: 0; display: flex; align-items: center; overflow: hidden; background: var(--crisp-bg-surface); }
|
|
1067
1222
|
& .crisp-datepicker-wheel { width: 100%; }
|
|
1068
|
-
|
|
1069
|
-
& .crisp-datepicker-continuous-scroll {
|
|
1070
|
-
height: 100%; min-height: 0; overflow-y: auto;
|
|
1071
|
-
overscroll-behavior: contain; scrollbar-width: none;
|
|
1072
|
-
}
|
|
1223
|
+
& .crisp-datepicker-continuous-scroll { height: 100%; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
|
|
1073
1224
|
& .crisp-datepicker-continuous-scroll::-webkit-scrollbar { display: none; }
|
|
1074
1225
|
& .crisp-datepicker-continuous-content { display: flex; flex-direction: column; }
|
|
1075
|
-
|
|
1076
1226
|
/* announced, never drawn */
|
|
1077
|
-
& .crisp-datepicker-live-region {
|
|
1078
|
-
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
1079
|
-
overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
|
|
1080
|
-
}
|
|
1227
|
+
& .crisp-datepicker-live-region { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
1081
1228
|
}
|
|
1082
1229
|
.crisp-datepicker--visibleRange_month {
|
|
1083
1230
|
|
|
@@ -1104,14 +1251,17 @@
|
|
|
1104
1251
|
|
|
1105
1252
|
.crisp-datepickerfield {
|
|
1106
1253
|
display: inline-flex; font-family: var(--crisp-font-sans);
|
|
1107
|
-
& .crisp-datepickerfield-box { display: inline-flex; align-items: center; box-sizing: border-box; height: 32px; margin: 0; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); }
|
|
1254
|
+
& .crisp-datepickerfield-box { display: inline-flex; align-items: center; width: 100%; box-sizing: border-box; height: 32px; margin: 0; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); }
|
|
1108
1255
|
& .crisp-datepickerfield-box[data-ghost] { background: transparent; box-shadow: none; }
|
|
1109
1256
|
& .crisp-datepickerfield-box[data-ghost]:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
|
|
1110
|
-
& .crisp-datepickerfield-trigger { display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 100%; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; background: none; color: inherit; font-family: inherit; font-size: inherit; white-space: nowrap; cursor: pointer; }
|
|
1257
|
+
& .crisp-datepickerfield-trigger { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 100%; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; background: none; color: inherit; font-family: inherit; font-size: inherit; white-space: nowrap; cursor: pointer; }
|
|
1111
1258
|
& .crisp-datepickerfield-box[data-placeholder] .crisp-datepickerfield-trigger { color: var(--crisp-fg-muted); }
|
|
1112
1259
|
& .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
1113
1260
|
/* Reuses TableToolbar's measured filter-chip remove button
|
|
1114
|
-
(tabletoolbar.chrome.ts's .crisp-tabletoolbar-fchip-x) -- the same
|
|
1261
|
+
(tabletoolbar.chrome.ts's .crisp-tabletoolbar-fchip-x) -- the same
|
|
1262
|
+
small inline "clear this value" affordance, not a freshly-measured
|
|
1263
|
+
one: no live Attio composition for a DatePickerField-equivalent
|
|
1264
|
+
clear was reachable this round (#394). */
|
|
1115
1265
|
& .crisp-datepickerfield-clear { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin-inline-end: var(--crisp-space-1); padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; }
|
|
1116
1266
|
& .crisp-datepickerfield-clear:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
|
|
1117
1267
|
& .crisp-datepickerfield-panel { padding: var(--crisp-space-2); width: 300px; }
|
|
@@ -1119,16 +1269,20 @@
|
|
|
1119
1269
|
& .crisp-datepickerfield-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
|
|
1120
1270
|
& .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
|
|
1121
1271
|
}
|
|
1272
|
+
.crisp-datepickerfield--width_full {
|
|
1273
|
+
width: 100%;
|
|
1274
|
+
}
|
|
1275
|
+
.crisp-datepickerfield--width_auto {
|
|
1276
|
+
width: auto;
|
|
1277
|
+
}
|
|
1122
1278
|
|
|
1123
1279
|
.crisp-dialog {
|
|
1124
1280
|
display: contents; font-family: var(--crisp-font-sans);
|
|
1125
1281
|
& .crisp-dialog-backdrop { position: fixed; inset: 0; z-index: 60; background: var(--crisp-bg-scrim); }
|
|
1126
1282
|
& .crisp-dialog-positioner { position: fixed; inset: 0; z-index: 61; display: flex; align-items: flex-start; justify-content: center; padding: 15vh var(--crisp-space-4) var(--crisp-space-4); }
|
|
1127
1283
|
& .crisp-dialog-positioner[data-variant="alert"] { align-items: center; padding: var(--crisp-space-4); }
|
|
1128
|
-
& .crisp-dialog-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 90vw; max-height: 74vh;
|
|
1129
|
-
& .crisp-dialog-
|
|
1130
|
-
& .crisp-dialog-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); overflow: hidden; }
|
|
1131
|
-
& .crisp-dialog-content[data-variant="alert"] .crisp-dialog-card { border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); }
|
|
1284
|
+
& .crisp-dialog-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 90vw; max-height: 74vh; opacity: 1; transform: scale(1); transition: opacity 0.2s ease, transform 0.2s ease; @starting-style { opacity: 0; transform: scale(0.97); } }
|
|
1285
|
+
& .crisp-dialog-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-3xl); background: var(--crisp-bg-surface); overflow: hidden; }
|
|
1132
1286
|
& .crisp-dialog-header { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; height: 52px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-4); border-bottom: 1px solid var(--crisp-border-subtle); }
|
|
1133
1287
|
& .crisp-dialog-header svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
1134
1288
|
& .crisp-dialog-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); margin: 0; }
|
|
@@ -1137,8 +1291,10 @@
|
|
|
1137
1291
|
/* The discard-confirm's own stacked title + sentence (crisp#677) — no
|
|
1138
1292
|
border, no close button, unlike the panel header above: measured
|
|
1139
1293
|
live, both themes, 18px/24px 600-weight title (no scale token
|
|
1140
|
-
reaches 18px — the scale tops out at text.xl's 16px, so this is raw
|
|
1141
|
-
|
|
1294
|
+
reaches 18px — the scale tops out at text.xl's 16px, so this is raw
|
|
1295
|
+
px per Golden Rule 3's "genuinely intrinsic size" exception, same as
|
|
1296
|
+
this file's own submit-key glyphs) then a 14px/20px 500-weight
|
|
1297
|
+
sentence 4px below it. */
|
|
1142
1298
|
& .crisp-dialog-alert-header { display: flex; flex-direction: column; gap: var(--crisp-space-1); padding: var(--crisp-space-4) var(--crisp-space-4) 0; }
|
|
1143
1299
|
& .crisp-dialog-alert-title { margin: 0; font-size: 18px; line-height: 24px; font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
1144
1300
|
& .crisp-dialog-alert-description { margin: 0; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-alert-description); }
|
|
@@ -1148,7 +1304,12 @@
|
|
|
1148
1304
|
& .crisp-dialog-field { display: flex; flex-direction: column; gap: var(--crisp-space-1-5); }
|
|
1149
1305
|
& .crisp-dialog-field-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 50%, transparent); }
|
|
1150
1306
|
& .crisp-dialog-more { display: inline-flex; align-items: center; gap: var(--crisp-space-2); margin-inline-end: auto; border: none; background: none; padding: 0; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); cursor: pointer; }
|
|
1151
|
-
|
|
1307
|
+
/* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
|
|
1308
|
+
the accent (#0298d9) only clears 3.23:1 with white; the darker
|
|
1309
|
+
sibling clears 4.5:1+, same fix already applied to Button/Badge/
|
|
1310
|
+
Avatar (#897). Scoped to this one fill only -- Dialog's own frosted-
|
|
1311
|
+
surface identity (#934) is untouched here. */
|
|
1312
|
+
& .crisp-dialog-submit { display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 28px; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
1152
1313
|
& .crisp-dialog-submit-key { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
1153
1314
|
& .crisp-dialog-submit-key kbd { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; padding: 0 3px; border-radius: 4px; background: transparent; color: var(--crisp-fg-on-brand); font-family: inherit; font-style: normal; font-size: 10px; }
|
|
1154
1315
|
}
|
|
@@ -1222,7 +1383,9 @@
|
|
|
1222
1383
|
& .crisp-emptystate-icon { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; margin-bottom: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: color-mix(in srgb, var(--crisp-fg-primary) 5%, transparent); color: var(--crisp-fg-muted); }
|
|
1223
1384
|
& .crisp-emptystate-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
1224
1385
|
& .crisp-emptystate-desc { max-width: 320px; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
1225
|
-
/* #603: measured 8px gap between "Import CSV"/"Connect data source" --
|
|
1386
|
+
/* #603: measured 8px gap between "Import CSV"/"Connect data source" --
|
|
1387
|
+
inline-flex so one action (the common case) or several lay out the
|
|
1388
|
+
same way, wrapping if the container is narrow. */
|
|
1226
1389
|
& .crisp-emptystate-action { display: inline-flex; align-items: center; flex-wrap: wrap; justify-content: center; gap: var(--crisp-space-2); margin-top: var(--crisp-space-2); }
|
|
1227
1390
|
/* #603: Attio's zero-records "Learn more" card -- a label above a
|
|
1228
1391
|
clickable icon+title tile. Left/start-aligned, unlike the rest of
|
|
@@ -1242,13 +1405,13 @@
|
|
|
1242
1405
|
.crisp-emptystate--variant_page {
|
|
1243
1406
|
gap: var(--crisp-space-2);
|
|
1244
1407
|
& .crisp-emptystate-icon { width: 45px; height: 45px; margin-bottom: var(--crisp-space-2); border-radius: var(--crisp-radius-full); border: 1px solid var(--crisp-border-subtle); background: none; color: var(--crisp-fg-muted); }
|
|
1245
|
-
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; }
|
|
1408
|
+
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; letter-spacing: var(--crisp-tracking-20); }
|
|
1246
1409
|
& .crisp-emptystate-desc { max-width: 266px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
1247
1410
|
& .crisp-emptystate-action { margin-top: var(--crisp-space-2); }
|
|
1248
1411
|
}
|
|
1249
1412
|
.crisp-emptystate--variant_records {
|
|
1250
1413
|
& .crisp-emptystate-icon { width: 138px; height: 138px; margin-bottom: var(--crisp-space-2); border-radius: 0; color: color-mix(in srgb, var(--crisp-fg-primary) 22%, transparent); background: radial-gradient(circle, color-mix(in srgb, var(--crisp-fg-primary) 12%, transparent) 1.2px, transparent 1.2px) 0 0 / 16px 16px; }
|
|
1251
|
-
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; }
|
|
1414
|
+
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; letter-spacing: var(--crisp-tracking-20); }
|
|
1252
1415
|
& .crisp-emptystate-desc { max-width: 266px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
1253
1416
|
}
|
|
1254
1417
|
|
|
@@ -1279,7 +1442,9 @@
|
|
|
1279
1442
|
& .crisp-fileupload-remove:hover { color: var(--crisp-fg-primary); }
|
|
1280
1443
|
& .crisp-fileupload-remove:focus-visible { outline-color: var(--crisp-stroke-focus-ring); }
|
|
1281
1444
|
& .crisp-fileupload-errors { display: flex; flex-direction: column; gap: var(--crisp-space-0-5); margin: 0; padding: 0; list-style: none; }
|
|
1282
|
-
/* out of flow while empty, so the always-mounted live region costs no
|
|
1445
|
+
/* out of flow while empty, so the always-mounted live region costs no
|
|
1446
|
+
layout: display:none would take it out of the accessibility tree, which
|
|
1447
|
+
is the one thing it exists to be in */
|
|
1283
1448
|
& .crisp-fileupload-errors:empty { position: absolute; }
|
|
1284
1449
|
& .crisp-fileupload-error { color: var(--crisp-bg-danger); font-size: var(--crisp-text-md); line-height: 18px; }
|
|
1285
1450
|
}
|
|
@@ -1392,7 +1557,7 @@
|
|
|
1392
1557
|
}
|
|
1393
1558
|
|
|
1394
1559
|
.crisp-input {
|
|
1395
|
-
position: relative; box-sizing: border-box; display: inline-flex; align-items: center; width: 100%; background: var(--crisp-bg-surface);
|
|
1560
|
+
position: relative; box-sizing: border-box; display: inline-flex; align-items: center; width: 100%; background: var(--crisp-bg-surface); border: 1px solid var(--crisp-border-default); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px;
|
|
1396
1561
|
&::after { content: ""; position: absolute; inset: 0; border-radius: inherit; border: 2px solid transparent; transition: border-color .1s ease; pointer-events: none; }
|
|
1397
1562
|
&:focus-within::after { border-color: var(--crisp-stroke-field-focus); }
|
|
1398
1563
|
& .crisp-input-value { box-sizing: border-box; flex: 1 1 auto; min-width: 0; width: 100%; align-self: stretch; margin: 0; border: none; background: none; outline: none; font: inherit; color: var(--crisp-fg-primary); }
|
|
@@ -1403,8 +1568,10 @@
|
|
|
1403
1568
|
primary-email field -- a tinted field, not just muted text, driven off
|
|
1404
1569
|
the native `readOnly` attribute. `ringField` (rgba(0,0,0,.06)) is an
|
|
1405
1570
|
exact match for the measured ring; the 2%-fgPrimary tint reuses the
|
|
1406
|
-
same color-mix idiom every other soft crisp surface already uses.
|
|
1407
|
-
|
|
1571
|
+
same color-mix idiom every other soft crisp surface already uses.
|
|
1572
|
+
`border-color: transparent` neutralises #910's new real rest border
|
|
1573
|
+
so this measured ring isn't drawn twice. */
|
|
1574
|
+
&[data-readonly] { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); border-color: transparent; box-shadow: inset 0 0 0 1px var(--crisp-ring-field); }
|
|
1408
1575
|
& .crisp-input-suffix { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); }
|
|
1409
1576
|
}
|
|
1410
1577
|
.crisp-input--size_sm {
|
|
@@ -1416,7 +1583,7 @@
|
|
|
1416
1583
|
& .crisp-input-value { padding-inline: var(--crisp-space-2-5); }
|
|
1417
1584
|
}
|
|
1418
1585
|
.crisp-input--size_large {
|
|
1419
|
-
height: 36px; border-radius:
|
|
1586
|
+
height: 36px; border-radius: var(--crisp-radius-xl);
|
|
1420
1587
|
& .crisp-input-value { padding-inline: var(--crisp-space-3); }
|
|
1421
1588
|
}
|
|
1422
1589
|
.crisp-input--invalid_true {
|
|
@@ -1469,8 +1636,8 @@
|
|
|
1469
1636
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
1470
1637
|
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1471
1638
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
1472
|
-
border-radius: var(--crisp-radius-
|
|
1473
|
-
box-shadow:
|
|
1639
|
+
border-radius: var(--crisp-radius-3xl); background: var(--crisp-bg-popover);
|
|
1640
|
+
box-shadow: 0 4px 16px var(--crisp-shadow-select);
|
|
1474
1641
|
transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
|
|
1475
1642
|
}
|
|
1476
1643
|
.crisp-menu-content[data-align="end"] { transform-origin: top right; }
|
|
@@ -1518,6 +1685,43 @@
|
|
|
1518
1685
|
}
|
|
1519
1686
|
}
|
|
1520
1687
|
|
|
1688
|
+
.crisp-menusheet {
|
|
1689
|
+
display: contents; font-family: var(--crisp-font-sans);
|
|
1690
|
+
& .crisp-menusheet-backdrop { position: fixed; inset: 0; z-index: 60; background: var(--crisp-bg-overlay-strong); /* menu-sheet.yaml:95 backdrop.color = $color.bg.overlay */ opacity: 1; transition: opacity 100ms cubic-bezier(0,0,.15,1); /* menu-sheet.yaml:96-98 enterDuration/enterTimingFunction = $duration.d2/$timing-function.enter */ @starting-style { opacity: 0; } }
|
|
1691
|
+
& .crisp-menusheet-positioner { position: fixed; inset: 0; z-index: 61; display: flex; align-items: flex-end; justify-content: center; }
|
|
1692
|
+
& .crisp-menusheet-content { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; box-sizing: border-box; display: flex; flex-direction: column; overflow: hidden; width: 100%; max-width: 480px; /* menu-sheet.yaml:104 content.maxWidth */ max-height: 85vh; background: var(--crisp-bg-surface); /* menu-sheet.yaml:103 content.color = $color.bg.layer-floating */ padding: var(--crisp-space-6) var(--crisp-space-4) var(--crisp-space-4); /* menu-sheet.yaml:105-107 content.paddingX/paddingTop/paddingBottom = global-gutter/x6/x4 (16px/24px/16px) */ border-radius: var(--crisp-radius-3xl) var(--crisp-radius-3xl) 0 0; /* menu-sheet.yaml:108 content.topCornerRadius = $radius.r5 (20px) */ transform: translateY(0); transition: transform 300ms cubic-bezier(.03,.4,.1,1); /* menu-sheet.yaml:109-110 content.enterDuration/enterTimingFunction (enter-expressive) */ @starting-style { transform: translateY(100%); } }
|
|
1693
|
+
& .crisp-menusheet-header { display: flex; flex-direction: column; gap: var(--crisp-space-1); /* menu-sheet.yaml:115 header.gap = $dimension.x1 (4px) */ padding-bottom: var(--crisp-space-4); /* menu-sheet.yaml:116 header.paddingBottom = $dimension.x4 (16px) */ flex-shrink: 0; }
|
|
1694
|
+
& .crisp-menusheet-title { color: var(--crisp-fg-primary); /* menu-sheet.yaml:121 title.color = $color.fg.neutral */ font-size: 18px; line-height: 24px; font-weight: var(--crisp-weight-bold); /* menu-sheet.yaml:118-120 title.fontSize/lineHeight/fontWeight = $font-size.t6/$line-height.t6/bold */ }
|
|
1695
|
+
& .crisp-menusheet-description { color: var(--crisp-fg-muted); /* menu-sheet.yaml:126 description.color = $color.fg.neutral-muted */ font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-regular); /* menu-sheet.yaml:123-125 description.fontSize/lineHeight/fontWeight = $font-size.t4/$line-height.t4/regular */ }
|
|
1696
|
+
& .crisp-menusheet-list { display: flex; flex-direction: column; gap: var(--crisp-space-2-5); /* menu-sheet.yaml:129 list.gap = $dimension.x2_5 (10px) */ overflow-y: auto; min-height: 0; }
|
|
1697
|
+
& .crisp-menusheet-group { display: flex; flex-direction: column; border-radius: var(--crisp-radius-2xl); overflow: hidden; /* menu-sheet.yaml:131 group.cornerRadius = $radius.r4 (16px) */ }
|
|
1698
|
+
& .crisp-menusheet-group > * + * { border-top: 1px solid var(--crisp-stroke-group-divider); }
|
|
1699
|
+
/* menu-sheet.yaml:132-134 divider.strokeBottomWidth/strokeColor = 1px/$color.stroke.neutral-muted */
|
|
1700
|
+
& .crisp-menusheet-footer { flex-shrink: 0; padding-top: var(--crisp-space-2-5); /* menu-sheet.yaml:136 footer.paddingTop = $dimension.x2_5 (10px) */ }
|
|
1701
|
+
& .crisp-menusheet-item { position: relative; box-sizing: border-box; display: flex; align-items: center; width: 100%; min-height: 52px; /* menu-sheet-item.yaml:72 root.minHeight */ padding: var(--crisp-space-3-5) var(--crisp-space-4); gap: var(--crisp-space-3-5); /* menu-sheet-item.yaml:73-75 root.paddingX/paddingY/gap = x4/x3_5/x3_5 (16px/14px/14px) */ border: none; margin: 0; cursor: pointer; text-align: start; background: var(--crisp-bg-neutral-weak); /* menu-sheet-item.yaml:71 root.color = $color.bg.neutral-weak */ font-family: inherit; }
|
|
1702
|
+
& .crisp-menusheet-item:hover, & .crisp-menusheet-item:active { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, var(--crisp-bg-neutral-weak)); }
|
|
1703
|
+
/* menu-sheet-item.yaml:90-91 pressed.root.color = $color.bg.neutral-weak-pressed, approximated as a tint over the base fill */
|
|
1704
|
+
& .crisp-menusheet-item:active .crisp-menusheet-item-content { transform: scale(0.98); }
|
|
1705
|
+
/* menu-sheet-item.yaml:92 pressed.root.scaleScope = content */
|
|
1706
|
+
& .crisp-menusheet-item-icon { flex-shrink: 0; display: inline-flex; width: 22px; height: 22px; }
|
|
1707
|
+
/* menu-sheet-item.yaml:77 prefixIcon.size */
|
|
1708
|
+
& .crisp-menusheet-item-content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--crisp-space-0-5); /* menu-sheet-item.yaml:79 content.gap = $dimension.x0_5 (2px) */ transition: transform 150ms cubic-bezier(0,0,.15,1); }
|
|
1709
|
+
& .crisp-menusheet-item-label { font-size: var(--crisp-text-xl); line-height: 22px; font-weight: var(--crisp-weight-regular); /* menu-sheet-item.yaml:81-83 label.fontSize/lineHeight/fontWeight = $font-size.t5/$line-height.t5/regular */ }
|
|
1710
|
+
& .crisp-menusheet-item-description { color: var(--crisp-fg-neutral-subtle); /* menu-sheet-item.yaml:88 description.color = $color.fg.neutral-subtle */ font-size: var(--crisp-text-md); line-height: 18px; font-weight: var(--crisp-weight-medium); /* menu-sheet-item.yaml:85-87 description.fontSize/lineHeight/fontWeight = $font-size.t3/$line-height.t3/medium */ }
|
|
1711
|
+
& .crisp-menusheet-item[data-tone="neutral"] .crisp-menusheet-item-icon, & .crisp-menusheet-item[data-tone="neutral"] .crisp-menusheet-item-label { color: var(--crisp-fg-primary); }
|
|
1712
|
+
/* menu-sheet-item.yaml:93-98 tone=neutral */
|
|
1713
|
+
& .crisp-menusheet-item[data-tone="critical"] .crisp-menusheet-item-icon, & .crisp-menusheet-item[data-tone="critical"] .crisp-menusheet-item-label { color: var(--crisp-fg-danger); }
|
|
1714
|
+
/* menu-sheet-item.yaml:99-104 tone=critical */
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1718
|
+
.crisp-menusheet, .crisp-menusheet * {
|
|
1719
|
+
animation-duration: 0.01ms !important;
|
|
1720
|
+
animation-iteration-count: 1 !important;
|
|
1721
|
+
transition-duration: 0.01ms !important;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1521
1725
|
|
|
1522
1726
|
/* pointer-events: auto (#375) -- see Select's matching comment. */
|
|
1523
1727
|
.crisp-multiselect-listbox {
|
|
@@ -1531,13 +1735,19 @@
|
|
|
1531
1735
|
}
|
|
1532
1736
|
.crisp-multiselect-listbox[data-up] { transform-origin: bottom left; }
|
|
1533
1737
|
.crisp-multiselect-listbox { @starting-style { opacity: 0; transform: scale(0.95); } }
|
|
1534
|
-
/*
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1738
|
+
/* Seed geometry (build/spec-check.mjs guards these four properties
|
|
1739
|
+
directly), superseding #481's old Attio lock -- see this file's
|
|
1740
|
+
header comment and Select's matching .crisp-select-search comment
|
|
1741
|
+
for the full citation. An ordinary flex child of the listbox, so its
|
|
1742
|
+
own 8px gap provides the inset/seam on every side, same as Select. */
|
|
1743
|
+
.crisp-multiselect-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-selectTriggerMd); flex-shrink: 0; padding: 0 var(--crisp-space-3-5); border: 1px solid var(--crisp-stroke-select-trigger); border-radius: var(--crisp-radius-md); color: var(--crisp-fg-neutral-muted); }
|
|
1538
1744
|
.crisp-multiselect-search svg { flex-shrink: 0; }
|
|
1539
|
-
.crisp-multiselect-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-select-neutral); }
|
|
1745
|
+
.crisp-multiselect-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
|
|
1540
1746
|
.crisp-multiselect-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
|
|
1747
|
+
/* Same header/body seam as Select's own .crisp-select-divider -- see
|
|
1748
|
+
that recipe's comment for the seed source (select.yaml's divider
|
|
1749
|
+
slot, stroke.neutral-muted). */
|
|
1750
|
+
.crisp-multiselect-divider { flex-shrink: 0; height: 1px; margin-inline: var(--crisp-space-4); background: var(--crisp-stroke-select-divider); }
|
|
1541
1751
|
/* Same groupLabel treatment as Select's (13px/regular/neutral-subtle). */
|
|
1542
1752
|
.crisp-multiselect-label { padding: var(--crisp-space-2) var(--crisp-space-4) 0; font-size: var(--crisp-text-md); line-height: 18px; font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-neutral-subtle); }
|
|
1543
1753
|
.crisp-multiselect-option {
|
|
@@ -1577,7 +1787,8 @@
|
|
|
1577
1787
|
& .crisp-multiselect-trigger[aria-readonly="true"] { background: var(--crisp-bg-select-disabled); cursor: default; }
|
|
1578
1788
|
& .crisp-multiselect-chips { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); }
|
|
1579
1789
|
& .crisp-multiselect-placeholder { color: var(--crisp-fg-select-placeholder); }
|
|
1580
|
-
/* closeRotateDuration/openRotateDuration, same asymmetric timing as
|
|
1790
|
+
/* closeRotateDuration/openRotateDuration, same asymmetric timing as
|
|
1791
|
+
Select's own chevron (see that recipe's comment). */
|
|
1581
1792
|
& .crisp-multiselect-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
|
|
1582
1793
|
& .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); transition-duration: .15s; }
|
|
1583
1794
|
}
|
|
@@ -1737,13 +1948,15 @@
|
|
|
1737
1948
|
& .crisp-resizablepanel-panel[data-floating="false"] { border-radius: 0; box-shadow: none; }
|
|
1738
1949
|
& .crisp-resizablepanel-panel[data-floating="false"][data-side="left"] { border-inline-end: 1px solid var(--crisp-border-subtle); }
|
|
1739
1950
|
& .crisp-resizablepanel-panel[data-floating="false"][data-side="right"] { border-inline-start: 1px solid var(--crisp-border-subtle); }
|
|
1740
|
-
/* floating — position: fixed, 8px gutter, r10, the measured floating elevation.
|
|
1951
|
+
/* floating — position: fixed, 8px gutter, r10, the measured floating elevation.
|
|
1952
|
+
Rest is transform: none (Lesson 27); the off-canvas value is the @starting-style enter only. */
|
|
1741
1953
|
& .crisp-resizablepanel-panel[data-floating="true"] { position: fixed; top: var(--crisp-space-2); bottom: var(--crisp-space-2); border-inline-end: none; border-inline-start: none; border-radius: 10px; box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: none; transition: transform 0.14s, padding 0.14s; }
|
|
1742
1954
|
& .crisp-resizablepanel-panel[data-floating="true"][data-side="left"] { padding: var(--crisp-space-2) 0 var(--crisp-space-2) var(--crisp-space-2); @starting-style { transform: translateX(calc(-100% - var(--crisp-space-2))); } }
|
|
1743
1955
|
& .crisp-resizablepanel-panel[data-floating="true"][data-side="right"] { padding: var(--crisp-space-2) var(--crisp-space-2) var(--crisp-space-2) 0; @starting-style { transform: translateX(calc(100% + var(--crisp-space-2))); } }
|
|
1744
1956
|
& .crisp-resizablepanel-inner { height: 100%; opacity: 1; }
|
|
1745
1957
|
& .crisp-resizablepanel-panel[data-floating="true"] .crisp-resizablepanel-inner { opacity: 1; transition: opacity 0.14s; @starting-style { opacity: 0; } }
|
|
1746
|
-
/* handle — variant "panel" (default): a 10px hit target, its ::before the
|
|
1958
|
+
/* handle — variant "panel" (default): a 10px hit target, its ::before the
|
|
1959
|
+
only visible divider (1px rest -> 2px on hover/drag, brand-solid). */
|
|
1747
1960
|
& .crisp-resizablepanel-handle { position: absolute; top: 0; width: 10px; height: 100%; z-index: 2; cursor: col-resize; background: transparent; touch-action: none; }
|
|
1748
1961
|
& .crisp-resizablepanel-handle[data-side="left"] { right: 0; }
|
|
1749
1962
|
& .crisp-resizablepanel-handle[data-side="right"] { left: 0; }
|
|
@@ -1751,9 +1964,10 @@
|
|
|
1751
1964
|
& .crisp-resizablepanel-handle[data-side="left"]::before { right: 0; }
|
|
1752
1965
|
& .crisp-resizablepanel-handle[data-side="right"]::before { left: 0; }
|
|
1753
1966
|
& .crisp-resizablepanel-handle:hover::before, & .crisp-resizablepanel-handle[data-dragging="true"]::before { width: 2px; background: var(--crisp-bg-brand-solid); }
|
|
1754
|
-
/* handle — variant "column": a wider 7px hit target straddling a 1px
|
|
1755
|
-
|
|
1756
|
-
|
|
1967
|
+
/* handle — variant "column": a wider 7px hit target straddling a 1px
|
|
1968
|
+
divider (table column edges), with a real 3px inner bar whose opacity
|
|
1969
|
+
comes in on a 100ms DELAY — distinct from the panel variant's instant
|
|
1970
|
+
::before swap. */ /* .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column (both classes) to
|
|
1757
1971
|
out-specificity the base [data-side] left/right rules above, which
|
|
1758
1972
|
otherwise tie-break by source order alone and would win. */
|
|
1759
1973
|
& .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column { display: flex; align-items: center; justify-content: center; width: 7px; left: -3px; right: -3px; z-index: 1; cursor: col-resize; }
|
|
@@ -1818,6 +2032,20 @@
|
|
|
1818
2032
|
.crisp-select-search svg { flex-shrink: 0; }
|
|
1819
2033
|
.crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
|
|
1820
2034
|
.crisp-select-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
|
|
2035
|
+
/* select.yaml's own divider slot (marginX x4, height 1px, colour
|
|
2036
|
+
stroke.neutral-muted -- described upstream as "the line marking a
|
|
2037
|
+
boundary between semantic units: between sections, between content
|
|
2038
|
+
and an action area, between a header and a body" -- exactly the
|
|
2039
|
+
search-field/option-list boundary crisp#904's review flagged as
|
|
2040
|
+
reading too tight). Not the general-purpose separator #867 declined
|
|
2041
|
+
to build (nothing groups options with one) -- scoped to this one
|
|
2042
|
+
specific header/body seam, which now exists because searchable
|
|
2043
|
+
does. Sits as an ordinary flex child, so the listbox's own 8px gap
|
|
2044
|
+
still applies on both sides of it -- total visual seam is
|
|
2045
|
+
gap+1px+gap (17px), deliberately more than the 8px between two
|
|
2046
|
+
plain option rows, so it reads as a section break, not a wider list
|
|
2047
|
+
gap. */
|
|
2048
|
+
.crisp-select-divider { flex-shrink: 0; height: 1px; margin-inline: var(--crisp-space-4); background: var(--crisp-stroke-select-divider); }
|
|
1821
2049
|
.crisp-select-empty { padding: var(--crisp-space-3) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-neutral-subtle); }
|
|
1822
2050
|
/* select.yaml's groupLabel -- font-size/line-height/weight are the same
|
|
1823
2051
|
across sizes, only paddingY differs (medium 8px, large 10px). */
|
|
@@ -1847,21 +2075,27 @@
|
|
|
1847
2075
|
.crisp-select {
|
|
1848
2076
|
position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
1849
2077
|
& .crisp-select-trigger { box-sizing: border-box; display: inline-flex; align-items: center; width: 100%; min-width: 0; margin: 0; border: 1px solid var(--crisp-stroke-select-trigger); background: transparent; cursor: pointer; font-family: inherit; color: var(--crisp-fg-select-neutral); transition: background-color .15s cubic-bezier(.35,0,.35,1), border-color .1s cubic-bezier(.35,0,.35,1), border-width .1s cubic-bezier(.35,0,.35,1); }
|
|
1850
|
-
/* seed defines no hover state for this trigger -- only pressed, invalid,
|
|
1851
|
-
|
|
1852
|
-
|
|
2078
|
+
/* seed defines no hover state for this trigger -- only pressed, invalid,
|
|
2079
|
+
disabled and readonly. The scale-down is scoped to the CONTENT
|
|
2080
|
+
(seed's scaleScope: content), not the button itself, so the border
|
|
2081
|
+
never moves. */ /* Only the value scales, not the chevron: the chevron's own transform is
|
|
2082
|
+
its open/close rotation, and a scale would fight it for one shared
|
|
2083
|
+
CSS property when both are true at once (pressing while open). */
|
|
1853
2084
|
& .crisp-select-trigger:active:not(:disabled):not([aria-readonly="true"]) { background: var(--crisp-bg-select-pressed); }
|
|
1854
2085
|
& .crisp-select-trigger:active:not(:disabled):not([aria-readonly="true"]) .crisp-select-value { transform: scale(0.98); }
|
|
1855
2086
|
& .crisp-select-trigger:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; }
|
|
1856
2087
|
& .crisp-select-trigger:disabled { background: var(--crisp-bg-select-disabled); cursor: not-allowed; }
|
|
1857
2088
|
& .crisp-select-trigger:disabled .crisp-select-value, & .crisp-select-trigger:disabled .crisp-select-placeholder, & .crisp-select-trigger:disabled .crisp-select-chevron { color: var(--crisp-fg-disabled); }
|
|
1858
|
-
/* readonly: same fill as disabled, but the value/placeholder text stays
|
|
2089
|
+
/* readonly: same fill as disabled, but the value/placeholder text stays
|
|
2090
|
+
normal ink -- it reads as "answered and locked", not "answered and
|
|
1859
2091
|
greyed out" (select-trigger.yaml's readonly state only overrides
|
|
1860
2092
|
root.color; value/placeholder keep their enabled colours). */
|
|
1861
2093
|
& .crisp-select-trigger[aria-readonly="true"] { background: var(--crisp-bg-select-disabled); cursor: default; }
|
|
1862
2094
|
& .crisp-select-value { flex: 1; min-width: 0; display: inline-flex; align-items: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: start; transition: transform .15s cubic-bezier(0,0,.15,1); }
|
|
1863
2095
|
& .crisp-select-placeholder { color: var(--crisp-fg-select-placeholder); }
|
|
1864
|
-
/* closeRotateDuration/closeRotateTimingFunction: 100ms, seed's "easing"
|
|
2096
|
+
/* closeRotateDuration/closeRotateTimingFunction: 100ms, seed's "easing"
|
|
2097
|
+
curve. Overridden to 150ms on open (openRotateDuration) below --
|
|
2098
|
+
same curve both ways, only the duration differs. */
|
|
1865
2099
|
& .crisp-select-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
|
|
1866
2100
|
& .crisp-select-trigger[data-open] .crisp-select-chevron { transform: rotate(180deg); transition-duration: .15s; }
|
|
1867
2101
|
}
|
|
@@ -1944,42 +2178,21 @@
|
|
|
1944
2178
|
}
|
|
1945
2179
|
|
|
1946
2180
|
.crisp-slider {
|
|
1947
|
-
display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
|
|
1951
|
-
}
|
|
2181
|
+
display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a
|
|
2182
|
+
thumb's name — read, never drawn */
|
|
2183
|
+
& .crisp-slider-thumblabel { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
1952
2184
|
& .crisp-slider-control { position: relative; height: 26px; display: flex; align-items: center; }
|
|
1953
|
-
|
|
1954
|
-
& .crisp-slider-track {
|
|
1955
|
-
position: relative; flex-grow: 1; height: var(--crisp-space-1);
|
|
1956
|
-
border-radius: var(--crisp-radius-full); background: var(--crisp-bg-neutral-weak);
|
|
1957
|
-
overflow: hidden;
|
|
1958
|
-
}
|
|
1959
|
-
|
|
2185
|
+
& .crisp-slider-track { position: relative; flex-grow: 1; height: var(--crisp-space-1); border-radius: var(--crisp-radius-full); background: var(--crisp-bg-neutral-weak); overflow: hidden; }
|
|
1960
2186
|
& .crisp-slider-range { position: absolute; height: 100%; background: var(--crisp-bg-brand-solid); }
|
|
1961
2187
|
& .crisp-slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
|
|
1962
2188
|
& .crisp-slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
|
|
1963
|
-
|
|
1964
|
-
& .crisp-slider-thumb {
|
|
1965
|
-
position: absolute; top: 50%;
|
|
1966
|
-
width: var(--crisp-space-5); height: var(--crisp-space-5);
|
|
1967
|
-
transform: translate(-50%, -50%);
|
|
1968
|
-
border: none; background: none; padding: 0;
|
|
1969
|
-
}
|
|
2189
|
+
& .crisp-slider-thumb { position: absolute; top: 50%; width: var(--crisp-space-5); height: var(--crisp-space-5); transform: translate(-50%, -50%); border: none; background: none; padding: 0; }
|
|
1970
2190
|
& .crisp-slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
1971
2191
|
& .crisp-slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
1972
|
-
& .crisp-slider-thumb::after {
|
|
1973
|
-
content: ""; position: absolute; inset: 0;
|
|
1974
|
-
border-radius: var(--crisp-radius-full); background: #fff; 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);
|
|
1975
|
-
outline: 2px solid transparent; outline-offset: 2px;
|
|
1976
|
-
transition: transform .2s ease, outline-color .2s ease;
|
|
1977
|
-
cursor: grab;
|
|
1978
|
-
}
|
|
2192
|
+
& .crisp-slider-thumb::after { content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-full); background: #fff; 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); outline: 2px solid transparent; outline-offset: 2px; transition: transform .2s ease, outline-color .2s ease; cursor: grab; }
|
|
1979
2193
|
& .crisp-slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
|
|
1980
2194
|
& .crisp-slider-thumb:focus { outline: none; }
|
|
1981
2195
|
& .crisp-slider-thumb:focus-visible::after { outline-color: var(--crisp-stroke-focus-ring); }
|
|
1982
|
-
|
|
1983
2196
|
&[data-disabled] { cursor: not-allowed; }
|
|
1984
2197
|
&[data-disabled] .crisp-slider-range { background: var(--crisp-fg-disabled); }
|
|
1985
2198
|
&[data-disabled] .crisp-slider-thumb::after { cursor: not-allowed; }
|
|
@@ -1993,6 +2206,31 @@
|
|
|
1993
2206
|
}
|
|
1994
2207
|
}
|
|
1995
2208
|
|
|
2209
|
+
.crisp-snackbar {
|
|
2210
|
+
& .crisp-snackbar-region { position: fixed; z-index: 80; inset-inline: 0; bottom: 0; display: flex; justify-content: center; padding: var(--crisp-space-2); /* snackbar.yaml:95-96 region.paddingX/paddingY = $dimension.x2 (8px) */ pointer-events: none; }
|
|
2211
|
+
& .crisp-snackbar { pointer-events: auto; box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2-5); /* snackbar.yaml:116 content.gap = $dimension.x2_5 (10px), reused as the icon+message-to-action gap */ min-height: 44px; max-width: 464px; /* snackbar.yaml:102-103 */ width: max-content; padding: var(--crisp-space-2-5); /* snackbar.yaml:104-105 root.paddingX/paddingY = $dimension.x2_5 (10px) */ border-radius: var(--crisp-radius-md); /* snackbar.yaml:101 root.cornerRadius = $radius.r2 (8px) */ background: var(--crisp-bg-neutral-inverted); /* snackbar.yaml:100 root.color = $color.bg.neutral-inverted */ font-family: var(--crisp-font-sans); opacity: 1; transform: scale(1); transition: opacity 150ms cubic-bezier(0,0,.15,1), transform 150ms cubic-bezier(0,0,.15,1); /* snackbar.yaml:108-109 enterDuration/enterTimingFunction = $duration.d3 (150ms) / $timing-function.enter */ @starting-style { opacity: 0; transform: scale(0.8); } /* snackbar.yaml:106-107 enterOpacity/enterScale */ }
|
|
2212
|
+
& .crisp-snackbar-content { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
|
|
2213
|
+
/* snackbar.yaml:124 prefixIcon.paddingRight = $dimension.x0_5 (2px), used as the icon-to-message gap */
|
|
2214
|
+
& .crisp-snackbar-icon { flex-shrink: 0; display: inline-flex; }
|
|
2215
|
+
& .crisp-snackbar[data-variant="positive"] .crisp-snackbar-icon { color: var(--crisp-bg-success); }
|
|
2216
|
+
/* snackbar.yaml:138-139 variant=positive prefixIcon.color = $color.fg.positive */
|
|
2217
|
+
& .crisp-snackbar[data-variant="critical"] .crisp-snackbar-icon { color: var(--crisp-bg-danger); }
|
|
2218
|
+
/* snackbar.yaml:142-143 variant=critical prefixIcon.color = $color.fg.critical */
|
|
2219
|
+
& .crisp-snackbar-message { flex: 1 1 auto; min-width: 0; color: var(--crisp-fg-on-neutral-inverted); font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-regular); }
|
|
2220
|
+
/* snackbar.yaml:117-121: message.color = $color.fg.neutral-inverted, fontSize/lineHeight = $font-size.t4/$line-height.t4 (14px/19px), fontWeight = regular */
|
|
2221
|
+
& .crisp-snackbar-action { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 var(--crisp-space-2); margin: -12px calc(-1 * var(--crisp-space-2)); /* snackbar.yaml:126-127 targetPaddingX/targetMinHeight = $dimension.x2 (8px, doubled here as horizontal padding)/44px -- a larger invisible tap target than the pill's own 44px content row, via negative margin so it doesn't grow the pill visually */ border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-on-neutral-inverted); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-bold); /* fontSize/lineHeight = t4/line-height.t4; fontWeight = bold (snackbar.yaml:129-131); colour deviation documented above */ cursor: pointer; transition: transform 150ms cubic-bezier(0,0,.15,1); }
|
|
2222
|
+
& .crisp-snackbar-action:active { transform: scale(0.98); }
|
|
2223
|
+
/* snackbar.yaml:133-134 pressed.actionButton.scaleScope = self */
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2227
|
+
.crisp-snackbar, .crisp-snackbar * {
|
|
2228
|
+
animation-duration: 0.01ms !important;
|
|
2229
|
+
animation-iteration-count: 1 !important;
|
|
2230
|
+
transition-duration: 0.01ms !important;
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
|
|
1996
2234
|
@keyframes crisp-spin { to { transform: rotate(360deg); } }
|
|
1997
2235
|
.crisp-spinner {
|
|
1998
2236
|
display: inline-block; box-sizing: border-box; width: 16px; height: 16px; border-radius: var(--crisp-radius-full); border: 2px solid color-mix(in srgb, var(--crisp-fg-primary) 15%, transparent); border-top-color: var(--crisp-fg-muted); animation: crisp-spin 0.6s linear infinite;
|
|
@@ -2028,7 +2266,9 @@
|
|
|
2028
2266
|
/* caption's own status colour, opt-in via data-tone: not a new measured
|
|
2029
2267
|
value — the same fg*Soft tokens Badge's tone already uses (and Badge's
|
|
2030
2268
|
own doc comment records why: a dedicated soft-text token, not the
|
|
2031
|
-
tone's accent colour, is the one that clears AA). No "ok" reading on
|
|
2269
|
+
tone's accent colour, is the one that clears AA). No "ok" reading on
|
|
2270
|
+
Badge itself; fgSuccessSoft is Badge's own "success" tone's text
|
|
2271
|
+
colour, reused here under the name a caption's own good-news state
|
|
2032
2272
|
reads as. */
|
|
2033
2273
|
& .crisp-statcard-caption[data-tone="ok"] { color: var(--crisp-fg-success-soft); }
|
|
2034
2274
|
& .crisp-statcard-caption[data-tone="warning"] { color: var(--crisp-fg-warning-soft); }
|
|
@@ -2068,40 +2308,63 @@
|
|
|
2068
2308
|
}
|
|
2069
2309
|
|
|
2070
2310
|
.crisp-table {
|
|
2071
|
-
display: block; box-sizing: border-box; background: var(--crisp-bg-surface); /* #554: both axes -- a consumer bounds the height via `scrollProps`
|
|
2311
|
+
display: block; box-sizing: border-box; background: var(--crisp-bg-surface); /* #554: both axes -- a consumer bounds the height via `scrollProps`
|
|
2312
|
+
(style/className on this element), and the header/footer below pin
|
|
2313
|
+
inside it exactly the way Attio's own grid does ("Both the header and
|
|
2072
2314
|
the summary row are sticky, on the scroll container rather than the
|
|
2073
2315
|
cells" -- docs/study/attio-table.md). Unbounded, `overflow: auto`
|
|
2074
2316
|
shows no vertical scrollbar and nothing sticks, so this is a no-op
|
|
2075
2317
|
for every existing consumer that never set a height. */
|
|
2076
2318
|
& .crisp-table-scroll { overflow: auto; }
|
|
2077
2319
|
& table { width: 100%; border-collapse: separate; border-spacing: 0; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
|
|
2078
|
-
/* #465: 12px, not crisp's old 8px -- measured on a live header cell
|
|
2320
|
+
/* #465: 12px, not crisp's old 8px -- measured on a live header cell
|
|
2321
|
+
(padding: 0 12px) and independently on a body cell's text inset
|
|
2079
2322
|
(getBoundingClientRect delta from the cell edge). Matches
|
|
2080
|
-
ColumnCalc's own already-correct 12px trigger inset. */
|
|
2081
|
-
|
|
2323
|
+
ColumnCalc's own already-correct 12px trigger inset. */ /* #719: overflow: clip, not hidden -- both render the ellipsis
|
|
2324
|
+
identically, but hidden still honours a programmatic scrollLeft
|
|
2325
|
+
assignment (a screenshot tool, a browser extension) even though it
|
|
2326
|
+
already blocks user-driven wheel/scrollbar input; clip leaves no
|
|
2327
|
+
scroll position for anything to move, so the truncated text can
|
|
2328
|
+
never be panned out of view. */
|
|
2329
|
+
& th, & td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; vertical-align: middle; white-space: nowrap; overflow: clip; text-overflow: ellipsis; }
|
|
2082
2330
|
/* #554: sticky on the vertical axis, mirroring RecordsTable's own
|
|
2083
2331
|
`.crisp-recordstable-th`. z-index 2 sits above a plain body cell (auto)
|
|
2084
|
-
and below a sticky-column corner cell (DataTable's `th[data-sticky]`,
|
|
2332
|
+
and below a sticky-column corner cell (DataTable's `th[data-sticky]`,
|
|
2333
|
+
z-index 3), so the corner always wins.
|
|
2334
|
+
`thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
|
|
2085
2335
|
column renders its BODY cell as a real `<th scope="row">` (#779, for
|
|
2086
2336
|
a11y), and a bare `th` here matched that one too -- every property in
|
|
2087
2337
|
this rule leaked onto it: `height: tableHeader` (40px) stretched the
|
|
2088
2338
|
whole body row to 40px instead of 36 (#833, confirmed live on the
|
|
2089
2339
|
showcase, every td in the row equalized to the one th); `color:
|
|
2090
|
-
color-mix(...63%...)` muted the primary column's own text below every
|
|
2091
|
-
|
|
2092
|
-
|
|
2340
|
+
color-mix(...63%...)` muted the primary column's own text below every
|
|
2341
|
+
sibling `<td>`'s full-opacity color (#835, re-measured live against
|
|
2342
|
+
Attio's own header labels -- including a genuinely computed one,
|
|
2343
|
+
"Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no
|
|
2344
|
+
muting at all, so this drops the color-mix entirely rather than
|
|
2345
|
+
narrowing it); `position:sticky; top:0` tried to stick a BODY row
|
|
2346
|
+
to the scroll container's top; the extra `border-top` doubled that
|
|
2347
|
+
row's own grid line. `thead th` simply never matches
|
|
2348
|
+
`tbody th[scope=row]` at all, so none of this reaches it; the base
|
|
2349
|
+
`& th, & td` rule above (36px, one border-bottom, full opacity via
|
|
2350
|
+
`& table`'s own color) applies to it like every other cell. */
|
|
2093
2351
|
& thead th { position: sticky; top: 0; z-index: 2; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-primary); user-select: none; }
|
|
2094
2352
|
& td { color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); }
|
|
2095
|
-
/* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the
|
|
2096
|
-
|
|
2353
|
+
/* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the
|
|
2354
|
+
header rule above to `thead th` correctly stopped it leaking onto
|
|
2355
|
+
the primary column's body cell (a real `<th scope="row">` since
|
|
2356
|
+
#779), but that same leaked rule's `font-weight: var(--crisp-weight-medium)`
|
|
2357
|
+
was the ONLY thing overriding the browser's own UA stylesheet default
|
|
2097
2358
|
for `<th>` (`font-weight: bold; text-align: center`) on that cell --
|
|
2098
2359
|
once the leak stopped, a plain-text primary column fell through to
|
|
2099
2360
|
bold+centred instead of matching its sibling `<td>`s (`400`/start,
|
|
2100
|
-
Attio's own plain-text primary cell). `text-align` was already safe
|
|
2361
|
+
Attio's own plain-text primary cell). `text-align` was already safe
|
|
2362
|
+
(the base `& th, & td` rule's own `text-align: start` above is
|
|
2101
2363
|
author-origin and always beats the UA stylesheet regardless of
|
|
2102
2364
|
specificity) but is restated here explicitly, defensively -- cheap,
|
|
2103
2365
|
and removes any doubt. `type: "entity"` primary columns are a
|
|
2104
|
-
separate case (Attio's own entity/record names are 500, not 400) --
|
|
2366
|
+
separate case (Attio's own entity/record names are 500, not 400) --
|
|
2367
|
+
see `.crisp-datatable-entity-name`'s own new explicit weight in
|
|
2105
2368
|
datatable.recipe.ts, which wins here by class specificity. */
|
|
2106
2369
|
& tbody th { font-weight: var(--crisp-weight-regular); text-align: start; }
|
|
2107
2370
|
& th:last-child, & td:last-child { border-inline-end: none; }
|
|
@@ -2145,12 +2408,18 @@
|
|
|
2145
2408
|
& .crisp-tabletoolbar-search svg { flex-shrink: 0; }
|
|
2146
2409
|
& .crisp-tabletoolbar-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
|
|
2147
2410
|
& .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
2148
|
-
/* crisp/#830: every trigger label here (Sort, Filter, View settings,
|
|
2149
|
-
|
|
2411
|
+
/* crisp/#830: every trigger label here (Sort, Filter, View settings,
|
|
2412
|
+
Import/Export -- all compose this one shared .tool rule) read the
|
|
2413
|
+
"md" text size, 13px. Re-measured on Attio's own trigger LEAF node
|
|
2414
|
+
(the button root itself inherits Attio's own 10px rem base and is a
|
|
2415
|
+
red herring, the same trap the original "10px font" layout-audit
|
|
2416
|
+
finding fell into): every label leaf is 14px/500/lh20, the "lg" text
|
|
2417
|
+
size. */
|
|
2150
2418
|
& .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
|
|
2151
2419
|
& .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
|
|
2152
2420
|
& .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
2153
|
-
/* crisp/#772: re-measured live on Sort with an actual sort applied --
|
|
2421
|
+
/* crisp/#772: re-measured live on Sort with an actual sort applied --
|
|
2422
|
+
an active trigger's own fill is white (bgSurface), the same as the
|
|
2154
2423
|
base .tool rule above now already sets; this override existed to
|
|
2155
2424
|
distinguish active from a base state that used to be transparent.
|
|
2156
2425
|
Kept explicit (not just deleted) so a future change to the base
|
|
@@ -2161,13 +2430,23 @@
|
|
|
2161
2430
|
/* crisp/#772 follow-up, re-measured live 2026-09-25: an EMPTY Sort/Filter
|
|
2162
2431
|
trigger (no sort/condition set) isn't a solid-ring chip at all -- it's
|
|
2163
2432
|
a dashed ::before (1px dashed, border-radius: inherit, absolutely
|
|
2164
|
-
positioned inset: 0) over a barely-there fill, confirmed on Attio's
|
|
2433
|
+
positioned inset: 0) over a barely-there fill, confirmed on Attio's
|
|
2434
|
+
own empty Filter chip (its ::before border computes to exactly
|
|
2435
|
+
"1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger
|
|
2436
|
+
drops the dashed pseudo and picks up the base tool's own solid ring
|
|
2165
2437
|
instead (the --active modifier, unchanged) -- confirmed on Sort with
|
|
2166
2438
|
an actual sort applied. color-mix (not the raw rgba Attio computes
|
|
2167
2439
|
to) so both the border and the fill flip correctly in dark mode, the
|
|
2168
2440
|
same reasoning --ghost above already uses. Only wired into
|
|
2169
|
-
TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's
|
|
2170
|
-
|
|
2441
|
+
TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's
|
|
2442
|
+
own Sort/Filter triggers share this same chrome function but are
|
|
2443
|
+
deprecated, not touched here.
|
|
2444
|
+
crisp/#844, correcting #831: the label colour was added here later,
|
|
2445
|
+
muting only the FILTER trigger (via a "--filter" modifier), on the
|
|
2446
|
+
assumption that was a Filter-specific tone distinct from Sort's.
|
|
2447
|
+
Re-measured live and that premise was wrong -- Sort's own resting
|
|
2448
|
+
label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5)
|
|
2449
|
+
as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
|
|
2171
2450
|
"Sort's colour" in an earlier pass is a different thing entirely: the
|
|
2172
2451
|
"Sorted by" PREFIX word inside an ACTIVE sort chip, #788 -- a
|
|
2173
2452
|
compound-label treatment that only exists once a sort is applied, not
|
|
@@ -2254,17 +2533,21 @@
|
|
|
2254
2533
|
& .crisp-tabletoolbar-fchip-x:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
|
|
2255
2534
|
& .crisp-tabletoolbar-spacer { flex: 1; }
|
|
2256
2535
|
& .crisp-tabletoolbar-count { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2536
|
+
/* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
|
|
2537
|
+
the accent (#0298d9) only clears 3.23:1 with white; the darker sibling
|
|
2538
|
+
clears 4.5:1+, same fix already applied to Button/Badge/Avatar (#897).
|
|
2539
|
+
Hover is a brightness filter on the new fill, not bgBrandSolidPressed
|
|
2540
|
+
(that token stays tuned for the lighter accent's own consumers). */
|
|
2541
|
+
& .crisp-tabletoolbar-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; transition: filter .12s; }
|
|
2542
|
+
& .crisp-tabletoolbar-new:hover { filter: brightness(0.96); }
|
|
2260
2543
|
& .crisp-tabletoolbar-fcond { display: inline-flex; align-items: center; height: var(--crisp-size-row); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); white-space: nowrap; }
|
|
2261
2544
|
& .crisp-tabletoolbar-fcond-seg { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: var(--crisp-bg-surface-muted); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); font-family: inherit; font-size: inherit; color: inherit; cursor: pointer; }
|
|
2262
2545
|
& .crisp-tabletoolbar-fcond-seg svg { flex-shrink: 0; }
|
|
2263
|
-
& .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--field,
|
|
2264
|
-
& .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
|
|
2546
|
+
& .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--field, & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
|
|
2265
2547
|
& .crisp-tabletoolbar-fcond-seg--field { border-radius: var(--crisp-radius-md) 0 0 var(--crisp-radius-md); font-weight: var(--crisp-weight-medium); max-width: 200px; }
|
|
2266
2548
|
& .crisp-tabletoolbar-fcond-seg--field svg { color: var(--crisp-fg-muted); }
|
|
2267
|
-
/* #592: a nested pick's field segment ("Team › Twitter follower
|
|
2549
|
+
/* #592: a nested pick's field segment ("Team › Twitter follower
|
|
2550
|
+
count") — measured live: BOTH path segments the same colour (chip
|
|
2268
2551
|
context only; the picker's own menu rows keep the parent muted, see
|
|
2269
2552
|
tabletoolbar.chrome.ts), each independently truncated. Attio's own
|
|
2270
2553
|
layout gives the leaf segment priority (it stays fully readable
|
|
@@ -2290,8 +2573,7 @@
|
|
|
2290
2573
|
& .crisp-tabletoolbar-sort-field-picker { position: relative; display: inline-flex; flex: 1; min-width: 0; }
|
|
2291
2574
|
& .crisp-tabletoolbar-sort-field-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-menuRow); width: 100%; min-width: 0; margin: 0; padding: 0 var(--crisp-space-1-5) 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s ease, box-shadow .12s ease; }
|
|
2292
2575
|
& .crisp-tabletoolbar-sort-field-trigger:hover { background: var(--crisp-bg-raised); }
|
|
2293
|
-
& .crisp-tabletoolbar-sort-field-trigger[aria-expanded="true"],
|
|
2294
|
-
& .crisp-tabletoolbar-sort-field-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); background: var(--crisp-bg-surface); }
|
|
2576
|
+
& .crisp-tabletoolbar-sort-field-trigger[aria-expanded="true"], & .crisp-tabletoolbar-sort-field-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); background: var(--crisp-bg-surface); }
|
|
2295
2577
|
& .crisp-tabletoolbar-sort-field-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: start; }
|
|
2296
2578
|
& .crisp-tabletoolbar-sort-field-picker .crisp-tabletoolbar-menu { min-width: 200px; }
|
|
2297
2579
|
& .crisp-tabletoolbar-menu--val { min-width: 134px; }
|
|
@@ -2299,18 +2581,10 @@
|
|
|
2299
2581
|
& .crisp-tabletoolbar-datepop-presets { display: flex; flex-wrap: wrap; gap: var(--crisp-space-1); margin-top: var(--crisp-space-2); padding: 0 var(--crisp-space-1); }
|
|
2300
2582
|
& .crisp-tabletoolbar-datepop-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
|
|
2301
2583
|
& .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
|
|
2302
|
-
|
|
2303
2584
|
& .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
|
|
2304
|
-
|
|
2305
2585
|
& .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
2306
|
-
& .crisp-tabletoolbar-sorted-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
|
|
2307
|
-
|
|
2308
|
-
box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
|
|
2309
|
-
|
|
2310
|
-
& .crisp-tabletoolbar-tool-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
|
|
2311
|
-
padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent);
|
|
2312
|
-
box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft);
|
|
2313
|
-
font-variant-numeric: tabular-nums; }
|
|
2586
|
+
& .crisp-tabletoolbar-sorted-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
|
|
2587
|
+
& .crisp-tabletoolbar-tool-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); font-variant-numeric: tabular-nums; }
|
|
2314
2588
|
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
2315
2589
|
}
|
|
2316
2590
|
|
|
@@ -2326,17 +2600,31 @@
|
|
|
2326
2600
|
display: flex; flex-direction: column; min-height: 0; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
2327
2601
|
& .crisp-tabs-list { position: relative; display: flex; align-items: center; gap: var(--crisp-space-1); box-sizing: content-box; height: var(--crisp-size-row); padding: 0 var(--crisp-space-3) var(--crisp-space-2); flex-shrink: 0; }
|
|
2328
2602
|
& .crisp-tabs-list::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--crisp-border-subtle); }
|
|
2603
|
+
/* crisp#908: an alternative to the "+N more" collapse above (crisp#863) --
|
|
2604
|
+
a consumer opts into a single scrolling row instead (Naver/Kakao's own
|
|
2605
|
+
pattern, docs/study/korean/), never both at once. No new visual value:
|
|
2606
|
+
reuses the same list gap/tab geometry, only adds overflow-x + snap. */
|
|
2607
|
+
& .crisp-tabs-list[data-overflow="scroll"] { overflow-x: auto; flex-wrap: nowrap; scroll-snap-type: x mandatory; scrollbar-width: none; }
|
|
2608
|
+
& .crisp-tabs-list[data-overflow="scroll"]::-webkit-scrollbar { display: none; }
|
|
2609
|
+
& .crisp-tabs-list[data-overflow="scroll"] .crisp-tabs-tab { flex-shrink: 0; scroll-snap-align: start; }
|
|
2329
2610
|
& .crisp-tabs-leading { display: inline-flex; align-items: center; margin-inline-end: var(--crisp-space-1); }
|
|
2330
|
-
& .crisp-tabs-tab { position: relative; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none;
|
|
2611
|
+
& .crisp-tabs-tab { position: relative; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-muted); cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease; }
|
|
2331
2612
|
& .crisp-tabs-tab svg { flex-shrink: 0; opacity: 0.85; }
|
|
2332
2613
|
& .crisp-tabs-tab:hover:not([data-selected]) { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
2333
|
-
& .crisp-tabs-tab[data-selected] { color: var(--crisp-fg-primary);
|
|
2614
|
+
& .crisp-tabs-tab[data-selected] { color: var(--crisp-fg-primary); }
|
|
2334
2615
|
& .crisp-tabs-tab:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
|
|
2335
2616
|
& .crisp-tabs-tab-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 14px; height: 14px; padding: 0 var(--crisp-space-1); border-radius: 4px; background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: 10px; line-height: 14px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
|
|
2336
2617
|
& .crisp-tabs-tab[data-selected] .crisp-tabs-tab-badge { color: var(--crisp-fg-primary); }
|
|
2337
2618
|
& .crisp-tabs-indicator { position: absolute; bottom: 0; left: 0; z-index: 1; height: 1px; background: var(--crisp-fg-primary); border-radius: 2px 2px 0 0; transition: transform .2s cubic-bezier(.4,0,.2,1), width .2s cubic-bezier(.4,0,.2,1); pointer-events: none; }
|
|
2338
|
-
/* crisp#863: the "+N more" overflow trigger, measured live -- its
|
|
2339
|
-
|
|
2619
|
+
/* crisp#863: the "+N more" overflow trigger, measured live -- its
|
|
2620
|
+
computed style is identical to a plain .crisp-tabs-tab (same pill,
|
|
2621
|
+
same 6px icon/label gap the tab class already gives via
|
|
2622
|
+
space["1.5"]), and the dropdown it opens is crisp's own Menu/
|
|
2623
|
+
MenuItem chrome (already matches Attio's popover, nothing new to
|
|
2624
|
+
style there). Only the wrapper needs a rule: an overflowed tab (or
|
|
2625
|
+
the trigger itself, when nothing is hidden) is taken out of the
|
|
2626
|
+
flex row and out of the a11y tree without ever making its own
|
|
2627
|
+
offsetWidth unmeasurable the way display:none would -- that's what
|
|
2340
2628
|
lets the tabs.tsx effect recompute the cutoff from cached widths on
|
|
2341
2629
|
every resize with no flash of an unclipped row. */
|
|
2342
2630
|
& .crisp-tabs-more { display: inline-flex; }
|
|
@@ -2377,18 +2665,14 @@
|
|
|
2377
2665
|
|
|
2378
2666
|
.crisp-textarea {
|
|
2379
2667
|
position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
|
|
2380
|
-
& .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border
|
|
2668
|
+
& .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); border: 1px solid var(--crisp-border-default); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
|
|
2381
2669
|
& .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
|
|
2382
2670
|
& .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2383
2671
|
/* seed-design's focus treatment, same as Input: a 2px ring on an ::after
|
|
2384
2672
|
overlay that is present-but-transparent at rest, so focusing never
|
|
2385
2673
|
shifts the box, animating only its colour. */
|
|
2386
2674
|
& .crisp-textarea-wrap { position: relative; display: block; }
|
|
2387
|
-
& .crisp-textarea-wrap::after {
|
|
2388
|
-
content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-md);
|
|
2389
|
-
border: 2px solid transparent; transition: border-color .1s ease;
|
|
2390
|
-
pointer-events: none;
|
|
2391
|
-
}
|
|
2675
|
+
& .crisp-textarea-wrap::after { content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-md); border: 2px solid transparent; transition: border-color .1s ease; pointer-events: none; }
|
|
2392
2676
|
& .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-stroke-field-focus); }
|
|
2393
2677
|
&[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
|
|
2394
2678
|
&[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
|
|
@@ -2480,14 +2764,16 @@
|
|
|
2480
2764
|
.crisp-wheelpicker {
|
|
2481
2765
|
position: relative; box-sizing: border-box; width: 100%; overflow: hidden; background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); /* the band the selected row sits in; behind the items, never hit-tested */
|
|
2482
2766
|
& .crisp-wheelpicker-indicator { position: absolute; z-index: 0; inset-inline: var(--crisp-space-4); top: 50%; transform: translateY(-50%); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-neutral-weak); pointer-events: none; }
|
|
2483
|
-
/* fades the rows furthest from the centre, so the column reads as a wheel
|
|
2767
|
+
/* fades the rows furthest from the centre, so the column reads as a wheel
|
|
2768
|
+
rather than a list. 40% of the viewport, capped, top and bottom. */
|
|
2484
2769
|
& .crisp-wheelpicker-fog { position: relative; z-index: 1; height: 100%; overflow: hidden; mask-image: linear-gradient( to bottom, transparent 0, #000 var(--crisp-wheelpicker-fog), #000 calc(100% - var(--crisp-wheelpicker-fog)), transparent 100% ); }
|
|
2485
2770
|
& .crisp-wheelpicker-columns { display: flex; width: 100%; height: 100%; justify-content: center; }
|
|
2486
2771
|
& .crisp-wheelpicker-column { box-sizing: border-box; flex: 0 0 auto; width: max-content; height: 100%; overflow-x: hidden; overflow-y: auto; overscroll-behavior-y: contain; overscroll-behavior-x: none; scroll-snap-type: y mandatory; touch-action: pan-y; scrollbar-width: none; -ms-overflow-style: none; outline: none; padding-block: var(--crisp-wheelpicker-offset); }
|
|
2487
2772
|
& .crisp-wheelpicker-column::-webkit-scrollbar { display: none; }
|
|
2488
2773
|
& .crisp-wheelpicker-item { display: flex; align-items: center; justify-content: center; scroll-snap-align: center; user-select: none; white-space: nowrap; padding-inline: var(--crisp-space-4); color: var(--crisp-fg-disabled); background: none; border: none; font: inherit; cursor: pointer; }
|
|
2489
2774
|
& .crisp-wheelpicker-item[data-selected] { color: var(--crisp-fg-primary); }
|
|
2490
|
-
/* the ring is drawn on the SELECTED row, and only for keyboard focus:
|
|
2775
|
+
/* the ring is drawn on the SELECTED row, and only for keyboard focus:
|
|
2776
|
+
a pointer user has just tapped the row they meant and does not need it */
|
|
2491
2777
|
& .crisp-wheelpicker-column:focus-visible .crisp-wheelpicker-item[data-selected] { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; border-radius: var(--crisp-radius-md); }
|
|
2492
2778
|
}
|
|
2493
2779
|
.crisp-wheelpicker--size_small {
|
|
@@ -2541,7 +2827,11 @@
|
|
|
2541
2827
|
& .crisp-authshell-progress { position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: var(--crisp-border-default); }
|
|
2542
2828
|
& .crisp-authshell-progress-fill { height: 2px; background: var(--crisp-fg-primary); border-radius: 4px; transition: width .2s; }
|
|
2543
2829
|
& .crisp-authshell-logo { margin-top: var(--crisp-space-8); min-height: 24px; display: flex; align-items: center; gap: var(--crisp-space-2-5); }
|
|
2544
|
-
|
|
2830
|
+
/* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
|
|
2831
|
+
the accent (#0298d9) only clears 3.23:1 with white; the darker
|
|
2832
|
+
sibling clears 4.5:1+, same fix already applied to Button/Badge/
|
|
2833
|
+
Avatar (#897). */
|
|
2834
|
+
& .crisp-authshell-logo-badge { flex-shrink: 0; box-sizing: border-box; width: 32px; height: 32px; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-contrast); color: #fff; display: flex; align-items: center; justify-content: center; }
|
|
2545
2835
|
& .crisp-authshell-logo-text { display: flex; flex-direction: column; line-height: 1.2; }
|
|
2546
2836
|
& .crisp-authshell-logo-title { font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-bold); letter-spacing: -0.2px; color: var(--crisp-fg-primary); }
|
|
2547
2837
|
& .crisp-authshell-logo-subtitle { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
@@ -2557,7 +2847,8 @@
|
|
|
2557
2847
|
& .crisp-authshell-form { align-self: stretch; display: flex; flex-direction: column; gap: 28px; }
|
|
2558
2848
|
& .crisp-authshell-footer { margin-top: var(--crisp-space-6); display: flex; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-sm); line-height: 16px; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
2559
2849
|
& .crisp-authshell-footer a { color: inherit; font-weight: var(--crisp-weight-medium); text-decoration: underline; }
|
|
2560
|
-
/* Auth-surface control treatment: flatter than the in-app chrome — a plain
|
|
2850
|
+
/* Auth-surface control treatment: flatter than the in-app chrome — a plain
|
|
2851
|
+
hairline ring instead of elevation.field's soft glow, and a 36px (not
|
|
2561
2852
|
40px) submit. Scoped to .crisp-authshell-body so a consumer keeps using
|
|
2562
2853
|
crisp's Input / FormField / Button and gets the auth treatment for free. */
|
|
2563
2854
|
& .crisp-authshell-body .crisp-formfield-label { font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium); letter-spacing: -0.12px; color: color-mix(in srgb, var(--crisp-fg-primary) 50%, transparent); padding-inline-start: var(--crisp-space-1); }
|
|
@@ -2565,10 +2856,10 @@
|
|
|
2565
2856
|
& .crisp-authshell-body .crisp-input { height: 34px; padding-inline: var(--crisp-space-2-5); border-radius: 10px; background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; transition: box-shadow .14s, background-color .14s; }
|
|
2566
2857
|
& .crisp-authshell-body .crisp-input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
2567
2858
|
/* Same three-layer brand shadow as Button's primary intent, but the auth
|
|
2568
|
-
button's inset ring is measured at rgba(0,0,0,0.06) — a hairline, not
|
|
2859
|
+
button's inset ring is measured at rgba(0,0,0,0.06) — a hairline, not
|
|
2860
|
+
the in-app button's rgba(255,255,255,0.07) highlight. */
|
|
2569
2861
|
& .crisp-authshell-body .crisp-button { height: 36px; padding-inline: var(--crisp-space-3); border-radius: 10px; }
|
|
2570
2862
|
& .crisp-authshell-body .crisp-button--intent_primary { box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08); }
|
|
2571
|
-
|
|
2572
2863
|
/* The preview pane drops out in JS on narrow viewports (measured: two
|
|
2573
2864
|
panes at 1393px, one at 954px), so 1200px is a chosen threshold inside
|
|
2574
2865
|
that bracket, not a measured value. A CONTAINER query, not a media
|
|
@@ -2599,19 +2890,29 @@
|
|
|
2599
2890
|
& .crisp-board-density button[data-state="on"] { background: var(--crisp-bg-surface); color: var(--crisp-fg-primary); }
|
|
2600
2891
|
& .crisp-board-row { display: flex; gap: var(--crisp-space-2); flex: 1; min-height: 0; box-sizing: border-box; padding: var(--crisp-space-3); overflow-x: auto; align-items: flex-start; }
|
|
2601
2892
|
& .crisp-board-col { display: flex; flex-direction: column; width: 268px; flex-shrink: 0; max-height: 100%; box-sizing: border-box; transition: width 0.15s; }
|
|
2602
|
-
/* #718: a collapsed column is a 52px vertical rail -- header only (dot
|
|
2893
|
+
/* #718: a collapsed column is a 52px vertical rail -- header only (dot
|
|
2894
|
+
+ count stacked above a vertical-rl title), body/footer hidden
|
|
2895
|
+
entirely. Measured live: 52px width, 8px 0 padding on the header,
|
|
2896
|
+
14px/600 title text. */
|
|
2603
2897
|
& .crisp-board-col[data-density="collapse"] { width: 52px; }
|
|
2604
2898
|
& .crisp-board-col[data-density="collapse"] .crisp-board-col-header { flex-direction: column; align-items: center; height: auto; padding: var(--crisp-space-2) 0; gap: var(--crisp-space-1); }
|
|
2605
|
-
/* Measured stacking order (top to bottom): dot, count, THEN the vertical
|
|
2899
|
+
/* Measured stacking order (top to bottom): dot, count, THEN the vertical
|
|
2900
|
+
title -- reordered visually via `order`, not by changing the JSX/DOM
|
|
2901
|
+
order, which stays dot/title/count (reading order, unaffected by
|
|
2902
|
+
density). */
|
|
2606
2903
|
& .crisp-board-col[data-density="collapse"] .crisp-board-col-title { order: 1; writing-mode: vertical-rl; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); }
|
|
2607
2904
|
& .crisp-board-col[data-density="collapse"] .crisp-board-col-count { order: 0; }
|
|
2608
2905
|
& .crisp-board-col[data-density="collapse"] .crisp-board-col-body, & .crisp-board-col[data-density="collapse"] .crisp-board-col-footer { display: none; }
|
|
2609
2906
|
& .crisp-board-col-header { display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding: 0 var(--crisp-space-1); flex-shrink: 0; }
|
|
2610
2907
|
& .crisp-board-col-dot { width: 12px; height: 12px; border-radius: var(--crisp-radius-full); flex-shrink: 0; }
|
|
2611
2908
|
& .crisp-board-col-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
2612
|
-
/* crisp#697: HANDOFF's #472 note claimed the count pill's
|
|
2909
|
+
/* crisp#697: HANDOFF's #472 note claimed the count pill's
|
|
2910
|
+
color-mix(fgPrimary, 63%, transparent) reproduced the measured
|
|
2911
|
+
rgb(80,81,85) -- it doesn't; 63% of fgPrimary composited on white
|
|
2613
2912
|
paints rgb(104,105,105), visibly lighter. Text now reads
|
|
2614
|
-
fgNeutralSoft directly (the same rgb(80,81,85) token Badge's neutral
|
|
2913
|
+
fgNeutralSoft directly (the same rgb(80,81,85) token Badge's neutral
|
|
2914
|
+
tone uses, #696), and the ring the pill was also missing
|
|
2915
|
+
(inset 0 0 0 1px borderSubtle, measured rgb(238,239,241)) is added. */
|
|
2615
2916
|
& .crisp-board-col-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) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
|
|
2616
2917
|
& .crisp-board-col-add { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin-inline-start: auto; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; }
|
|
2617
2918
|
& .crisp-board-col-add:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
|
|
@@ -2620,7 +2921,11 @@
|
|
|
2620
2921
|
& .crisp-board-newcard { display: flex; align-items: center; justify-content: center; gap: var(--crisp-space-1-5); height: 32px; flex-shrink: 0; border: none; border-radius: var(--crisp-radius-md); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
2621
2922
|
& .crisp-board-newcard:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); }
|
|
2622
2923
|
& .crisp-board-card { display: flex; flex-direction: column; gap: var(--crisp-space-2); box-sizing: border-box; padding: var(--crisp-space-2-5) var(--crisp-space-3); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); cursor: grab; touch-action: none; }
|
|
2623
|
-
/* #718: a collapsed card is a single 40px row -- measured live and
|
|
2924
|
+
/* #718: a collapsed card is a single 40px row -- measured live and
|
|
2925
|
+
independent of `c.size.tableRow`/`tableHeader` (36/40px) even
|
|
2926
|
+
though it happens to match the latter; a plain literal, not a
|
|
2927
|
+
cross-reference to a token measured for a different surface.
|
|
2928
|
+
`renderCard`'s own second argument is what actually decides what a
|
|
2624
2929
|
collapsed card SHOWS (Board never sees inside its opaque output);
|
|
2625
2930
|
this only supplies the row-shaped box that content sits in. */
|
|
2626
2931
|
& .crisp-board-card[data-density="collapse"] { flex-direction: row; align-items: center; height: 40px; padding: 0 var(--crisp-space-3); }
|
|
@@ -2628,11 +2933,15 @@
|
|
|
2628
2933
|
& .crisp-board-card[data-dragging] { opacity: 0.4; }
|
|
2629
2934
|
& .crisp-board-card:focus { outline: none; }
|
|
2630
2935
|
& .crisp-board-card:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
|
|
2631
|
-
/* #674: the pointer-events drag's own drag image -- the same card
|
|
2936
|
+
/* #674: the pointer-events drag's own drag image -- the same card
|
|
2937
|
+
surface above, just pinned to the pointer instead of the flex flow.
|
|
2938
|
+
No shadow lift or scale: neither was measured against Attio, and this
|
|
2939
|
+
is the same card, momentarily somewhere else, not a new look. */
|
|
2632
2940
|
& .crisp-board-ghost { position: fixed; z-index: 1; pointer-events: none; cursor: grabbing; }
|
|
2633
2941
|
/* #604: a per-column calc footer, mirroring the table's own (measured
|
|
2634
2942
|
live, Deals pipeline). Sits below the scrollable card body, not
|
|
2635
|
-
inside it or pinned to it -- Attio's own is position: static, not
|
|
2943
|
+
inside it or pinned to it -- Attio's own is position: static, not
|
|
2944
|
+
sticky, so it's a plain flex-shrink:0 sibling here too. */
|
|
2636
2945
|
& .crisp-board-col-footer { flex-shrink: 0; padding: var(--crisp-space-1) 0; }
|
|
2637
2946
|
& .crisp-board-col-calc { display: flex; align-items: center; justify-content: center; gap: var(--crisp-space-1); width: 100%; height: 28px; padding: var(--crisp-space-1) var(--crisp-space-2); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); cursor: pointer; }
|
|
2638
2947
|
& .crisp-board-col-calc:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
|
|
@@ -2641,7 +2950,9 @@
|
|
|
2641
2950
|
& .crisp-board-col-calc-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; }
|
|
2642
2951
|
/* #718: "Add stage" -- measured live: 52×52px, transparent, a 1px
|
|
2643
2952
|
dashed border (rgb(230,231,234), exactly `borderDropzone`/`line150`
|
|
2644
|
-
-- the same dashed-border colour ImportDialog's own dropzone already
|
|
2953
|
+
-- the same dashed-border colour ImportDialog's own dropzone already
|
|
2954
|
+
uses, not borderSubtle/line100, a close but different value), radius.xl
|
|
2955
|
+
(16px), a centered 16px "+". */
|
|
2645
2956
|
& .crisp-board-addstage { display: inline-flex; align-items: center; justify-content: center; width: 52px; height: 52px; flex-shrink: 0; border: 1px dashed var(--crisp-border-dropzone); border-radius: var(--crisp-radius-xl); background: none; color: var(--crisp-fg-primary); font-family: inherit; cursor: pointer; }
|
|
2646
2957
|
& .crisp-board-addstage:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
|
|
2647
2958
|
/* announced, never drawn */
|
|
@@ -2665,28 +2976,32 @@
|
|
|
2665
2976
|
& .crisp-command-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); overflow: hidden; }
|
|
2666
2977
|
& .crisp-command-control { display: flex; align-items: center; gap: var(--crisp-space-2-5); height: 52px; flex-shrink: 0; padding: 0 var(--crisp-space-4); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
|
|
2667
2978
|
& .crisp-command-control svg { flex-shrink: 0; }
|
|
2668
|
-
/* The palette's label element. It exists for the assistive tree only: zag's
|
|
2979
|
+
/* The palette's label element. It exists for the assistive tree only: zag's
|
|
2980
|
+
combobox names the input through it and points the listbox's
|
|
2669
2981
|
aria-labelledby at it, and without it both were unnamed and the reference
|
|
2670
2982
|
resolved to nothing (#225). Clipped rather than display:none, which would
|
|
2671
2983
|
take it out of the tree it exists for. */
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2984
|
+
& .crisp-command-srlabel { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
2985
|
+
& .crisp-command-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-xl); color: var(--crisp-fg-primary); }
|
|
2986
|
+
& .crisp-command-input::placeholder { color: var(--crisp-fg-muted); }
|
|
2987
|
+
& .crisp-command-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--crisp-space-1) var(--crisp-space-2-5); display: flex; flex-direction: column; gap: var(--crisp-space-px); }
|
|
2988
|
+
& .crisp-command-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
2989
|
+
& .crisp-command-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding-inline: var(--crisp-space-2-5); border-radius: var(--crisp-radius-xl); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; }
|
|
2990
|
+
& .crisp-command-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
2991
|
+
& .crisp-command-item[data-highlighted] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
|
|
2992
|
+
& .crisp-command-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2993
|
+
& .crisp-command-item-shortcut { margin-inline-start: auto; flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
|
|
2994
|
+
& .crisp-command-group-label { padding: var(--crisp-space-2) var(--crisp-space-2-5) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
2995
|
+
& .crisp-command-list > .crisp-command-group-label:first-child { padding-top: var(--crisp-space-1); }
|
|
2996
|
+
& .crisp-command-footer { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; height: 44px; padding: 0 var(--crisp-space-2-5); border-top: 1px solid var(--crisp-border-subtle); }
|
|
2997
|
+
& .crisp-command-footer-nav { display: flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
2998
|
+
/* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
|
|
2999
|
+
the accent (#0298d9) only clears 3.23:1 with white; the darker sibling
|
|
3000
|
+
clears 4.5:1+, same fix already applied to Button/Badge/Avatar (#897). */
|
|
3001
|
+
& .crisp-command-footer-action { display: flex; align-items: center; gap: var(--crisp-space-2); height: 28px; max-width: 60%; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
|
|
3002
|
+
& .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
|
|
3003
|
+
& .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3004
|
+
& .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
|
|
2690
3005
|
}
|
|
2691
3006
|
|
|
2692
3007
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -2729,7 +3044,7 @@
|
|
|
2729
3044
|
[dir="rtl"] .crisp-comments-badge [data-rtl-flip] { transform: scaleX(-1); }
|
|
2730
3045
|
|
|
2731
3046
|
.crisp-comments {
|
|
2732
|
-
display: flex; flex-direction: column; box-sizing: border-box;
|
|
3047
|
+
display: flex; flex-direction: column; box-sizing: border-box; height: 100%; background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
2733
3048
|
& * { box-sizing: border-box; }
|
|
2734
3049
|
& .crisp-comments-head { display: flex; align-items: center; gap: var(--crisp-space-1); flex-shrink: 0; height: 49px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-4); }
|
|
2735
3050
|
& .crisp-comments-headbtn { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
@@ -2739,13 +3054,21 @@
|
|
|
2739
3054
|
& .crisp-comments-breadcrumb { display: flex; align-items: center; gap: var(--crisp-space-1); font-size: 12px; font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2740
3055
|
& .crisp-comments-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
2741
3056
|
& .crisp-comments-body--pad-top { padding-top: var(--crisp-space-3); }
|
|
2742
|
-
/* One comment row -- avatar 16px (Avatar size="sm"), 6px gap to the
|
|
2743
|
-
|
|
3057
|
+
/* One comment row -- avatar 16px (Avatar size="sm"), 6px gap to the
|
|
3058
|
+
name/time line, 14px/600 name + 12px/500 63%-muted time, 14px/400 body
|
|
3059
|
+
two lines below. Hover actions fade in flush with the name line.
|
|
3060
|
+
.crisp-comments-row-head's own height: 20px (above) is a single
|
|
3061
|
+
text-line's worth, on the same assumption .crisp-comments-title/
|
|
3062
|
+
.crisp-comments-breadcrumb already act on higher up in this same
|
|
3063
|
+
recipe -- a name that doesn't fit wraps to two lines with nothing
|
|
2744
3064
|
reserving room for the second one, overflowing straight into the
|
|
2745
|
-
body text underneath (found live: this app's own dev-bypass author
|
|
3065
|
+
body text underneath (found live: this app's own dev-bypass author
|
|
3066
|
+
name, an email long enough to wrap, sat on top of the comment's own
|
|
2746
3067
|
body text). .crisp-comments-author gets the identical nowrap-
|
|
2747
3068
|
ellipsis treatment those two already have, plus min-width: 0 so a
|
|
2748
|
-
flex item is actually allowed to shrink below its own text's natural
|
|
3069
|
+
flex item is actually allowed to shrink below its own text's natural
|
|
3070
|
+
width in the first place; .crisp-comments-time gets flex-shrink: 0
|
|
3071
|
+
so it's the name that gives, never the timestamp -- the same "one
|
|
2749
3072
|
side shrinks, the other one doesn't" split PersonChip's own name/
|
|
2750
3073
|
avatar pair already uses (crisp#668/#671). */
|
|
2751
3074
|
& .crisp-comments-row { position: relative; display: flex; gap: var(--crisp-space-1-5); }
|
|
@@ -2755,16 +3078,13 @@
|
|
|
2755
3078
|
& .crisp-comments-time { flex-shrink: 0; font-size: 12px; font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); white-space: nowrap; }
|
|
2756
3079
|
& .crisp-comments-resolved-label { display: flex; align-items: center; gap: var(--crisp-space-1); margin-bottom: var(--crisp-space-1); font-size: 12px; font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
2757
3080
|
& .crisp-comments-body-text { font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
|
|
2758
|
-
|
|
2759
3081
|
/* Hover actions -- measured: 4 buttons, 28x28, radius 8, flush
|
|
2760
3082
|
side-by-side (0 gap), transparent by default, 16px icon at 55% ink. */
|
|
2761
3083
|
& .crisp-comments-row-actions { position: absolute; top: 0; inset-inline-end: 0; display: flex; opacity: 0; pointer-events: none; background: var(--crisp-bg-surface); }
|
|
2762
|
-
& .crisp-comments-row:hover .crisp-comments-row-actions,
|
|
2763
|
-
& .crisp-comments-row-actions:focus-within { opacity: 1; pointer-events: auto; }
|
|
3084
|
+
& .crisp-comments-row:hover .crisp-comments-row-actions, & .crisp-comments-row-actions:focus-within { opacity: 1; pointer-events: auto; }
|
|
2764
3085
|
& .crisp-comments-action { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
2765
3086
|
& .crisp-comments-action:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
2766
3087
|
& .crisp-comments-action[data-active] { color: var(--crisp-bg-brand-solid); }
|
|
2767
|
-
|
|
2768
3088
|
/* Reactions -- measured: 28px pill, radius 8, subtle 4% ink fill,
|
|
2769
3089
|
padding 4px 8px 4px 6px, gap 4px between the emoji glyph and count. */
|
|
2770
3090
|
& .crisp-comments-reactions { display: flex; flex-wrap: wrap; gap: var(--crisp-space-1); margin-top: var(--crisp-space-1-5); }
|
|
@@ -2773,12 +3093,9 @@
|
|
|
2773
3093
|
& .crisp-comments-reaction-add { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: none; border-radius: var(--crisp-radius-md); background: transparent; font-family: inherit; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); cursor: pointer; opacity: 0; transition: opacity .12s, background-color .12s; }
|
|
2774
3094
|
& .crisp-comments-row:hover .crisp-comments-reaction-add { opacity: 1; }
|
|
2775
3095
|
& .crisp-comments-reaction-add:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
2776
|
-
|
|
2777
3096
|
/* Reply-in-thread view -- an indented block of replies below the root. */
|
|
2778
3097
|
& .crisp-comments-replies { display: flex; flex-direction: column; gap: var(--crisp-space-4); margin-top: var(--crisp-space-3); padding-inline-start: var(--crisp-space-4); border-inline-start: 1px solid var(--crisp-border-subtle); }
|
|
2779
|
-
|
|
2780
3098
|
& .crisp-comments-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--crisp-space-1); padding: var(--crisp-space-6) var(--crisp-space-4); text-align: center; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-size: var(--crisp-text-lg); }
|
|
2781
|
-
|
|
2782
3099
|
/* Composer -- measured: 14px/20px body text, 16px gap above the
|
|
2783
3100
|
reply/mention icon row, Comment button 84x32 padding 6px 10px radius
|
|
2784
3101
|
9 (= radius.lg) brand-solid fill, 14px/500 white label, opacity .4
|
|
@@ -2796,21 +3113,28 @@
|
|
|
2796
3113
|
box-shadow, so this reuses that literal rather than re-deriving it.
|
|
2797
3114
|
32px/radius.lg/6px-10px padding has no matching Button `size` yet
|
|
2798
3115
|
(24/28/40 are the three that exist), so this stays hand-rolled instead
|
|
2799
|
-
of stretching one of those.
|
|
2800
|
-
|
|
2801
|
-
|
|
3116
|
+
of stretching one of those. your-moon/crisp#953:
|
|
3117
|
+
bgBrandContrast, not bgBrandSolid -- the accent (#0298d9) only clears
|
|
3118
|
+
3.23:1 with white; same fix already applied to Button/Badge/Avatar
|
|
3119
|
+
(#897). Hover is a brightness filter on the new fill, matching that
|
|
3120
|
+
PR's own Button primary treatment, not bgBrandSolidPressed. */
|
|
3121
|
+
& .crisp-comments-post { display: inline-flex; align-items: center; justify-content: center; height: 32px; padding: 6px var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-lg); background: var(--crisp-bg-brand-contrast); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-on-brand); cursor: pointer; opacity: 1; transition: opacity .12s, filter .12s; }
|
|
3122
|
+
& .crisp-comments-post:hover:not(:disabled) { filter: brightness(0.96); }
|
|
2802
3123
|
& .crisp-comments-post:disabled { opacity: .4; cursor: default; }
|
|
2803
|
-
|
|
2804
3124
|
/* Filter menu -- measured: 220px, radius 12 (radius.xl), 4px padding,
|
|
2805
3125
|
elevation.floating -- a plain reuse of crisp's own Menu, so no rules
|
|
2806
|
-
live here; kept as a comment for the record. */
|
|
2807
|
-
|
|
2808
|
-
/* An inserted "@mention" chip in the composer -- same shape as
|
|
3126
|
+
live here; kept as a comment for the record. */ /* An inserted "@mention" chip in the composer -- same shape as
|
|
2809
3127
|
RichTextEditor's own `.crisp-rte-mention` (crisp#428), reused here
|
|
2810
3128
|
rather than re-derived since it's the same atomic-chip affordance. */
|
|
2811
3129
|
& .crisp-comments-mention { display: inline; padding: 0 2px; border-radius: 4px; background: color-mix(in srgb, var(--crisp-bg-brand-solid) 12%, transparent); color: var(--crisp-bg-brand-solid); font-weight: var(--crisp-weight-medium); user-select: none; }
|
|
2812
3130
|
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
2813
3131
|
}
|
|
3132
|
+
.crisp-comments--variant_drawer {
|
|
3133
|
+
width: 320px; border-inline-start: 1px solid var(--crisp-border-subtle);
|
|
3134
|
+
}
|
|
3135
|
+
.crisp-comments--variant_pane {
|
|
3136
|
+
width: 100%;
|
|
3137
|
+
}
|
|
2814
3138
|
|
|
2815
3139
|
@media (prefers-reduced-motion: reduce) {
|
|
2816
3140
|
.crisp-comments, .crisp-comments * {
|
|
@@ -2952,7 +3276,9 @@
|
|
|
2952
3276
|
& .crisp-listpage-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); white-space: nowrap; }
|
|
2953
3277
|
/* #641: trailing (View settings / New) has to reach the toolbar's own
|
|
2954
3278
|
inline-end edge on its own -- the only thing pushing it there used
|
|
2955
|
-
to be .crisp-listpage-count's margin-inline-start: auto, which a
|
|
3279
|
+
to be .crisp-listpage-count's margin-inline-start: auto, which a
|
|
3280
|
+
consumer with no count badge (TasksTable, measured live: trailing
|
|
3281
|
+
sat right after leading, nowhere near the row's own right edge)
|
|
2956
3282
|
never renders. A bare margin-inline-start: auto here is safely
|
|
2957
3283
|
overridden by the more specific rule right below whenever count IS
|
|
2958
3284
|
present, so the two cases don't fight -- count's own auto margin
|
|
@@ -2982,6 +3308,74 @@
|
|
|
2982
3308
|
}
|
|
2983
3309
|
}
|
|
2984
3310
|
|
|
3311
|
+
.crisp-memberssettings {
|
|
3312
|
+
& .crisp-memberssettings-page { display: flex; flex-direction: column; gap: var(--crisp-space-6); font-family: var(--crisp-font-sans); }
|
|
3313
|
+
& .crisp-memberssettings-heading { display: flex; flex-direction: column; gap: var(--crisp-space-0-5); }
|
|
3314
|
+
& .crisp-memberssettings-title { font-size: 24px; line-height: 28px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.48px; color: var(--crisp-fg-primary); margin: 0; }
|
|
3315
|
+
& .crisp-memberssettings-desc { font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-muted); margin: 0; }
|
|
3316
|
+
/* Segmented Members/Teams switcher -- measured: 28px pills, radius 8,
|
|
3317
|
+
4px gap, 6px icon-label gap, 14/500 label, selected bg bgSubtle +
|
|
3318
|
+
inset borderSubtle ring, unselected transparent + a flat 63%-opacity
|
|
3319
|
+
fgPrimary mix (measured rgba(0,0,0,.63) on the live page, not the
|
|
3320
|
+
solid fgMuted token — same alpha technique this file's table header
|
|
3321
|
+
already uses). */
|
|
3322
|
+
& .crisp-memberssettings-tabpair { display: inline-flex; align-items: center; gap: 4px; }
|
|
3323
|
+
& .crisp-memberssettings-tab { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: none; box-shadow: inset 0 0 0 1px transparent; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease, box-shadow .12s ease; }
|
|
3324
|
+
& .crisp-memberssettings-tab svg { flex-shrink: 0; }
|
|
3325
|
+
& .crisp-memberssettings-tab:hover:not([data-selected]) { color: var(--crisp-fg-primary); }
|
|
3326
|
+
& .crisp-memberssettings-tab[data-selected] { color: var(--crisp-fg-primary); background: var(--crisp-bg-subtle); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); }
|
|
3327
|
+
& .crisp-memberssettings-tab:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
|
|
3328
|
+
/* Toolbar row: search grows, Filter + Invite sit trailing -- measured
|
|
3329
|
+
32px height on all three, search radius 9 with a 6% ink ring,
|
|
3330
|
+
Filter/Invite radius 9 with the button drop-shadow pairing. */
|
|
3331
|
+
& .crisp-memberssettings-toolbar { display: flex; align-items: center; gap: var(--crisp-space-2); }
|
|
3332
|
+
& .crisp-memberssettings-search { display: flex; align-items: center; flex: 1; min-width: 0; gap: var(--crisp-space-1-5); height: 32px; padding: 0 var(--crisp-space-2-5) 0 var(--crisp-space-2); border-radius: 9px; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-muted); }
|
|
3333
|
+
& .crisp-memberssettings-search:focus-within { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
3334
|
+
& .crisp-memberssettings-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
3335
|
+
& .crisp-memberssettings-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
3336
|
+
& .crisp-memberssettings-filterbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 32px; padding: 6px 10px 6px 8px; border: none; border-radius: 9px; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px transparent, 0 0 2px 0 rgba(28,40,64,.18), 0 1px 3px 0 rgba(0,0,0,.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); cursor: pointer; white-space: nowrap; }
|
|
3337
|
+
& .crisp-memberssettings-filterbtn:hover { background: var(--crisp-bg-raised); }
|
|
3338
|
+
/* your-moon/crisp#979: bgBrandContrast, not bgBrandSolid -- the accent
|
|
3339
|
+
(#0298d9) only clears 3.23:1 with white; the darker sibling clears
|
|
3340
|
+
4.5:1+, same fix already applied to Button/Badge/Avatar (#897) and
|
|
3341
|
+
TableToolbar/Dialog/Command/Comments/AuthShell (#953/#961), which
|
|
3342
|
+
explicitly flagged this button as found-not-fixed. */
|
|
3343
|
+
& .crisp-memberssettings-invitebtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 32px; padding: 6px 10px 6px 8px; border: none; border-radius: 9px; background: var(--crisp-bg-brand-contrast); box-shadow: inset 0 0 0 1px rgba(0,0,0,.06), 0 2px 4px -2px color-mix(in srgb, var(--crisp-bg-brand-contrast) 12%, transparent), 0 3px 6px -2px color-mix(in srgb, var(--crisp-bg-brand-contrast) 8%, transparent); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); cursor: pointer; white-space: nowrap; }
|
|
3344
|
+
& .crisp-memberssettings-invitebtn:hover { filter: brightness(0.95); }
|
|
3345
|
+
/* Table wrapper -- measured card: radius 12, 1px borderSubtle, 40px
|
|
3346
|
+
rows, header label 12/500/63%-opacity fgPrimary. */
|
|
3347
|
+
& .crisp-memberssettings-table-wrap { border-radius: 12px; border: 1px solid var(--crisp-border-subtle); overflow: hidden; }
|
|
3348
|
+
& .crisp-memberssettings-table { width: 100%; border-collapse: collapse; font-family: inherit; }
|
|
3349
|
+
& .crisp-memberssettings-table th { height: 32px; padding: 0 var(--crisp-space-4); text-align: start; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); border-bottom: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); }
|
|
3350
|
+
& .crisp-memberssettings-table td { height: 40px; padding: 0 var(--crisp-space-4); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); border-bottom: 1px solid var(--crisp-border-subtle); }
|
|
3351
|
+
& .crisp-memberssettings-table tr:last-child td { border-bottom: none; }
|
|
3352
|
+
& .crisp-memberssettings-user { display: flex; align-items: center; gap: var(--crisp-space-2); }
|
|
3353
|
+
& .crisp-memberssettings-avatarimg { width: 24px; height: 24px; border-radius: var(--crisp-radius-full); object-fit: cover; }
|
|
3354
|
+
/* Name + email sit on ONE line, not stacked -- confirmed live: both spans
|
|
3355
|
+
share the same y and the same 14px size, only the email's colour
|
|
3356
|
+
differs (a flat 63%-opacity fgPrimary mix, not a smaller muted font). */
|
|
3357
|
+
& .crisp-memberssettings-usermeta { display: flex; align-items: baseline; gap: var(--crisp-space-2); min-width: 0; }
|
|
3358
|
+
& .crisp-memberssettings-usermeta > span:first-child { flex-shrink: 0; }
|
|
3359
|
+
& .crisp-memberssettings-useremail { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-regular); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3360
|
+
& .crisp-memberssettings-kebab { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-inline-start: auto; border: none; border-radius: var(--crisp-radius-sm); background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: pointer; }
|
|
3361
|
+
& .crisp-memberssettings-kebab:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
3362
|
+
& .crisp-memberssettings-teamspanel { display: flex; align-items: center; justify-content: center; padding: var(--crisp-space-8) 0; color: var(--crisp-fg-muted); font-size: var(--crisp-text-lg); }
|
|
3363
|
+
/* Invite dialog fields -- measured 708x386 dialog, radius 16; the
|
|
3364
|
+
"Invite as"/"Add to team" selects are 32/34px with a flat 1px
|
|
3365
|
+
6%-ink border and 9/10px radius respectively (Attio's own two
|
|
3366
|
+
selects don't share one radius). */
|
|
3367
|
+
& .crisp-memberssettings-invitefield { display: flex; flex-direction: column; gap: var(--crisp-space-1-5); }
|
|
3368
|
+
& .crisp-memberssettings-invitelabel { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
3369
|
+
}
|
|
3370
|
+
|
|
3371
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3372
|
+
.crisp-memberssettings, .crisp-memberssettings * {
|
|
3373
|
+
animation-duration: 0.01ms !important;
|
|
3374
|
+
animation-iteration-count: 1 !important;
|
|
3375
|
+
transition-duration: 0.01ms !important;
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
|
|
2985
3379
|
|
|
2986
3380
|
.crisp-navitem-shortcut { display: flex; align-items: baseline; justify-content: space-between; gap: var(--crisp-space-3); }
|
|
2987
3381
|
.crisp-navitem-shortcut-desc { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); line-height: 16px; white-space: nowrap; }
|
|
@@ -3005,6 +3399,29 @@
|
|
|
3005
3399
|
}
|
|
3006
3400
|
}
|
|
3007
3401
|
|
|
3402
|
+
.crisp-notificationssettings {
|
|
3403
|
+
& .crisp-notificationssettings-page { display: flex; flex-direction: column; gap: var(--crisp-space-6); font-family: var(--crisp-font-sans); }
|
|
3404
|
+
& .crisp-notificationssettings-heading { display: flex; flex-direction: column; gap: var(--crisp-space-0-5); }
|
|
3405
|
+
& .crisp-notificationssettings-title { font-size: 24px; line-height: 28px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.48px; color: var(--crisp-fg-primary); margin: 0; }
|
|
3406
|
+
& .crisp-notificationssettings-desc { font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-muted); margin: 0; }
|
|
3407
|
+
& .crisp-notificationssettings-section { display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
3408
|
+
& .crisp-notificationssettings-sectiontitle { font-size: 16px; line-height: 20px; font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); margin: 0; }
|
|
3409
|
+
/* Daily digest card: one bordered 12px-radius row. */
|
|
3410
|
+
& .crisp-notificationssettings-digestcard { display: flex; align-items: center; justify-content: space-between; gap: var(--crisp-space-6); padding: var(--crisp-space-2) var(--crisp-space-3); border: 1px solid var(--crisp-border-subtle); border-radius: 12px; background: var(--crisp-bg-surface); }
|
|
3411
|
+
& .crisp-notificationssettings-digesttext { display: flex; flex-direction: column; gap: var(--crisp-space-1); }
|
|
3412
|
+
& .crisp-notificationssettings-rowtitle { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
3413
|
+
& .crisp-notificationssettings-rowdesc { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
3414
|
+
/* Collaboration matrix: a bordered card, header row + N body rows. */
|
|
3415
|
+
& .crisp-notificationssettings-matrix { border: 1px solid var(--crisp-border-subtle); border-radius: 12px; overflow: hidden; background: var(--crisp-bg-surface); }
|
|
3416
|
+
& .crisp-notificationssettings-matrixhead { display: flex; align-items: center; gap: var(--crisp-space-3); padding: 0 var(--crisp-space-4); height: 40px; border-bottom: 1px solid var(--crisp-border-subtle); }
|
|
3417
|
+
& .crisp-notificationssettings-matrixhead-about { display: flex; align-items: center; gap: var(--crisp-space-1-5); flex: 1; min-width: 0; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
3418
|
+
& .crisp-notificationssettings-matrixhead-col { display: flex; align-items: center; justify-content: center; gap: var(--crisp-space-1-5); width: 64px; flex-shrink: 0; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
3419
|
+
& .crisp-notificationssettings-matrixrow { display: flex; align-items: center; gap: var(--crisp-space-3); padding: var(--crisp-space-2) var(--crisp-space-4); min-height: 52px; }
|
|
3420
|
+
& .crisp-notificationssettings-matrixrow + .crisp-notificationssettings-matrixrow { border-top: 1px solid var(--crisp-border-subtle); }
|
|
3421
|
+
& .crisp-notificationssettings-matrixrow-about { display: flex; flex-direction: column; gap: var(--crisp-space-1); flex: 1; min-width: 0; }
|
|
3422
|
+
& .crisp-notificationssettings-matrixrow-col { display: flex; align-items: center; justify-content: center; width: 64px; flex-shrink: 0; }
|
|
3423
|
+
}
|
|
3424
|
+
|
|
3008
3425
|
.crisp-objectsettings {
|
|
3009
3426
|
& .crisp-objectsettings-page { display: flex; flex-direction: column; gap: var(--crisp-space-6); }
|
|
3010
3427
|
& .crisp-objectsettings-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--crisp-space-4); }
|
|
@@ -3019,22 +3436,22 @@
|
|
|
3019
3436
|
& .crisp-objectsettings-filterbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-2-5) 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-lg); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); cursor: pointer; white-space: nowrap; }
|
|
3020
3437
|
& .crisp-objectsettings-filterbtn:hover { background: var(--crisp-bg-raised); }
|
|
3021
3438
|
/* Object / attribute icon tile — Attio's own squircle (measured
|
|
3022
|
-
border-radius: 30%, not a scale token: it's a proportional radius
|
|
3439
|
+
border-radius: 30%, not a scale token: it's a proportional radius
|
|
3440
|
+
tied to the tile's own size, unlike every other radius crisp uses,
|
|
3023
3441
|
which is a fixed px). */
|
|
3024
3442
|
& .crisp-objectsettings-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 16px; height: 16px; border-radius: 30%; color: var(--crisp-fg-on-brand); }
|
|
3025
3443
|
& .crisp-objectsettings-icon--lg { width: 48px; height: 48px; border-radius: 16px; }
|
|
3026
|
-
|
|
3027
3444
|
/* "Standard"/"Custom" type badge and the muted "No records" cell —
|
|
3028
3445
|
plain text, not a Badge pill (measured: transparent background). */
|
|
3029
3446
|
& .crisp-objectsettings-typebadge { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
|
|
3030
3447
|
& .crisp-objectsettings-muted { color: var(--crisp-fg-muted); }
|
|
3031
|
-
|
|
3032
3448
|
/* Attribute-type option row (icon + label + optional trailing badge),
|
|
3033
3449
|
composed as a Select option's `label` ReactNode. */
|
|
3034
3450
|
& .crisp-objectsettings-typeoption { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; min-width: 0; }
|
|
3035
3451
|
& .crisp-objectsettings-typeoption-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
3036
3452
|
& .crisp-objectsettings-typeoption-badge { flex-shrink: 0; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-brand-soft); }
|
|
3037
|
-
/* Create-attribute dialog's AI-autofill row and the submit button's
|
|
3453
|
+
/* Create-attribute dialog's AI-autofill row and the submit button's
|
|
3454
|
+
⌘↵ hint (measured off the same dialog, same shape as Dialog's own
|
|
3038
3455
|
.crisp-dialog-submit-key, kept local rather than reaching into
|
|
3039
3456
|
another component's scoped classes). */
|
|
3040
3457
|
& .crisp-objectsettings-aiautofill { display: flex; flex-direction: column; gap: var(--crisp-space-1-5); }
|
|
@@ -3090,6 +3507,21 @@
|
|
|
3090
3507
|
display: flex; flex-direction: column; height: 100%; min-height: 0; background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: var(--crisp-fg-primary);
|
|
3091
3508
|
& * { box-sizing: border-box; }
|
|
3092
3509
|
& .crisp-recordpage-topbar { display: flex; align-items: center; gap: var(--crisp-space-2); height: 44px; flex-shrink: 0; padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); }
|
|
3510
|
+
/* #624: expanding a peek to its full record keeps a hybrid header
|
|
3511
|
+
(Close/Previous/Next/counter) instead of reverting to the plain
|
|
3512
|
+
breadcrumb above -- measured live on a real expanded record: 49px
|
|
3513
|
+
tall (not 44px), 8px/10px padding, same borderSubtle hairline. Same
|
|
3514
|
+
tokens as product/recordpanel's own already-shipped toolbar, not
|
|
3515
|
+
new values -- this is the same row, reused in a second component. */
|
|
3516
|
+
& .crisp-recordpage-topbar[data-peek] { height: 49px; padding: var(--crisp-space-2) var(--crisp-space-2-5); }
|
|
3517
|
+
& .crisp-recordpage-peekbar { display: flex; align-items: center; }
|
|
3518
|
+
& .crisp-recordpage-peek-iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; cursor: pointer; transition: background-color .12s; }
|
|
3519
|
+
& .crisp-recordpage-peek-iconbtn:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
3520
|
+
& .crisp-recordpage-peek-pager { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: var(--crisp-space-3); }
|
|
3521
|
+
& .crisp-recordpage-peek-navbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: 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; cursor: pointer; }
|
|
3522
|
+
& .crisp-recordpage-peek-navbtn:hover:not(:disabled) { background: var(--crisp-bg-raised); }
|
|
3523
|
+
& .crisp-recordpage-peek-navbtn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
3524
|
+
& .crisp-recordpage-peek-counter { margin-inline-start: var(--crisp-space-3); font-size: 12px; font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3093
3525
|
& .crisp-recordpage-crumbs { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
3094
3526
|
& .crisp-recordpage-crumb { display: inline-flex; align-items: center; height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0 calc(-1 * var(--crisp-space-1-5)) 0 0; border: none; border-radius: var(--crisp-radius-md); background: none; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); cursor: pointer; }
|
|
3095
3527
|
& .crisp-recordpage-crumb:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
@@ -3107,6 +3539,17 @@
|
|
|
3107
3539
|
& .crisp-recordpage-resizer::before { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: -4px; width: 9px; }
|
|
3108
3540
|
& .crisp-recordpage-resizer::after { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: -1px; width: 2px; background: transparent; transition: background-color .12s ease; }
|
|
3109
3541
|
& .crisp-recordpage-resizer:hover::after, & .crisp-recordpage-resizer[data-active]::after { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 55%, transparent); }
|
|
3542
|
+
/* #930: RecordDetails' own standalone resize handle -- same visible
|
|
3543
|
+
hit-slop/line-highlight shape as .crisp-recordpage-resizer just above,
|
|
3544
|
+
just absolutely positioned at the trailing edge instead of a 0-width
|
|
3545
|
+
flex sibling, since RecordDetails always returns a single root (the
|
|
3546
|
+
same internal-strip placement RecordPanel's own resize handle uses,
|
|
3547
|
+
mirrored to the opposite edge -- this column is leading, RecordPanel
|
|
3548
|
+
is trailing). */
|
|
3549
|
+
& .crisp-recordpage-section[data-resizable] { position: relative; }
|
|
3550
|
+
& .crisp-recordpage-detailresize { position: absolute; top: 0; bottom: 0; inset-inline-end: -4px; width: 9px; cursor: col-resize; z-index: 5; touch-action: none; }
|
|
3551
|
+
& .crisp-recordpage-detailresize::after { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-end: 3px; width: 2px; background: transparent; transition: background-color .12s ease; }
|
|
3552
|
+
& .crisp-recordpage-detailresize:hover::after, & .crisp-recordpage-detailresize[data-active]::after { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 55%, transparent); }
|
|
3110
3553
|
& .crisp-recordpage-entity { display: flex; align-items: center; gap: var(--crisp-space-2); padding: var(--crisp-space-1) var(--crisp-space-1) var(--crisp-space-2); }
|
|
3111
3554
|
& .crisp-recordpage-entity-logo { width: 32px; height: 32px; border-radius: 30%; flex-shrink: 0; object-fit: cover; background: var(--crisp-bg-raised); }
|
|
3112
3555
|
& .crisp-recordpage-entity-name { flex: 0 1 auto; min-width: 0; font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.3px; color: var(--crisp-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
@@ -3122,7 +3565,8 @@
|
|
|
3122
3565
|
& .crisp-recordpage-quickbtn:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
3123
3566
|
& .crisp-recordpage-section { padding-top: var(--crisp-space-2); }
|
|
3124
3567
|
& .crisp-recordpage-section-title { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); letter-spacing: -0.12px; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); padding: var(--crisp-space-1); }
|
|
3125
|
-
/* main-area section headers (Highlights / Activity / Emails / Notes / Tasks)
|
|
3568
|
+
/* main-area section headers (Highlights / Activity / Emails / Notes / Tasks)
|
|
3569
|
+
are 14px; the left column's (Record Details / Lists) stay 12px. */
|
|
3126
3570
|
& .crisp-recordpage-main .crisp-recordpage-section-title { font-size: var(--crisp-text-lg); }
|
|
3127
3571
|
& .crisp-recordpage-detailhead { display: flex; align-items: center; gap: var(--crisp-space-0-5); margin-bottom: var(--crisp-space-3); padding-inline-end: var(--crisp-space-0-5); }
|
|
3128
3572
|
& .crisp-recordpage-collapse { display: inline-flex; align-items: center; gap: 2px; flex: 1; min-width: 0; margin: 0; border: none; background: none; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); letter-spacing: -0.12px; color: var(--crisp-fg-muted); cursor: pointer; text-align: start; }
|
|
@@ -3137,7 +3581,8 @@
|
|
|
3137
3581
|
& .crisp-recordpage-noresults { padding: var(--crisp-space-1-5) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
3138
3582
|
/* A caller-supplied `sections` grouping (#528) is not an Attio-measured
|
|
3139
3583
|
shape (its own Details column is flat) -- this heading reuses
|
|
3140
|
-
.crisp-recordpage-section-title's own type treatment verbatim, just
|
|
3584
|
+
.crisp-recordpage-section-title's own type treatment verbatim, just
|
|
3585
|
+
spaced from the group above it. */
|
|
3141
3586
|
& .crisp-recordpage-fieldsection-title { margin-top: var(--crisp-space-3); }
|
|
3142
3587
|
& .crisp-recordpage-morevalues { display: inline-flex; align-items: center; padding: 0; margin: 0; border: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); cursor: pointer; }
|
|
3143
3588
|
& .crisp-recordpage-morevalues:hover { color: var(--crisp-fg-primary); }
|
|
@@ -3153,25 +3598,38 @@
|
|
|
3153
3598
|
& .crisp-recordpage-field-label-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3154
3599
|
& .crisp-recordpage-field-value { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); padding-top: 2px; line-height: 20px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
3155
3600
|
& .crisp-recordpage-field-value[data-editable] { cursor: pointer; }
|
|
3156
|
-
/* the click-to-edit trigger is a real <button> (keyboard-operable),
|
|
3601
|
+
/* the click-to-edit trigger is a real <button> (keyboard-operable),
|
|
3602
|
+
reset back to plain inline text and made a flex-wrap container of its
|
|
3603
|
+
own -- FieldValue can render several chips (tags), which still need
|
|
3604
|
+
to wrap the way they did before this had a button around them at
|
|
3605
|
+
all. It wraps only FieldValue, never the error slot beside it (see
|
|
3606
|
+
the component's own comment) -- NOT `display: contents`, which
|
|
3157
3607
|
drops a button's accessible semantics in some engines. */
|
|
3158
3608
|
& .crisp-recordpage-edit-trigger { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); margin: 0; padding: 0; border: none; background: none; text-align: start; font: inherit; color: inherit; cursor: pointer; }
|
|
3159
3609
|
& .crisp-recordpage-empty { color: var(--crisp-fg-muted); }
|
|
3160
3610
|
/* #431: measured live on app.attio.com's record page Details column --
|
|
3161
|
-
clicking a field's value opens a plain, borderless field exactly
|
|
3611
|
+
clicking a field's value opens a plain, borderless field exactly
|
|
3612
|
+
filling the value's own box (no border, no background, no
|
|
3162
3613
|
box-shadow), same font as the value it replaces (hence `font:
|
|
3163
|
-
inherit`, not a restated size/weight). A field row's own hover tint
|
|
3164
|
-
|
|
3614
|
+
inherit`, not a restated size/weight). A field row's own hover tint
|
|
3615
|
+
above already carries the "this is interactive" affordance; the
|
|
3616
|
+
pending/error treatment isn't Attio-measured -- it reuses the same
|
|
3617
|
+
tokens DataTable's identical states already use (opacity 0.5,
|
|
3618
|
+
`bgDanger`), per #385/#430. */
|
|
3165
3619
|
& .crisp-recordpage-edit { display: block; width: 100%; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; box-shadow: none; outline: none; font: inherit; color: inherit; }
|
|
3166
|
-
/* not Attio-measured (its own field shows no focus ring either, caret
|
|
3620
|
+
/* not Attio-measured (its own field shows no focus ring either, caret
|
|
3621
|
+
only) -- kept for real keyboard users, the same brand ring every
|
|
3622
|
+
other crisp field already shows on focus (DataTable's identical
|
|
3167
3623
|
.crisp-datatable-edit:focus, e.g.). */
|
|
3168
3624
|
& .crisp-recordpage-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
3169
3625
|
& .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
3170
3626
|
& .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
3171
3627
|
& .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); }
|
|
3172
|
-
/* #457: an `editor: "select"` field's at-rest chip -- same shape as
|
|
3628
|
+
/* #457: an `editor: "select"` field's at-rest chip -- same shape as
|
|
3629
|
+
RecordsTable's own `.crisp-recordstable-status[-dot]` (already
|
|
3173
3630
|
measured against Attio there), but its own classes: that pair is
|
|
3174
|
-
scoped under `.crisp-recordstable`'s own recipe root, so reusing the
|
|
3631
|
+
scoped under `.crisp-recordstable`'s own recipe root, so reusing the
|
|
3632
|
+
classnames verbatim here would resolve to nothing. */
|
|
3175
3633
|
& .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
3176
3634
|
& .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
|
|
3177
3635
|
& .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
|
|
@@ -3194,7 +3652,6 @@
|
|
|
3194
3652
|
& .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); }
|
|
3195
3653
|
& .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); }
|
|
3196
3654
|
& .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
|
|
3197
|
-
|
|
3198
3655
|
& .crisp-recordpage-feed { display: flex; flex-direction: column; }
|
|
3199
3656
|
& .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
|
|
3200
3657
|
& .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); }
|
|
@@ -3203,7 +3660,6 @@
|
|
|
3203
3660
|
& .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
|
|
3204
3661
|
& .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; }
|
|
3205
3662
|
& .crisp-recordpage-feed-more:hover { text-decoration: underline; }
|
|
3206
|
-
|
|
3207
3663
|
& .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
|
|
3208
3664
|
& .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
|
|
3209
3665
|
& .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); }
|
|
@@ -3211,7 +3667,6 @@
|
|
|
3211
3667
|
& .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; }
|
|
3212
3668
|
& .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
|
|
3213
3669
|
& .crisp-recordpage-addbtn svg { flex-shrink: 0; }
|
|
3214
|
-
|
|
3215
3670
|
& .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); }
|
|
3216
3671
|
& .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); }
|
|
3217
3672
|
& .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
|
|
@@ -3221,23 +3676,52 @@
|
|
|
3221
3676
|
& .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
|
|
3222
3677
|
& .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
|
|
3223
3678
|
& .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3679
|
+
/* #871: one bordered card per note (border-radius.xl, borderSubtle),
|
|
3680
|
+
not a flush divider-list row -- measured live on a real populated
|
|
3681
|
+
note: the whole row is flex space-between, avatar+title+body on the
|
|
3682
|
+
left (its own flex, gap.2), the relative time alone on the right.
|
|
3683
|
+
The real DOM nests an inner clickable button (padding 6/8, radius.md)
|
|
3684
|
+
inside an outer card (padding 4px, radius.xl) -- collapsed into this
|
|
3685
|
+
one non-interactive div's own combined padding (2.5/3) since crisp's
|
|
3686
|
+
NotesSection has no click-to-open behaviour to justify the extra
|
|
3687
|
+
layer. The 6px gap between stacked cards is NOT independently
|
|
3688
|
+
measured (this workspace only ever had one real note to check) --
|
|
3689
|
+
a judgement call off the existing space scale, not a live value. */
|
|
3690
|
+
& .crisp-recordpage-note { display: flex; align-items: center; justify-content: space-between; gap: var(--crisp-space-3); padding: var(--crisp-space-2-5) var(--crisp-space-3); border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-xl); }
|
|
3691
|
+
& .crisp-recordpage-note + .crisp-recordpage-note { margin-top: var(--crisp-space-1-5); }
|
|
3692
|
+
& .crisp-recordpage-note-left { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; }
|
|
3693
|
+
& .crisp-recordpage-note-title { flex-shrink: 0; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
3694
|
+
& .crisp-recordpage-note-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
3695
|
+
& .crisp-recordpage-note-time { flex-shrink: 0; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 50%, transparent); }
|
|
3232
3696
|
& .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); }
|
|
3233
3697
|
& .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
|
|
3234
3698
|
& .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
|
|
3235
|
-
|
|
3236
3699
|
& .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; }
|
|
3237
3700
|
& .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
|
|
3238
|
-
|
|
3701
|
+
/* #622: the Activity tab's own toolbar -- "Filters" + "+ Add meeting",
|
|
3702
|
+
both the same measured button chrome as the topbar's own action
|
|
3703
|
+
buttons (28px, e.field shadow, 14/500 label). */
|
|
3704
|
+
& .crisp-recordpage-tabtoolbar { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); }
|
|
3705
|
+
/* #622: Files tab's empty state -- measured live on Attio's own record
|
|
3706
|
+
page (a company with no files uploaded). The 138x138 dotted-grid
|
|
3707
|
+
backdrop is the same measured tile EmptyState's records variant uses
|
|
3708
|
+
(crisp/#603), duplicated here rather than composed through that
|
|
3709
|
+
component because this surface's title (16/600) and body (14/500,
|
|
3710
|
+
63%-mixed fgPrimary, not the flat fgMuted EmptyState uses) measure to
|
|
3711
|
+
their own values, matching neither of that component's existing
|
|
3712
|
+
variants. */
|
|
3713
|
+
& .crisp-recordpage-panel--center { flex: 1; align-items: center; justify-content: center; }
|
|
3714
|
+
& .crisp-recordpage-illustrated { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); text-align: center; }
|
|
3715
|
+
& .crisp-recordpage-illustrated-icon { display: flex; align-items: center; justify-content: center; width: 138px; height: 138px; margin-bottom: var(--crisp-space-2); color: color-mix(in srgb, var(--crisp-fg-primary) 22%, transparent); background: radial-gradient(circle, color-mix(in srgb, var(--crisp-fg-primary) 12%, transparent) 1.2px, transparent 1.2px) 0 0 / 16px 16px; }
|
|
3716
|
+
& .crisp-recordpage-illustrated-title { font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
3717
|
+
/* #988: the Calls tab's own gated state measures a larger 20/24 title
|
|
3718
|
+
than Files/Deals' 16/600 -- Attio's own "empty view" pattern (the
|
|
3719
|
+
same 20/600 EmptyState's page/records variants already carry, not a
|
|
3720
|
+
one-off). */
|
|
3721
|
+
& .crisp-recordpage-illustrated-title--lg { font-size: 20px; line-height: 24px; }
|
|
3722
|
+
& .crisp-recordpage-illustrated-desc { max-width: 320px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
3723
|
+
& .crisp-recordpage-illustrated-actions { display: inline-flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--crisp-space-1-5); margin-top: var(--crisp-space-2); }
|
|
3239
3724
|
& .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
|
|
3240
|
-
|
|
3241
3725
|
& .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); }
|
|
3242
3726
|
& .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)); }
|
|
3243
3727
|
& .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)); }
|
|
@@ -3266,11 +3750,14 @@
|
|
|
3266
3750
|
beneath (the same borderSubtle every other panel/row edge here
|
|
3267
3751
|
already uses). Close keeps the existing transparent ghost button;
|
|
3268
3752
|
Previous/Next/Open record are a distinct field-elevation style
|
|
3269
|
-
(white fill, e.field's own ring+shadow, solid icon) -- measured as
|
|
3753
|
+
(white fill, e.field's own ring+shadow, solid icon) -- measured as
|
|
3754
|
+
genuinely different chrome from Close, not a reuse. */
|
|
3270
3755
|
& .crisp-recordpanel-toolbar { display: flex; align-items: center; height: 49px; flex-shrink: 0; padding: var(--crisp-space-2) var(--crisp-space-2-5); border-bottom: 1px solid var(--crisp-border-subtle); }
|
|
3271
3756
|
& .crisp-recordpanel-toolbar-spacer { flex: 1; }
|
|
3272
3757
|
& .crisp-recordpanel-pager { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: var(--crisp-space-3); }
|
|
3273
|
-
/* #413: "2 of 37 in All Companies" -- measured live, same toolbar row,
|
|
3758
|
+
/* #413: "2 of 37 in All Companies" -- measured live, same toolbar row,
|
|
3759
|
+
right after Prev/Next. 12px/500, the same 63%-of-fgPrimary mix every
|
|
3760
|
+
other muted heading in this panel already uses. */
|
|
3274
3761
|
& .crisp-recordpanel-counter { margin-inline-start: var(--crisp-space-3); font-size: 12px; font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3275
3762
|
& .crisp-recordpanel-iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; cursor: pointer; transition: background-color .12s; }
|
|
3276
3763
|
& .crisp-recordpanel-iconbtn:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
@@ -3278,26 +3765,36 @@
|
|
|
3278
3765
|
& .crisp-recordpanel-navbtn:hover:not(:disabled) { background: var(--crisp-bg-raised); }
|
|
3279
3766
|
& .crisp-recordpanel-navbtn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
3280
3767
|
/* #413: measured live -- a 10px strip at the panel's own left edge,
|
|
3281
|
-
cursor: col-resize (the issue's own repro calls it "ew-resize";
|
|
3282
|
-
|
|
3768
|
+
cursor: col-resize (the issue's own repro calls it "ew-resize";
|
|
3769
|
+
the actual computed value read off the live DOM is col-resize, the
|
|
3770
|
+
same cursor family under a different keyword). Kept fully inside the
|
|
3771
|
+
panel's own box, not extending past inset-inline-start: 0, so the
|
|
3772
|
+
panel's own overflow: hidden (there for its rounded corners) never
|
|
3773
|
+
clips it. touch-action: none stops a touchscreen's own pan gesture
|
|
3283
3774
|
from fighting the drag. */
|
|
3284
3775
|
& .crisp-recordpanel-resize-handle { position: absolute; top: 0; bottom: 0; inset-inline-start: 0; width: 10px; cursor: col-resize; z-index: 1; touch-action: none; }
|
|
3285
3776
|
& .crisp-recordpanel-resize-handle:hover, & .crisp-recordpanel-resize-handle:active { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
|
|
3286
|
-
|
|
3287
3777
|
& .crisp-recordpanel-header { display: flex; align-items: center; gap: var(--crisp-space-2); height: 52px; flex-shrink: 0; padding: 0 var(--crisp-space-3); }
|
|
3288
3778
|
& .crisp-recordpanel-fav { width: 22px; height: var(--crisp-size-chip); border-radius: var(--crisp-radius-sm); flex-shrink: 0; object-fit: cover; background: var(--crisp-bg-raised); }
|
|
3289
3779
|
& .crisp-recordpanel-title { flex: 1; min-width: 0; font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; color: var(--crisp-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3290
|
-
|
|
3291
3780
|
& .crisp-recordpanel-body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--crisp-space-2) var(--crisp-space-3); }
|
|
3292
|
-
|
|
3293
|
-
|
|
3781
|
+
/* #448: measured live on app.attio.com's peek (hover a Companies row,
|
|
3782
|
+
click "Open preview"). Section label reads identically for both
|
|
3783
|
+
Highlights and Activity: 14px/500, the same 63%-of-fgPrimary mix
|
|
3784
|
+
RecordPage's own field-label already uses (product/recordpage's
|
|
3785
|
+
.crisp-recordpage-field-label) -- one more surface landing on the
|
|
3786
|
+
same measured "muted section heading" colour. */
|
|
3294
3787
|
& .crisp-recordpanel-section { padding: var(--crisp-space-2) var(--crisp-space-1) 0; }
|
|
3295
3788
|
& .crisp-recordpanel-section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--crisp-space-2); height: 20px; margin-bottom: var(--crisp-space-2); }
|
|
3296
3789
|
& .crisp-recordpanel-section-label { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
3297
|
-
/* "View all" -- measured 10px/400, a lighter mix than the section label
|
|
3790
|
+
/* "View all" -- measured 10px/400, a lighter mix than the section label
|
|
3791
|
+
(55%, not 63%) -- its own distinct, honestly-measured value, not a
|
|
3792
|
+
reuse of a nearby one that happened to be close. */
|
|
3298
3793
|
& .crisp-recordpanel-section-action { border: none; background: none; padding: 0; font-family: inherit; font-size: 10px; font-weight: var(--crisp-weight-regular); color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); cursor: pointer; }
|
|
3299
3794
|
& .crisp-recordpanel-section-action:hover { color: var(--crisp-fg-primary); }
|
|
3300
|
-
/* Highlights: a 2-column grid of label+icon+value cards, no card
|
|
3795
|
+
/* Highlights: a 2-column grid of label+icon+value cards, no card
|
|
3796
|
+
chrome at all (no border/background/radius/shadow -- confirmed on
|
|
3797
|
+
the live DOM: every highlight's computed style is fully transparent).
|
|
3301
3798
|
8px row/column gap; two rows measured "233x86" inside 473px content
|
|
3302
3799
|
width is exactly (473 - 8) / 2. */
|
|
3303
3800
|
& .crisp-recordpanel-highlights { display: grid; grid-template-columns: 1fr 1fr; gap: var(--crisp-space-2); }
|
|
@@ -3306,27 +3803,33 @@
|
|
|
3306
3803
|
& .crisp-recordpanel-highlight-label span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3307
3804
|
& .crisp-recordpanel-highlight-label svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
3308
3805
|
& .crisp-recordpanel-highlight-value { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); overflow: hidden; text-overflow: ellipsis; }
|
|
3309
|
-
|
|
3310
3806
|
/* Activity is a consumer-supplied slot (crisp has no activity-feed
|
|
3311
3807
|
model of its own to render) -- this only wraps it with the measured
|
|
3312
3808
|
section heading above. */
|
|
3313
3809
|
& .crisp-recordpanel-activity { font-size: var(--crisp-text-lg); }
|
|
3314
|
-
|
|
3315
3810
|
/* #413: collapsed Emails/Notes/Tasks below Activity -- measured live: a
|
|
3316
|
-
473px-wide row (the panel's own content width, 497 minus its 12px/8px
|
|
3317
|
-
|
|
3811
|
+
473px-wide row (the panel's own content width, 497 minus its 12px/8px
|
|
3812
|
+
side insets), 20px tall, 14px/500 solid fgPrimary label (NOT the 63%
|
|
3813
|
+
mix Highlights/Activity headings use -- this is body text, not a
|
|
3814
|
+
muted heading), a trailing count. padding "0 8px 0 12px" measured on
|
|
3815
|
+
the row itself; reproduced here as the trigger's own padding, since
|
|
3816
|
+
the trigger IS the row (a plain div, not a button, when there's no
|
|
3817
|
+
content to expand into -- matches the empty ("Emails 0") row
|
|
3818
|
+
measured live, which has no expand affordance at all). */
|
|
3318
3819
|
& .crisp-recordpanel-sections { display: flex; flex-direction: column; padding-top: var(--crisp-space-2); }
|
|
3319
3820
|
& .crisp-recordpanel-section-trigger { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; height: 20px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-3); border: none; background: none; font-family: inherit; text-align: start; cursor: pointer; }
|
|
3320
3821
|
& .crisp-recordpanel-section-trigger-inert { cursor: default; }
|
|
3321
3822
|
& .crisp-recordpanel-section-row-label { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
3322
3823
|
/* The count wasn't captured with its own background/pill chrome in the
|
|
3323
3824
|
live measurement (only its text: 14px, a "tertiary" internal variant
|
|
3324
|
-
name that doesn't map to anything crisp defines) -- muted text next
|
|
3825
|
+
name that doesn't map to anything crisp defines) -- muted text next
|
|
3826
|
+
to the label, not an invented badge shape. */
|
|
3325
3827
|
& .crisp-recordpanel-section-row-count { font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); }
|
|
3326
3828
|
& .crisp-recordpanel-section-chevron { margin-inline-start: auto; flex-shrink: 0; color: var(--crisp-fg-muted); transition: transform .15s ease; }
|
|
3327
3829
|
& .crisp-recordpanel-section-chevron[data-open] { transform: rotate(180deg); }
|
|
3328
3830
|
& .crisp-recordpanel-section-content { padding: var(--crisp-space-2) var(--crisp-space-2) var(--crisp-space-2) var(--crisp-space-3); }
|
|
3329
|
-
/* #329: an optional slot for record actions (e.g. Edit). Reuses the
|
|
3831
|
+
/* #329: an optional slot for record actions (e.g. Edit). Reuses the
|
|
3832
|
+
header's own measured values rather than inventing new ones -- the
|
|
3330
3833
|
same horizontal inset (space.3), the same hairline border token
|
|
3331
3834
|
(borderSubtle, flipped to border-top since this sits at the opposite
|
|
3332
3835
|
edge), and the header/body gap (space.2) for its own vertical padding
|
|
@@ -3354,13 +3857,28 @@
|
|
|
3354
3857
|
& .crisp-rte-body h1 { font-size: var(--crisp-text-xl); line-height: 28px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.3px; margin-top: var(--crisp-space-4); }
|
|
3355
3858
|
& .crisp-rte-body h2 { font-size: 17px; line-height: 24px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; margin-top: var(--crisp-space-3); }
|
|
3356
3859
|
& .crisp-rte-body h3 { font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-semibold); margin-top: var(--crisp-space-2-5); }
|
|
3357
|
-
/* #575: a consumer's CSS reset (e.g. Tailwind preflight's un-scoped
|
|
3358
|
-
|
|
3860
|
+
/* #575: a consumer's CSS reset (e.g. Tailwind preflight's un-scoped
|
|
3861
|
+
ul, ol { list-style: none }, specificity 0,0,1) was winning every
|
|
3862
|
+
list marker outright -- this rule set padding but never declared
|
|
3863
|
+
list-style-type, so there was no higher-specificity value (this
|
|
3864
|
+
selector is 0,1,1) to beat the reset with. Split into two
|
|
3865
|
+
single-selector rules, each declaring its own marker type, rather
|
|
3866
|
+
than the old single comma-joined rule ( .crisp-rte-body ul, &
|
|
3867
|
+
.crisp-rte-body ol ) the issue flagged as malformed.
|
|
3868
|
+
#611: padding-inline-start re-measured live once CRUD on the
|
|
3869
|
+
measurement workspace was allowed (a "zz-parity" note with a
|
|
3870
|
+
bulleted list, a nested bulleted list, and a numbered list) --
|
|
3871
|
+
Attio's own <ul>/<ol> measures 36px (getComputedStyle,
|
|
3359
3872
|
~36.1353px), not the 20px placeholder #575 shipped with no real
|
|
3360
|
-
content to check against. 36px isn't in tokens/scale.ts (steps
|
|
3873
|
+
content to check against. 36px isn't in tokens/scale.ts (steps
|
|
3874
|
+
stop at 24px, jump to 32px) and is a single component-intrinsic
|
|
3875
|
+
value, so it stays a raw px per AUTHORING.md's golden rule 4b
|
|
3361
3876
|
rather than being rounded to an existing token or added to the
|
|
3362
3877
|
shared scale. Marker colour (currentColor via the already-measured
|
|
3363
|
-
fgPrimary, confirmed to equal Attio's measured rgb(16,17,18) ==
|
|
3878
|
+
fgPrimary, confirmed to equal Attio's measured rgb(16,17,18) ==
|
|
3879
|
+
#101112 exactly) and the ~4px li-to-li gap (the existing li
|
|
3880
|
+
margin-top rule below) were re-checked at the same time and
|
|
3881
|
+
already matched -- only the padding was wrong. Attio doesn't vary
|
|
3364
3882
|
marker type for a nested list either (nested <ul> is disc too,
|
|
3365
3883
|
not circle), which this already doesn't attempt. */
|
|
3366
3884
|
& .crisp-rte-body ul { list-style-type: disc; padding-inline-start: 36px; }
|
|
@@ -3371,10 +3889,13 @@
|
|
|
3371
3889
|
& .crisp-rte-body a { color: var(--crisp-bg-brand-solid); text-decoration: underline; text-underline-offset: 2px; }
|
|
3372
3890
|
& .crisp-rte-body strong { font-weight: var(--crisp-weight-semibold); }
|
|
3373
3891
|
& .crisp-rte-body img { display: block; max-width: 100%; border-radius: var(--crisp-radius-md); }
|
|
3374
|
-
/* Not measured against Attio (#428) — nothing in a read-only pass over
|
|
3892
|
+
/* Not measured against Attio (#428) — nothing in a read-only pass over
|
|
3893
|
+
app.attio.com had a live @mention rendered to read computed styles
|
|
3894
|
+
from, and typing one to create one is off-limits there. Reused
|
|
3895
|
+
verbatim from the one measured "brand" tag/chip this repo already
|
|
3896
|
+
has (RecordsTable/MultiSelect's [data-tone="brand"]) rather than
|
|
3375
3897
|
inventing a new color or shape. */
|
|
3376
3898
|
& .crisp-rte-mention { display: inline; border-radius: var(--crisp-radius-chip); padding: 0 var(--crisp-space-1); 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)); font-weight: var(--crisp-weight-medium); cursor: default; }
|
|
3377
|
-
|
|
3378
3899
|
& .crisp-rte-toolbar { position: fixed; z-index: 70; display: inline-flex; align-items: center; gap: 2px; padding: 2px; border-radius: 10px; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: translate(-50%, -100%); opacity: 1; transition: opacity 0.1s ease; }
|
|
3379
3900
|
& .crisp-rte-toolbar { @starting-style { opacity: 0; } }
|
|
3380
3901
|
& .crisp-rte-tool { display: inline-flex; align-items: center; justify-content: center; gap: var(--crisp-space-1); min-width: 30px; height: 28px; padding: 0 7px; margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); cursor: pointer; transition: background-color .1s; }
|
|
@@ -3382,13 +3903,11 @@
|
|
|
3382
3903
|
& .crisp-rte-tool:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
|
|
3383
3904
|
& .crisp-rte-tool[data-active], & .crisp-rte-tool[aria-expanded="true"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 12%, transparent); color: var(--crisp-bg-brand-solid); }
|
|
3384
3905
|
& .crisp-rte-tool-sep { width: 1px; height: 16px; margin: 0 2px; background: var(--crisp-border-subtle); }
|
|
3385
|
-
|
|
3386
3906
|
& .crisp-rte-swatchpanel { position: fixed; z-index: 71; display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--crisp-space-1); width: 168px; padding: var(--crisp-space-1-5); border-radius: var(--crisp-radius-lg); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: translate(-50%, var(--crisp-space-1-5)); opacity: 1; transition: opacity 0.1s ease; }
|
|
3387
3907
|
& .crisp-rte-swatchpanel { @starting-style { opacity: 0; } }
|
|
3388
3908
|
& .crisp-rte-swatch { width: 28px; height: 28px; padding: 0; margin: 0; border: none; border-radius: 50%; background: none; font-family: inherit; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); cursor: pointer; }
|
|
3389
3909
|
& .crisp-rte-swatch--none { background: var(--crisp-bg-surface); position: relative; }
|
|
3390
3910
|
& .crisp-rte-swatch--none::after { content: ""; position: absolute; inset: 6px; border-top: 1.5px solid color-mix(in srgb, var(--crisp-fg-primary) 40%, transparent); transform: rotate(-45deg); }
|
|
3391
|
-
|
|
3392
3911
|
& .crisp-rte-blockmenu { position: fixed; z-index: 71; box-sizing: border-box; width: 356px; padding: 0; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transition: opacity 0.1s ease; }
|
|
3393
3912
|
& .crisp-rte-blockmenu { @starting-style { opacity: 0; } }
|
|
3394
3913
|
& .crisp-rte-blockmenu-search { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-2-5) var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
@@ -3488,9 +4007,16 @@
|
|
|
3488
4007
|
|
|
3489
4008
|
.crisp-savedviews {
|
|
3490
4009
|
position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; /* crisp/#772 follow-up, re-measured live 2026-09-25 in the trigger's
|
|
3491
|
-
actual position (Attio's real view bar, next to View settings --
|
|
4010
|
+
actual position (Attio's real view bar, next to View settings --
|
|
4011
|
+
fixed there in #766/#768/#778): white (bgSurface, rgb(255,255,255)
|
|
4012
|
+
exact) with elevation.field's 3-layer shadow, the same raised
|
|
3492
4013
|
chrome View settings and Import/Export both carry
|
|
3493
|
-
(tabletoolbar.recipe.ts's own --raised, not reused here directly
|
|
4014
|
+
(tabletoolbar.recipe.ts's own --raised, not reused here directly
|
|
4015
|
+
since this is a separate recipe/component, but the identical measured
|
|
4016
|
+
values). Supersedes the original #555 measurement (rgb(246,247,247),
|
|
4017
|
+
reused as bgRaised -- a flat grey fill with no shadow at all), which
|
|
4018
|
+
was wrong: this trigger was never re-checked once it moved into its
|
|
4019
|
+
real view-bar position. */
|
|
3494
4020
|
& .crisp-savedviews-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: var(--crisp-space-1) var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); cursor: pointer; white-space: nowrap; transition: background-color .12s ease; }
|
|
3495
4021
|
& .crisp-savedviews-trigger:hover, & .crisp-savedviews-trigger[data-open] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
|
|
3496
4022
|
& .crisp-savedviews-trigger-icon { flex-shrink: 0; display: inline-flex; width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
|
|
@@ -3523,14 +4049,14 @@
|
|
|
3523
4049
|
& .crisp-settingsshell-back svg { color: var(--crisp-fg-muted); }
|
|
3524
4050
|
& .crisp-settingsshell-back:hover svg { color: var(--crisp-fg-primary); }
|
|
3525
4051
|
& .crisp-settingsshell-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 32px; margin-bottom: var(--crisp-space-2); padding: 0 var(--crisp-space-2-5); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-muted); }
|
|
3526
|
-
/* The field box owns the ring, so focus has to move it -- the inner
|
|
4052
|
+
/* The field box owns the ring, so focus has to move it -- the inner
|
|
4053
|
+
input kills its own outline. Measured live: a focused field's
|
|
3527
4054
|
input carries box-shadow: none while its wrapper carries
|
|
3528
4055
|
inset 0 0 0 1px #266df0. */
|
|
3529
4056
|
& .crisp-settingsshell-search:focus-within { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
3530
4057
|
& .crisp-settingsshell-search svg { flex-shrink: 0; }
|
|
3531
4058
|
& .crisp-settingsshell-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
|
|
3532
4059
|
& .crisp-settingsshell-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
3533
|
-
|
|
3534
4060
|
& .crisp-settingsshell-groups { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--crisp-space-2-5); }
|
|
3535
4061
|
& .crisp-settingsshell-group { display: flex; flex-direction: column; gap: 1px; }
|
|
3536
4062
|
& .crisp-settingsshell-group-label { padding: var(--crisp-space-1) var(--crisp-space-2); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
@@ -3541,7 +4067,6 @@
|
|
|
3541
4067
|
& .crisp-settingsshell-item[data-active] { background: var(--crisp-bg-raised); font-weight: var(--crisp-weight-medium); }
|
|
3542
4068
|
& .crisp-settingsshell-item[data-active] svg { color: var(--crisp-fg-primary); }
|
|
3543
4069
|
& .crisp-settingsshell-empty { padding: var(--crisp-space-3) var(--crisp-space-2); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
3544
|
-
|
|
3545
4070
|
& .crisp-settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: var(--crisp-space-6) var(--crisp-space-8); }
|
|
3546
4071
|
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
3547
4072
|
}
|
|
@@ -3649,7 +4174,8 @@
|
|
|
3649
4174
|
& [data-swatch="light"] .crisp-themepicker-preview-bar:not(:nth-child(1)), & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #eeeff1; }
|
|
3650
4175
|
& [data-swatch="light"] .crisp-themepicker-preview-main, & [data-swatch="system"] .crisp-themepicker-preview-main { background: #ffffff; }
|
|
3651
4176
|
& [data-swatch="light"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar, & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #eeeff1; }
|
|
3652
|
-
/* Dark swatch colours -- always for "dark", and for "system" only
|
|
4177
|
+
/* Dark swatch colours -- always for "dark", and for "system" only
|
|
4178
|
+
when the OS itself reports dark. */
|
|
3653
4179
|
& .crisp-themepicker-preview[data-swatch="dark"] { border: 1px solid #1c1d1f; background: #0e0f10; }
|
|
3654
4180
|
& [data-swatch="dark"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; }
|
|
3655
4181
|
& [data-swatch="dark"] .crisp-themepicker-preview-main { background: #0a0a0a; }
|
|
@@ -3694,4 +4220,35 @@
|
|
|
3694
4220
|
transition-duration: 0.01ms !important;
|
|
3695
4221
|
}
|
|
3696
4222
|
}
|
|
4223
|
+
|
|
4224
|
+
.crisp-workspacegeneralsettings {
|
|
4225
|
+
& .crisp-workspacegeneralsettings-page { display: flex; flex-direction: column; gap: var(--crisp-space-6); font-family: var(--crisp-font-sans); }
|
|
4226
|
+
& .crisp-workspacegeneralsettings-heading { display: flex; flex-direction: column; gap: var(--crisp-space-0-5); }
|
|
4227
|
+
& .crisp-workspacegeneralsettings-title { font-size: 24px; line-height: 28px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.48px; color: var(--crisp-fg-primary); margin: 0; }
|
|
4228
|
+
& .crisp-workspacegeneralsettings-desc { font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-muted); margin: 0; }
|
|
4229
|
+
& .crisp-workspacegeneralsettings-section { display: flex; flex-direction: column; gap: var(--crisp-space-4); }
|
|
4230
|
+
& .crisp-workspacegeneralsettings-sectiontitle { font-size: 16px; line-height: 20px; font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); margin: 0; }
|
|
4231
|
+
& .crisp-workspacegeneralsettings-sectionhead { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--crisp-space-4); }
|
|
4232
|
+
& .crisp-workspacegeneralsettings-sectionhead-text { display: flex; flex-direction: column; gap: var(--crisp-space-1); }
|
|
4233
|
+
/* Logo row: a tile + helper text + "Upload logo" button. */
|
|
4234
|
+
& .crisp-workspacegeneralsettings-logorow { display: flex; align-items: center; gap: var(--crisp-space-4); }
|
|
4235
|
+
& .crisp-workspacegeneralsettings-logohelp { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
4236
|
+
& .crisp-workspacegeneralsettings-logotext { display: flex; flex-direction: column; align-items: flex-start; gap: var(--crisp-space-1); }
|
|
4237
|
+
/* Name + Slug sit side by side, each ~half the content width. */
|
|
4238
|
+
& .crisp-workspacegeneralsettings-fieldrow { display: flex; gap: var(--crisp-space-4); }
|
|
4239
|
+
& .crisp-workspacegeneralsettings-fieldrow > * { flex: 1; min-width: 0; }
|
|
4240
|
+
& .crisp-workspacegeneralsettings-slugfield { display: flex; align-items: center; gap: var(--crisp-space-1-5); }
|
|
4241
|
+
& .crisp-workspacegeneralsettings-slugfield > :first-child { flex: 1; min-width: 0; }
|
|
4242
|
+
& .crisp-workspacegeneralsettings-copybtn { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 32px; height: 32px; border: none; border-radius: var(--crisp-radius-md); background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: pointer; }
|
|
4243
|
+
& .crisp-workspacegeneralsettings-copybtn:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
4244
|
+
/* Export-data empty state -- measured: 14/500/63%-opacity, centred in a
|
|
4245
|
+
40px row, no border of its own (the Table wrapper already draws it). */
|
|
4246
|
+
& .crisp-workspacegeneralsettings-emptyrow { padding: var(--crisp-space-2-5) var(--crisp-space-4); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); text-align: center; }
|
|
4247
|
+
/* Danger zone: a red-tinted bordered row, distinct from every other
|
|
4248
|
+
card on the page. */
|
|
4249
|
+
& .crisp-workspacegeneralsettings-dangerrow { display: flex; align-items: center; justify-content: space-between; gap: var(--crisp-space-6); padding: var(--crisp-space-3) var(--crisp-space-4); border: 1px solid color-mix(in srgb, var(--crisp-bg-danger) 30%, transparent); border-radius: 12px; background: color-mix(in srgb, var(--crisp-bg-danger) 6%, transparent); }
|
|
4250
|
+
& .crisp-workspacegeneralsettings-dangertext { display: flex; flex-direction: column; gap: var(--crisp-space-1); }
|
|
4251
|
+
& .crisp-workspacegeneralsettings-rowtitle { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
4252
|
+
& .crisp-workspacegeneralsettings-dangerwarning { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
4253
|
+
}
|
|
3697
4254
|
}
|