@crisp-ui-kit/crisp 0.57.1 → 0.57.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +7 -6
- package/dist/button.layered.css +7 -6
- package/dist/checkbox.css +7 -3
- package/dist/checkbox.layered.css +7 -3
- package/dist/chip.css +15 -0
- package/dist/chip.d.ts +3 -1
- package/dist/chip.layered.css +15 -0
- 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/button/button.recipe.js +39 -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 +69 -1
- 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 +11 -2
- 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.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/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/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/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/recordpage.js +57 -6
- package/dist/cjs/product/recordpage/recordpage.recipe.js +43 -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 +161 -67
- package/dist/datatable.layered.css +161 -67
- package/dist/datepicker.css +13 -41
- package/dist/datepicker.layered.css +13 -41
- package/dist/datepickerfield.css +4 -1
- package/dist/datepickerfield.layered.css +4 -1
- 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/button/button.recipe.js +40 -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 +69 -1
- 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 +11 -2
- 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.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/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/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/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/recordpage.js +58 -7
- package/dist/esm/product/recordpage/recordpage.recipe.js +43 -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 +67 -23
- package/dist/recordpage.layered.css +67 -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 +859 -345
- package/dist/styles.layered.css +859 -345
- package/dist/table.css +28 -10
- package/dist/table.layered.css +28 -10
- 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/button/button.recipe.d.ts +11 -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 +48 -0
- 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/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/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/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/recordpage.d.ts +53 -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/datepickerfield.css
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
& .crisp-datepickerfield-box[data-placeholder] .crisp-datepickerfield-trigger { color: var(--crisp-fg-muted); }
|
|
8
8
|
& .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
9
9
|
/* Reuses TableToolbar's measured filter-chip remove button
|
|
10
|
-
(tabletoolbar.chrome.ts's .crisp-tabletoolbar-fchip-x) -- the same
|
|
10
|
+
(tabletoolbar.chrome.ts's .crisp-tabletoolbar-fchip-x) -- the same
|
|
11
|
+
small inline "clear this value" affordance, not a freshly-measured
|
|
12
|
+
one: no live Attio composition for a DatePickerField-equivalent
|
|
13
|
+
clear was reachable this round (#394). */
|
|
11
14
|
& .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; }
|
|
12
15
|
& .crisp-datepickerfield-clear:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
|
|
13
16
|
& .crisp-datepickerfield-panel { padding: var(--crisp-space-2); width: 300px; }
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
& .crisp-datepickerfield-box[data-placeholder] .crisp-datepickerfield-trigger { color: var(--crisp-fg-muted); }
|
|
9
9
|
& .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
10
10
|
/* Reuses TableToolbar's measured filter-chip remove button
|
|
11
|
-
(tabletoolbar.chrome.ts's .crisp-tabletoolbar-fchip-x) -- the same
|
|
11
|
+
(tabletoolbar.chrome.ts's .crisp-tabletoolbar-fchip-x) -- the same
|
|
12
|
+
small inline "clear this value" affordance, not a freshly-measured
|
|
13
|
+
one: no live Attio composition for a DatePickerField-equivalent
|
|
14
|
+
clear was reachable this round (#394). */
|
|
12
15
|
& .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; }
|
|
13
16
|
& .crisp-datepickerfield-clear:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
|
|
14
17
|
& .crisp-datepickerfield-panel { padding: var(--crisp-space-2); width: 300px; }
|
package/dist/dialog.css
CHANGED
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
& .crisp-dialog-backdrop { position: fixed; inset: 0; z-index: 60; background: var(--crisp-bg-scrim); }
|
|
4
4
|
& .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); }
|
|
5
5
|
& .crisp-dialog-positioner[data-variant="alert"] { align-items: center; padding: var(--crisp-space-4); }
|
|
6
|
-
& .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;
|
|
7
|
-
& .crisp-dialog-
|
|
8
|
-
& .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; }
|
|
9
|
-
& .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); }
|
|
6
|
+
& .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); } }
|
|
7
|
+
& .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; }
|
|
10
8
|
& .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); }
|
|
11
9
|
& .crisp-dialog-header svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
12
10
|
& .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; }
|
|
@@ -15,8 +13,10 @@
|
|
|
15
13
|
/* The discard-confirm's own stacked title + sentence (crisp#677) — no
|
|
16
14
|
border, no close button, unlike the panel header above: measured
|
|
17
15
|
live, both themes, 18px/24px 600-weight title (no scale token
|
|
18
|
-
reaches 18px — the scale tops out at text.xl's 16px, so this is raw
|
|
19
|
-
|
|
16
|
+
reaches 18px — the scale tops out at text.xl's 16px, so this is raw
|
|
17
|
+
px per Golden Rule 3's "genuinely intrinsic size" exception, same as
|
|
18
|
+
this file's own submit-key glyphs) then a 14px/20px 500-weight
|
|
19
|
+
sentence 4px below it. */
|
|
20
20
|
& .crisp-dialog-alert-header { display: flex; flex-direction: column; gap: var(--crisp-space-1); padding: var(--crisp-space-4) var(--crisp-space-4) 0; }
|
|
21
21
|
& .crisp-dialog-alert-title { margin: 0; font-size: 18px; line-height: 24px; font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
22
22
|
& .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); }
|
|
@@ -26,7 +26,12 @@
|
|
|
26
26
|
& .crisp-dialog-field { display: flex; flex-direction: column; gap: var(--crisp-space-1-5); }
|
|
27
27
|
& .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); }
|
|
28
28
|
& .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; }
|
|
29
|
-
|
|
29
|
+
/* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
|
|
30
|
+
the accent (#0298d9) only clears 3.23:1 with white; the darker
|
|
31
|
+
sibling clears 4.5:1+, same fix already applied to Button/Badge/
|
|
32
|
+
Avatar (#897). Scoped to this one fill only -- Dialog's own frosted-
|
|
33
|
+
surface identity (#934) is untouched here. */
|
|
34
|
+
& .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; }
|
|
30
35
|
& .crisp-dialog-submit-key { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
31
36
|
& .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; }
|
|
32
37
|
}
|
package/dist/dialog.layered.css
CHANGED
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
& .crisp-dialog-backdrop { position: fixed; inset: 0; z-index: 60; background: var(--crisp-bg-scrim); }
|
|
5
5
|
& .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); }
|
|
6
6
|
& .crisp-dialog-positioner[data-variant="alert"] { align-items: center; padding: var(--crisp-space-4); }
|
|
7
|
-
& .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;
|
|
8
|
-
& .crisp-dialog-
|
|
9
|
-
& .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; }
|
|
10
|
-
& .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); }
|
|
7
|
+
& .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); } }
|
|
8
|
+
& .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; }
|
|
11
9
|
& .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); }
|
|
12
10
|
& .crisp-dialog-header svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
13
11
|
& .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; }
|
|
@@ -16,8 +14,10 @@
|
|
|
16
14
|
/* The discard-confirm's own stacked title + sentence (crisp#677) — no
|
|
17
15
|
border, no close button, unlike the panel header above: measured
|
|
18
16
|
live, both themes, 18px/24px 600-weight title (no scale token
|
|
19
|
-
reaches 18px — the scale tops out at text.xl's 16px, so this is raw
|
|
20
|
-
|
|
17
|
+
reaches 18px — the scale tops out at text.xl's 16px, so this is raw
|
|
18
|
+
px per Golden Rule 3's "genuinely intrinsic size" exception, same as
|
|
19
|
+
this file's own submit-key glyphs) then a 14px/20px 500-weight
|
|
20
|
+
sentence 4px below it. */
|
|
21
21
|
& .crisp-dialog-alert-header { display: flex; flex-direction: column; gap: var(--crisp-space-1); padding: var(--crisp-space-4) var(--crisp-space-4) 0; }
|
|
22
22
|
& .crisp-dialog-alert-title { margin: 0; font-size: 18px; line-height: 24px; font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
23
23
|
& .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); }
|
|
@@ -27,7 +27,12 @@
|
|
|
27
27
|
& .crisp-dialog-field { display: flex; flex-direction: column; gap: var(--crisp-space-1-5); }
|
|
28
28
|
& .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); }
|
|
29
29
|
& .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; }
|
|
30
|
-
|
|
30
|
+
/* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
|
|
31
|
+
the accent (#0298d9) only clears 3.23:1 with white; the darker
|
|
32
|
+
sibling clears 4.5:1+, same fix already applied to Button/Badge/
|
|
33
|
+
Avatar (#897). Scoped to this one fill only -- Dialog's own frosted-
|
|
34
|
+
surface identity (#934) is untouched here. */
|
|
35
|
+
& .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; }
|
|
31
36
|
& .crisp-dialog-submit-key { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
|
|
32
37
|
& .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; }
|
|
33
38
|
}
|
package/dist/emptystate.css
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
& .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); }
|
|
4
4
|
& .crisp-emptystate-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
5
5
|
& .crisp-emptystate-desc { max-width: 320px; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
6
|
-
/* #603: measured 8px gap between "Import CSV"/"Connect data source" --
|
|
6
|
+
/* #603: measured 8px gap between "Import CSV"/"Connect data source" --
|
|
7
|
+
inline-flex so one action (the common case) or several lay out the
|
|
8
|
+
same way, wrapping if the container is narrow. */
|
|
7
9
|
& .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); }
|
|
8
10
|
/* #603: Attio's zero-records "Learn more" card -- a label above a
|
|
9
11
|
clickable icon+title tile. Left/start-aligned, unlike the rest of
|
|
@@ -23,12 +25,12 @@
|
|
|
23
25
|
.crisp-emptystate--variant_page {
|
|
24
26
|
gap: var(--crisp-space-2);
|
|
25
27
|
& .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); }
|
|
26
|
-
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; }
|
|
28
|
+
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; letter-spacing: var(--crisp-tracking-20); }
|
|
27
29
|
& .crisp-emptystate-desc { max-width: 266px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
28
30
|
& .crisp-emptystate-action { margin-top: var(--crisp-space-2); }
|
|
29
31
|
}
|
|
30
32
|
.crisp-emptystate--variant_records {
|
|
31
33
|
& .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; }
|
|
32
|
-
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; }
|
|
34
|
+
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; letter-spacing: var(--crisp-tracking-20); }
|
|
33
35
|
& .crisp-emptystate-desc { max-width: 266px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
34
36
|
}
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
& .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); }
|
|
5
5
|
& .crisp-emptystate-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); color: var(--crisp-fg-primary); }
|
|
6
6
|
& .crisp-emptystate-desc { max-width: 320px; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
7
|
-
/* #603: measured 8px gap between "Import CSV"/"Connect data source" --
|
|
7
|
+
/* #603: measured 8px gap between "Import CSV"/"Connect data source" --
|
|
8
|
+
inline-flex so one action (the common case) or several lay out the
|
|
9
|
+
same way, wrapping if the container is narrow. */
|
|
8
10
|
& .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); }
|
|
9
11
|
/* #603: Attio's zero-records "Learn more" card -- a label above a
|
|
10
12
|
clickable icon+title tile. Left/start-aligned, unlike the rest of
|
|
@@ -24,13 +26,13 @@
|
|
|
24
26
|
.crisp-emptystate--variant_page {
|
|
25
27
|
gap: var(--crisp-space-2);
|
|
26
28
|
& .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); }
|
|
27
|
-
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; }
|
|
29
|
+
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; letter-spacing: var(--crisp-tracking-20); }
|
|
28
30
|
& .crisp-emptystate-desc { max-width: 266px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
29
31
|
& .crisp-emptystate-action { margin-top: var(--crisp-space-2); }
|
|
30
32
|
}
|
|
31
33
|
.crisp-emptystate--variant_records {
|
|
32
34
|
& .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; }
|
|
33
|
-
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; }
|
|
35
|
+
& .crisp-emptystate-title { font-size: 20px; line-height: 24px; letter-spacing: var(--crisp-tracking-20); }
|
|
34
36
|
& .crisp-emptystate-desc { max-width: 266px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
|
|
35
37
|
}
|
|
36
38
|
}
|
|
@@ -89,7 +89,11 @@ const spec = defineSpec({
|
|
|
89
89
|
paddingInline: c.space["1"],
|
|
90
90
|
fontSize: c.text.sm,
|
|
91
91
|
lineHeight: "16px",
|
|
92
|
-
|
|
92
|
+
// your-moon/crisp#919: seed-design's own Badge (`badge.yaml`)
|
|
93
|
+
// is a small rounded-rect at every size, never a pill -- its
|
|
94
|
+
// small/medium step is `$radius.r1` = 4px (`radius.xs`), not the 6px
|
|
95
|
+
// `radius.sm` this used to share with Chip's old rounded-rect shape.
|
|
96
|
+
borderRadius: c.radius.xs,
|
|
93
97
|
},
|
|
94
98
|
// crisp#696: Attio's tag pill (Standard/System/Enriched) measures
|
|
95
99
|
// 20px h / 4px padding / 12px text / 16px line-height / 3px gap -- was
|
|
@@ -101,14 +105,24 @@ const spec = defineSpec({
|
|
|
101
105
|
fontSize: c.text.sm,
|
|
102
106
|
lineHeight: "16px",
|
|
103
107
|
gap: "3px",
|
|
104
|
-
|
|
108
|
+
// your-moon/crisp#919: same seed radius step as `small`
|
|
109
|
+
// above -- seed's Badge treats small/medium as one radius step
|
|
110
|
+
// (`$radius.r1` = 4px), unlike Button/Input's per-size table.
|
|
111
|
+
borderRadius: c.radius.xs,
|
|
105
112
|
},
|
|
106
113
|
// crisp#805: measured live against Attio's real status/stage chip
|
|
107
|
-
// (Deals "Deal stage" column, All Deals table view) --
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
114
|
+
// (Deals "Deal stage" column, All Deals table view) -- asymmetric
|
|
115
|
+
// padding (room for a leading dot/icon: 1px top/bottom, 6px trailing,
|
|
116
|
+
// 4px leading), not a symmetric 9px. Height/font/tracking are
|
|
117
|
+
// unchanged (still not independently re-measured this round, per
|
|
118
|
+
// #696's own note).
|
|
119
|
+
// your-moon/crisp#919: radius was Attio's own measured 9px
|
|
120
|
+
// (`radius.lg`, deliberately not `radius.chip`'s then-7px) -- now
|
|
121
|
+
// `radius.sm` (6px), seed-design's own Badge large step
|
|
122
|
+
// (`$radius.r1_5`). Radius specifically is one of the values this
|
|
123
|
+
// migration takes from seed over an Attio measurement (colours/radii/
|
|
124
|
+
// control-styling/elevation all do); the padding/height facts above
|
|
125
|
+
// are unaffected and still Attio's.
|
|
112
126
|
large: {
|
|
113
127
|
height: c.size.chip,
|
|
114
128
|
paddingBlock: c.space.px,
|
|
@@ -116,7 +130,7 @@ const spec = defineSpec({
|
|
|
116
130
|
paddingInlineEnd: c.space["1.5"],
|
|
117
131
|
fontSize: c.text.lg,
|
|
118
132
|
letterSpacing: "-0.1px",
|
|
119
|
-
borderRadius: c.radius.
|
|
133
|
+
borderRadius: c.radius.sm,
|
|
120
134
|
},
|
|
121
135
|
},
|
|
122
136
|
variant: { soft: {}, solid: {} },
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as dialog from "@zag-js/dialog";
|
|
3
|
+
import { normalizeProps, Portal, useMachine } from "@zag-js/react";
|
|
4
|
+
import { X } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { cx, hasOpenFloatingLayer, useCrispMessage, withDescribedBy, } from "../../core/index.js";
|
|
7
|
+
import { bottomsheetRecipe } from "./bottomsheet.recipe.js";
|
|
8
|
+
let instanceCounter = 0;
|
|
9
|
+
function useBottomSheetInstanceId() {
|
|
10
|
+
const idRef = React.useRef(null);
|
|
11
|
+
if (idRef.current == null) {
|
|
12
|
+
instanceCounter += 1;
|
|
13
|
+
idRef.current = `crisp-bottomsheet-${instanceCounter}`;
|
|
14
|
+
}
|
|
15
|
+
return idRef.current;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A mobile bottom sheet — composes Zag's dialog machine (focus trap, scroll
|
|
19
|
+
* lock, Escape / outside-click dismissal) with a panel that slides up from
|
|
20
|
+
* the bottom edge. Compose the body with `BottomSheetBody` and actions with
|
|
21
|
+
* `BottomSheetFooter`.
|
|
22
|
+
*/
|
|
23
|
+
export function BottomSheet({ open, onOpenChange, title, description, headerAlign = "left", showCloseButton, "aria-label": ariaLabel, closeLabel: closeLabelProp, children, className, "aria-describedby": describedBy, ...rest }) {
|
|
24
|
+
const closeLabel = useCrispMessage(closeLabelProp, "Close");
|
|
25
|
+
const id = useBottomSheetInstanceId();
|
|
26
|
+
const service = useMachine(dialog.machine, {
|
|
27
|
+
id,
|
|
28
|
+
open,
|
|
29
|
+
onOpenChange(details) {
|
|
30
|
+
onOpenChange(details.open);
|
|
31
|
+
},
|
|
32
|
+
"aria-label": typeof title === "string" ? title : ariaLabel,
|
|
33
|
+
// Defer to a nested Menu/Select/Popover/ContextMenu's own Escape
|
|
34
|
+
// handling (#361) -- same reasoning as Dialog/Drawer, same machine.
|
|
35
|
+
onEscapeKeyDown(event) {
|
|
36
|
+
if (hasOpenFloatingLayer())
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const api = dialog.connect(service, normalizeProps);
|
|
41
|
+
if (!api.open)
|
|
42
|
+
return null;
|
|
43
|
+
const hasClose = showCloseButton ?? title != null;
|
|
44
|
+
return (_jsx(Portal, { children: _jsxs("div", { className: bottomsheetRecipe(), children: [_jsx("div", { ...api.getBackdropProps(), className: "crisp-bottomsheet-backdrop" }), _jsx("div", { ...api.getPositionerProps(), className: "crisp-bottomsheet-positioner", children: _jsxs("div", { ...rest, ...withDescribedBy(api.getContentProps(), describedBy), className: cx("crisp-bottomsheet-content", className), "data-header-align": headerAlign, "data-has-close": hasClose ? "" : undefined, children: [(title != null || description != null) && (_jsxs("div", { className: "crisp-bottomsheet-header", children: [title != null && (_jsx("span", { ...api.getTitleProps(), className: "crisp-bottomsheet-title", children: title })), description != null && (_jsx("span", { className: "crisp-bottomsheet-description", children: description })), hasClose && (_jsx("button", { type: "button", ...api.getCloseTriggerProps(), className: "crisp-bottomsheet-close", "aria-label": closeLabel, children: _jsx(X, { size: 16, strokeWidth: 2, "aria-hidden": "true" }) }))] })), children] }) })] }) }));
|
|
45
|
+
}
|
|
46
|
+
BottomSheet.displayName = "BottomSheet";
|
|
47
|
+
export function BottomSheetBody({ children }) {
|
|
48
|
+
return _jsx("div", { className: "crisp-bottomsheet-body", children: children });
|
|
49
|
+
}
|
|
50
|
+
export function BottomSheetFooter({ children, }) {
|
|
51
|
+
return _jsx("div", { className: "crisp-bottomsheet-footer", children: children });
|
|
52
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { defineRecipe, resolveRecipe } from "../../core/index.js";
|
|
2
|
+
import { contract as c } from "../../tokens/index.js";
|
|
3
|
+
// A mobile bottom sheet — daangn/seed-design's
|
|
4
|
+
// packages/rootage/components/bottom-sheet.yaml (dev@e1c486b904297f7b6a8f17b8523f732c37015d60),
|
|
5
|
+
// not Attio (no such component there; crisp#911). Composes @zag-js/dialog, the
|
|
6
|
+
// same headless machine Dialog/Drawer already use, with a panel that slides
|
|
7
|
+
// up from the bottom edge over a scrim -- only the TOP corners round; the
|
|
8
|
+
// panel sits flush with the viewport's bottom edge, unlike Drawer's own
|
|
9
|
+
// 8px-gutter floating panel. Every numeric value below cites its yaml line.
|
|
10
|
+
const config = defineRecipe({
|
|
11
|
+
name: "bottomsheet",
|
|
12
|
+
base: `display: contents; font-family: ${c.font.sans};
|
|
13
|
+
& .crisp-bottomsheet-backdrop {
|
|
14
|
+
position: fixed; inset: 0; z-index: 60;
|
|
15
|
+
background: ${c.bgOverlayStrong}; /* bottom-sheet.yaml:99 backdrop.color = $color.bg.overlay -- a different, darker, theme-constant scrim than the Dialog bgScrim token, see its own comment */
|
|
16
|
+
opacity: 1; transition: opacity 300ms cubic-bezier(0,0,.15,1); /* bottom-sheet.yaml:100-102 enterDuration/enterTimingFunction */
|
|
17
|
+
@starting-style { opacity: 0; }
|
|
18
|
+
}
|
|
19
|
+
& .crisp-bottomsheet-positioner {
|
|
20
|
+
position: fixed; inset: 0; z-index: 61;
|
|
21
|
+
display: flex; align-items: flex-end; justify-content: center;
|
|
22
|
+
}
|
|
23
|
+
& .crisp-bottomsheet-content {
|
|
24
|
+
-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
25
|
+
position: relative; box-sizing: border-box; display: flex; flex-direction: column;
|
|
26
|
+
overflow: hidden; width: 100%; max-width: 480px; /* bottom-sheet.yaml:110 content.maxWidth */
|
|
27
|
+
max-height: 85vh;
|
|
28
|
+
background: ${c.bgSurface}; /* bottom-sheet.yaml:109 content.color = $color.bg.layer-floating */
|
|
29
|
+
border-radius: ${c.radius["4xl"]} ${c.radius["4xl"]} 0 0; /* bottom-sheet.yaml:111 content.topCornerRadius = $radius.r6 (24px), bottom flush with the viewport */
|
|
30
|
+
transform: translateY(0);
|
|
31
|
+
transition: transform 300ms cubic-bezier(.03,.4,.1,1); /* bottom-sheet.yaml:112-113 content.enterDuration/enterTimingFunction (enter-expressive) */
|
|
32
|
+
@starting-style { transform: translateY(100%); }
|
|
33
|
+
}
|
|
34
|
+
& .crisp-bottomsheet-header {
|
|
35
|
+
position: relative; display: flex; flex-direction: column;
|
|
36
|
+
gap: ${c.space["2"]}; /* bottom-sheet.yaml:120 header.gap = $dimension.x2 (8px) */
|
|
37
|
+
padding-top: ${c.space["6"]}; padding-bottom: ${c.space["4"]}; /* bottom-sheet.yaml:121-122 header.paddingTop/paddingBottom = $dimension.x6/x4 (24px/16px) */
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
}
|
|
40
|
+
& .crisp-bottomsheet-title {
|
|
41
|
+
color: ${c.fgPrimary}; /* bottom-sheet.yaml:130 title.color = $color.fg.neutral */
|
|
42
|
+
font-size: 22px; line-height: 30px; font-weight: ${c.weight.bold}; /* bottom-sheet.yaml:131-133 title.fontSize/lineHeight/fontWeight = $font-size.t8/$line-height.t8/bold */
|
|
43
|
+
padding-inline: ${c.space["4"]}; /* default (headerAlignment=left, no close button): bottom-sheet.yaml:150-152 */
|
|
44
|
+
}
|
|
45
|
+
&[data-header-align="left"][data-has-close] .crisp-bottomsheet-title { padding-inline-start: ${c.space["4"]}; padding-inline-end: 56px; } /* bottom-sheet.yaml:141-144 */
|
|
46
|
+
&[data-header-align="center"] .crisp-bottomsheet-title { text-align: center; }
|
|
47
|
+
&[data-header-align="center"][data-has-close] .crisp-bottomsheet-title { padding-inline: 56px; } /* bottom-sheet.yaml:154-157 */
|
|
48
|
+
& .crisp-bottomsheet-description {
|
|
49
|
+
color: ${c.fgMuted}; /* bottom-sheet.yaml:138 description.color = $color.fg.neutral-muted */
|
|
50
|
+
font-size: ${c.text.xl}; line-height: 22px; font-weight: ${c.weight.regular}; /* bottom-sheet.yaml:139-141 description.fontSize/lineHeight/fontWeight = $font-size.t5/$line-height.t5/regular */
|
|
51
|
+
padding-inline: ${c.space["4"]}; /* bottom-sheet.yaml:142 description.paddingX = global-gutter (16px) */
|
|
52
|
+
}
|
|
53
|
+
& .crisp-bottomsheet-close {
|
|
54
|
+
position: absolute; top: ${c.space["6"]}; inset-inline-end: ${c.space["4"]}; /* bottom-sheet.yaml:145-146 closeButton.fromTop/fromRight = $dimension.x6/x4 (24px/16px) */
|
|
55
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
56
|
+
width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: ${c.radius.md};
|
|
57
|
+
background: none; color: ${c.fgMuted}; font-family: inherit; cursor: pointer;
|
|
58
|
+
}
|
|
59
|
+
& .crisp-bottomsheet-close:hover { background: color-mix(in srgb, ${c.fgPrimary} 6%, transparent); color: ${c.fgPrimary}; }
|
|
60
|
+
& .crisp-bottomsheet-body {
|
|
61
|
+
flex: 1; min-height: 0; overflow-y: auto;
|
|
62
|
+
padding-inline: ${c.space["4"]}; /* bottom-sheet.yaml:126 body.paddingX = global-gutter (16px) -- no vertical padding in the spec */
|
|
63
|
+
}
|
|
64
|
+
& .crisp-bottomsheet-footer {
|
|
65
|
+
display: flex; align-items: center; justify-content: flex-end; gap: ${c.space["3"]};
|
|
66
|
+
flex-shrink: 0;
|
|
67
|
+
padding-inline: ${c.space["4"]}; padding-top: ${c.space["3"]}; padding-bottom: ${c.space["4"]}; /* bottom-sheet.yaml:127-129 footer.paddingX/paddingTop/paddingBottom = global-gutter/x3/x4 (16px/12px/16px) */
|
|
68
|
+
}`,
|
|
69
|
+
variants: {},
|
|
70
|
+
defaultVariants: {},
|
|
71
|
+
compoundVariants: [],
|
|
72
|
+
});
|
|
73
|
+
export const bottomsheetRecipe = resolveRecipe(config);
|
|
74
|
+
export default config;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
|
|
2
|
-
import { contract as c
|
|
2
|
+
import { contract as c } from "../../tokens/index.js";
|
|
3
3
|
const spec = defineSpec({
|
|
4
4
|
name: "button",
|
|
5
5
|
base: {
|
|
@@ -22,6 +22,12 @@ const spec = defineSpec({
|
|
|
22
22
|
},
|
|
23
23
|
parts: [
|
|
24
24
|
{ selector: "&:disabled", decls: { opacity: 0.5, cursor: "not-allowed" } },
|
|
25
|
+
// your-moon/crisp#910: seed-design's every Button variant
|
|
26
|
+
// gives press feedback as a `scaleScope: self` micro-interaction, not a
|
|
27
|
+
// shadow/fill change alone (`action-button.yaml`, read in the seed raw
|
|
28
|
+
// dump) -- on top of, not instead of, each intent's own colour-on-press
|
|
29
|
+
// below. Root-level so it applies uniformly across all four intents.
|
|
30
|
+
{ selector: "&:active", decls: { transform: "scale(0.98)" } },
|
|
25
31
|
],
|
|
26
32
|
variants: {
|
|
27
33
|
intent: {
|
|
@@ -35,12 +41,13 @@ const spec = defineSpec({
|
|
|
35
41
|
// buttons use white).
|
|
36
42
|
background: c.bgBrandContrast,
|
|
37
43
|
color: c.fgOnBrand,
|
|
38
|
-
// crisp#
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
+
// your-moon/crisp#910: seed's brandSolid carries no
|
|
45
|
+
// shadow/ring at all (`action-button.yaml`: `border: none`, no
|
|
46
|
+
// shadow key) -- dropped the coloured ambient drop-shadow and the
|
|
47
|
+
// black-tint inset ring (crisp#494) that were tuned for Attio's
|
|
48
|
+
// own look, per the owner's directive that elevation/control
|
|
49
|
+
// styling now follows seed, not Attio.
|
|
50
|
+
boxShadow: "none",
|
|
44
51
|
},
|
|
45
52
|
// your-moon/crisp#897: a brightness filter, not a second background
|
|
46
53
|
// swap — matches `danger`'s own pattern below. `bgBrandSolidPressed`
|
|
@@ -56,20 +63,29 @@ const spec = defineSpec({
|
|
|
56
63
|
},
|
|
57
64
|
neutral: {
|
|
58
65
|
decls: {
|
|
59
|
-
|
|
66
|
+
// your-moon/crisp#910: seed's `neutralWeak` fill is
|
|
67
|
+
// `bg.neutral-weak` (#f3f4f5) at rest, not an opaque white --
|
|
68
|
+
// `bgNeutralWeak` is already this exact hex (no new measurement).
|
|
69
|
+
// No border/shadow in seed's spec either; dropped `e.field`'s
|
|
70
|
+
// 3-layer button-chrome glow for the same reason primary/danger
|
|
71
|
+
// lost theirs.
|
|
72
|
+
background: c.bgNeutralWeak,
|
|
60
73
|
color: c.fgPrimary,
|
|
61
|
-
boxShadow:
|
|
74
|
+
boxShadow: "none",
|
|
62
75
|
},
|
|
63
|
-
parts: [
|
|
76
|
+
parts: [
|
|
77
|
+
// seed's neutralWeak "pressed" bg (#eeeff1) is `borderSubtle`'s
|
|
78
|
+
// own already-exact value -- reused, not a fresh literal.
|
|
79
|
+
{ selector: "&:hover", decls: { background: c.borderSubtle } },
|
|
80
|
+
],
|
|
64
81
|
},
|
|
65
82
|
danger: {
|
|
66
83
|
decls: {
|
|
67
84
|
background: c.bgDangerSolid,
|
|
68
85
|
color: c.fgOnBrand,
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(186,37,37,0.20), 0 3px 6px -2px rgba(186,37,37,0.12)",
|
|
86
|
+
// your-moon/crisp#910: same "no shadow at all" call as
|
|
87
|
+
// primary above -- seed's criticalSolid carries no ring either.
|
|
88
|
+
boxShadow: "none",
|
|
73
89
|
},
|
|
74
90
|
parts: [
|
|
75
91
|
{ selector: "&:hover", decls: { filter: "brightness(0.96)" } },
|
|
@@ -79,7 +95,12 @@ const spec = defineSpec({
|
|
|
79
95
|
ghost: {
|
|
80
96
|
decls: {
|
|
81
97
|
background: "transparent",
|
|
82
|
-
|
|
98
|
+
// your-moon/crisp#910: seed's `ghost` enabled label/icon
|
|
99
|
+
// colour is `fg.neutral` (full ink), not a de-emphasised muted
|
|
100
|
+
// grey that only darkens on hover -- `action-button.yaml`'s own
|
|
101
|
+
// enabled-state colour table has no separate "muted" step for
|
|
102
|
+
// ghost. Real behaviour change, flagged in HANDOFF/CHANGELOG.
|
|
103
|
+
color: c.fgPrimary,
|
|
83
104
|
boxShadow: "none",
|
|
84
105
|
},
|
|
85
106
|
parts: [
|
|
@@ -129,7 +150,10 @@ const spec = defineSpec({
|
|
|
129
150
|
height: "40px",
|
|
130
151
|
paddingInline: "14px",
|
|
131
152
|
fontSize: c.text.lg,
|
|
132
|
-
|
|
153
|
+
// your-moon/crisp#910: was a stray literal `10px`, matching neither
|
|
154
|
+
// the token scale nor seed's own large-size radius (`$radius.r3` =
|
|
155
|
+
// 12px, `action-button.yaml`) -- now the actual `xl` token.
|
|
156
|
+
borderRadius: c.radius.xl,
|
|
133
157
|
},
|
|
134
158
|
},
|
|
135
159
|
shape: {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
|
|
2
2
|
import { contract as c } from "../../tokens/index.js";
|
|
3
|
-
// A 16px square checkbox measured from a record grid:
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// A 16px square checkbox measured from a record grid: brand fill + white
|
|
4
|
+
// check when on. The check is a data-URI SVG background so it renders
|
|
5
|
+
// reliably (input pseudo-content doesn't). Radius (r4) and the real 1px
|
|
6
|
+
// border when empty are seed-design's own (your-moon/crisp#926),
|
|
7
|
+
// not the original 6px/box-shadow-ring measurement.
|
|
6
8
|
const CHECK = "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\")";
|
|
7
9
|
const spec = defineSpec({
|
|
8
10
|
name: "checkbox",
|
|
@@ -14,25 +16,32 @@ const spec = defineSpec({
|
|
|
14
16
|
margin: 0,
|
|
15
17
|
width: "16px",
|
|
16
18
|
height: "16px",
|
|
17
|
-
border:
|
|
18
|
-
|
|
19
|
+
// your-moon/crisp#926: was `border: none` + a box-shadow
|
|
20
|
+
// inset ring -- seed-design's own checkmark (`checkmark.yaml`) is a real
|
|
21
|
+
// 1px border (`stroke.neutral-weak`, `borderDefault`'s exact value),
|
|
22
|
+
// removed entirely (not hidden via boxShadow:none) when selected, same
|
|
23
|
+
// technique change already made for Input (your-moon/crisp#910).
|
|
24
|
+
border: `1px solid ${c.borderDefault}`,
|
|
25
|
+
// your-moon/crisp#926: seed's checkmark box corner is
|
|
26
|
+
// `$radius.r1` (4px, `radius.xs`), not the 6px `radius.sm` this shared
|
|
27
|
+
// with Chip's old rounded-rect shape.
|
|
28
|
+
borderRadius: c.radius.xs,
|
|
19
29
|
background: c.bgSurface,
|
|
20
|
-
boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 9%, transparent)`,
|
|
21
30
|
cursor: "pointer",
|
|
22
|
-
transition: "background-color .12s,
|
|
31
|
+
transition: "background-color .12s, border-color .12s",
|
|
23
32
|
},
|
|
24
33
|
parts: [
|
|
25
34
|
{
|
|
26
35
|
selector: "&:hover",
|
|
27
36
|
decls: {
|
|
28
|
-
|
|
37
|
+
borderColor: `color-mix(in srgb, ${c.fgPrimary} 30%, transparent)`,
|
|
29
38
|
},
|
|
30
39
|
},
|
|
31
40
|
{
|
|
32
41
|
selector: "&:checked, &:indeterminate",
|
|
33
42
|
decls: {
|
|
34
43
|
background: `${c.bgBrandSolid} center / 10px no-repeat`,
|
|
35
|
-
|
|
44
|
+
borderColor: "transparent",
|
|
36
45
|
},
|
|
37
46
|
},
|
|
38
47
|
{ selector: "&:checked", decls: { backgroundImage: CHECK } },
|
|
@@ -50,6 +59,49 @@ const spec = defineSpec({
|
|
|
50
59
|
outlineOffset: "1px",
|
|
51
60
|
},
|
|
52
61
|
},
|
|
62
|
+
// your-moon/crisp#963: was no `:disabled` styling at all
|
|
63
|
+
// -- seed-design's own checkmark spec (`checkmark.yaml`) treats disabled
|
|
64
|
+
// as its own recolor, not a blanket opacity dim: fill `bg.disabled`
|
|
65
|
+
// (crisp's already-exact `bgNeutralWeak`, #f3f4f5), border
|
|
66
|
+
// `stroke.neutral-muted` (crisp's already-exact `borderSubtle`, applied
|
|
67
|
+
// here as the disabled border colour rather than its usual ring role).
|
|
68
|
+
// "disabled (any state)" per seed -- checked/indeterminate get the same
|
|
69
|
+
// muted fill/border, not the brand fill, hence the compound selectors
|
|
70
|
+
// below outranking the plain `:checked`/`:indeterminate` rule above.
|
|
71
|
+
{
|
|
72
|
+
selector: "&:disabled",
|
|
73
|
+
decls: {
|
|
74
|
+
background: c.bgNeutralWeak,
|
|
75
|
+
borderColor: c.borderSubtle,
|
|
76
|
+
cursor: "not-allowed",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
// Higher specificity than the plain `&:checked, &:indeterminate` rule
|
|
81
|
+
// above (two pseudo-classes vs one), so this wins regardless of
|
|
82
|
+
// declaration order. Deliberately keeps the existing white check icon
|
|
83
|
+
// rather than recolouring it to seed's `fg.disabled` -- that glyph is
|
|
84
|
+
// baked into a static SVG data-URI with no theme-aware way to retint
|
|
85
|
+
// it without switching techniques entirely (mask + a separate colour
|
|
86
|
+
// layer), and white still reads clearly against the muted grey fill.
|
|
87
|
+
selector: "&:checked:disabled, &:indeterminate:disabled",
|
|
88
|
+
decls: {
|
|
89
|
+
background: `${c.bgNeutralWeak} center / 10px no-repeat`,
|
|
90
|
+
borderColor: c.borderSubtle,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{ selector: "&:checked:disabled", decls: { backgroundImage: CHECK } },
|
|
94
|
+
{
|
|
95
|
+
// The `background` shorthand just above resets `background-image` to
|
|
96
|
+
// `none` on every property it doesn't restate -- without this, a
|
|
97
|
+
// disabled indeterminate checkbox would show the muted fill but lose
|
|
98
|
+
// its dash entirely.
|
|
99
|
+
selector: "&:indeterminate:disabled",
|
|
100
|
+
decls: {
|
|
101
|
+
backgroundImage: `linear-gradient(${c.fgOnBrand}, ${c.fgOnBrand})`,
|
|
102
|
+
backgroundSize: "8px 2px",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
53
105
|
],
|
|
54
106
|
});
|
|
55
107
|
const config = specToRecipe(spec);
|
|
@@ -15,9 +15,21 @@ import { chipRecipe } from "./chip.recipe.js";
|
|
|
15
15
|
* an inline ×) — so `Chip` has no `onRemove`/remove button yet. Add one once
|
|
16
16
|
* that surface can be measured; don't guess the icon, its hit target, or its
|
|
17
17
|
* spacing from the label.
|
|
18
|
+
*
|
|
19
|
+
* `appearance` (`"filled"` default | `"outline"`) and `selected` separate
|
|
20
|
+
* three visual roles crisp/#907's study found conflated: a filled chip reads
|
|
21
|
+
* as a status/value (not clickable), an outline chip reads as actionable (a
|
|
22
|
+
* tag or filter you can tap), and `selected` overrides either to a dark fill
|
|
23
|
+
* once tapped — see `chip.recipe.ts` for the structural reference.
|
|
18
24
|
*/
|
|
19
|
-
export const Chip = React.forwardRef(({ tone, truncate, className, asChild, children, ...props }, ref) => {
|
|
25
|
+
export const Chip = React.forwardRef(({ tone, truncate, appearance, selected, className, asChild, children, ...props }, ref) => {
|
|
20
26
|
const content = truncate && !asChild && typeof children === "string" ? (_jsx("span", { className: "crisp-chip-label", children: children })) : (children);
|
|
21
|
-
return (_jsx(Primitive.span, { ref: ref, asChild: asChild, className: chipRecipe({
|
|
27
|
+
return (_jsx(Primitive.span, { ref: ref, asChild: asChild, className: chipRecipe({
|
|
28
|
+
tone,
|
|
29
|
+
truncate,
|
|
30
|
+
appearance,
|
|
31
|
+
selected,
|
|
32
|
+
className,
|
|
33
|
+
}), ...props, children: content }));
|
|
22
34
|
});
|
|
23
35
|
Chip.displayName = "Chip";
|