@crisp-ui-kit/crisp 0.37.0 → 0.39.0
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/badge.css +5 -5
- package/dist/badge.layered.css +5 -5
- package/dist/cjs/components/badge/badge.recipe.js +11 -5
- package/dist/cjs/components/contextmenu/contextmenu.js +1 -1
- package/dist/cjs/components/contextmenu/contextmenu.recipe.js +22 -10
- package/dist/cjs/components/fileupload/fileupload.js +2 -2
- package/dist/cjs/components/menu/menu.js +1 -1
- package/dist/cjs/components/menu/menu.recipe.js +32 -20
- package/dist/cjs/components/multiselect/multiselect.js +4 -4
- package/dist/cjs/components/multiselect/multiselect.recipe.js +50 -24
- package/dist/cjs/components/popover/popover.js +1 -1
- package/dist/cjs/components/popover/popover.recipe.js +19 -4
- package/dist/cjs/components/select/select.js +3 -3
- package/dist/cjs/components/select/select.recipe.js +42 -16
- package/dist/cjs/core/floating-portal.js +55 -2
- package/dist/cjs/tokens/palette.js +23 -0
- package/dist/cjs/tokens/semantic.js +7 -0
- package/dist/contextmenu.css +11 -9
- package/dist/contextmenu.layered.css +11 -9
- package/dist/esm/components/badge/badge.recipe.js +11 -5
- package/dist/esm/components/contextmenu/contextmenu.js +1 -1
- package/dist/esm/components/contextmenu/contextmenu.recipe.js +22 -10
- package/dist/esm/components/fileupload/fileupload.js +2 -2
- package/dist/esm/components/menu/menu.js +1 -1
- package/dist/esm/components/menu/menu.recipe.js +32 -20
- package/dist/esm/components/multiselect/multiselect.js +4 -4
- package/dist/esm/components/multiselect/multiselect.recipe.js +50 -24
- package/dist/esm/components/popover/popover.js +1 -1
- package/dist/esm/components/popover/popover.recipe.js +19 -4
- package/dist/esm/components/select/select.js +3 -3
- package/dist/esm/components/select/select.recipe.js +42 -16
- package/dist/esm/core/floating-portal.js +22 -2
- package/dist/esm/tokens/palette.js +23 -0
- package/dist/esm/tokens/semantic.js +7 -0
- package/dist/menu.css +34 -19
- package/dist/menu.layered.css +34 -19
- package/dist/multiselect.css +40 -21
- package/dist/multiselect.d.ts +2 -2
- package/dist/multiselect.layered.css +40 -21
- package/dist/native/tokens.d.ts +1 -1
- package/dist/native/tokens.js +24 -4
- package/dist/popover.css +5 -3
- package/dist/popover.layered.css +5 -3
- package/dist/select.css +33 -14
- package/dist/select.d.ts +2 -1
- package/dist/select.layered.css +33 -14
- package/dist/styles.css +138 -71
- package/dist/styles.layered.css +138 -71
- package/dist/tokens.css +10 -0
- package/dist/tokens.json +24 -4
- package/dist/types/components/fileupload/fileupload.d.ts +1 -1
- package/dist/types/components/multiselect/multiselect.d.ts +3 -1
- package/dist/types/components/multiselect/multiselect.recipe.d.ts +18 -3
- package/dist/types/components/select/select.d.ts +4 -1
- package/dist/types/components/select/select.recipe.d.ts +12 -0
- package/dist/types/core/floating-portal.d.ts +17 -3
- package/dist/types/product/sidebar/index.d.ts +1 -1
- package/dist/types/tokens/contract.d.ts +5 -0
- package/dist/types/tokens/palette.d.ts +20 -0
- package/dist/types/tokens/semantic.d.ts +7 -0
- package/package.json +3 -3
|
@@ -16,7 +16,7 @@ function optionText(o) {
|
|
|
16
16
|
* "No results" empty state). Full keyboard model — ↑/↓ move, Enter/Space pick,
|
|
17
17
|
* Esc close, Home/End jump, opens upward when tight. Controlled or uncontrolled.
|
|
18
18
|
*/
|
|
19
|
-
export function Select({ options, value, defaultValue, onValueChange, name, required, placeholder = "Select…", variant = "default", width = "full", searchable, searchPlaceholder = "Search…", emptyLabel = "No results", disabled, className, "aria-label": ariaLabel, id, ...rest }) {
|
|
19
|
+
export function Select({ options, value, defaultValue, onValueChange, name, required, placeholder = "Select…", variant = "default", width = "full", searchable, searchPlaceholder = "Search…", emptyLabel = "No results", disabled, invalid, className, "aria-label": ariaLabel, id, ...rest }) {
|
|
20
20
|
// Virtual focus: DOM focus stays on the trigger (or the search field), and the
|
|
21
21
|
// active option is named by `aria-activedescendant`. That is the only thing a
|
|
22
22
|
// screen reader has to go on -- `data-highlighted` is invisible to it -- so the
|
|
@@ -141,10 +141,10 @@ export function Select({ options, value, defaultValue, onValueChange, name, requ
|
|
|
141
141
|
document.addEventListener("pointerdown", onDown);
|
|
142
142
|
return () => document.removeEventListener("pointerdown", onDown);
|
|
143
143
|
}, [open]);
|
|
144
|
-
return (_jsxs("div", { ref: rootRef, className: selectRecipe({ variant, width, className }), ...rest, children: [name && (selected || required) && (_jsx("input", { className: "crisp-formvalue", style: formValueStyle, name: name, value: selected ?? "", required: required, tabIndex: -1, "aria-hidden": "true",
|
|
144
|
+
return (_jsxs("div", { ref: rootRef, className: selectRecipe({ variant, width, invalid, className }), ...rest, children: [name && (selected || required) && (_jsx("input", { className: "crisp-formvalue", style: formValueStyle, name: name, value: selected ?? "", required: required, tabIndex: -1, "aria-hidden": "true",
|
|
145
145
|
// controlled by the listbox above; `readOnly` would bar it from
|
|
146
146
|
// validation, which is the only reason this input is not hidden
|
|
147
|
-
onChange: () => { } })), _jsxs("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "crisp-select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [_jsx("span", { className: "crisp-select-value", children: selectedOption ? (_jsxs(_Fragment, { children: [selectedOption.color && (_jsx("span", { className: "crisp-select-option-dot", style: { background: selectedOption.color } })), selectedOption.label] })) : (_jsx("span", { className: "crisp-select-placeholder", children: placeholder })) }), _jsx(ChevronDown, { className: "crisp-select-chevron", size: 16, strokeWidth: 1.75 })] }), open && (_jsx(FloatingPortal, { children: _jsxs("div", { ref: listboxRef, id: listboxId, className: "crisp-select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && (_jsxs("div", { className: "crisp-select-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
147
|
+
onChange: () => { } })), _jsxs("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, "aria-invalid": invalid === true || undefined, disabled: disabled, "data-open": open ? "" : undefined, className: "crisp-select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [_jsx("span", { className: "crisp-select-value", children: selectedOption ? (_jsxs(_Fragment, { children: [selectedOption.color && (_jsx("span", { className: "crisp-select-option-dot", style: { background: selectedOption.color } })), selectedOption.label] })) : (_jsx("span", { className: "crisp-select-placeholder", children: placeholder })) }), _jsx(ChevronDown, { className: "crisp-select-chevron", size: 16, strokeWidth: 1.75 })] }), open && (_jsx(FloatingPortal, { sourceRef: rootRef, children: _jsxs("div", { ref: listboxRef, id: listboxId, className: "crisp-select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && (_jsxs("div", { className: "crisp-select-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
148
148
|
setQuery(e.target.value);
|
|
149
149
|
setHighlight(0);
|
|
150
150
|
}, onKeyDown: onNavKeys })] })), filtered.length === 0 ? (_jsx("div", { className: "crisp-select-empty", children: emptyLabel })) : (filtered.map((opt, i) => {
|
|
@@ -8,6 +8,17 @@ import { contract as c, elevation as e } from "../../tokens/index.js";
|
|
|
8
8
|
// (Dialog's own measured surface sets both) can capture its position: fixed
|
|
9
9
|
// box; z-index 70 keeps it above Dialog/Drawer's z-index 60/61 layers, since
|
|
10
10
|
// it's no longer nested inside whichever one opened it.
|
|
11
|
+
// The listbox and everything inside it live in `globalCss` below, not
|
|
12
|
+
// nested under `&` (#357): nesting compiles to a real descendant combinator
|
|
13
|
+
// scoped to the recipe's root class, which needs actual DOM containment —
|
|
14
|
+
// exactly what the portal to `document.body` breaks. Nested, these rules
|
|
15
|
+
// matched nothing once the listbox moved and it rendered completely
|
|
16
|
+
// unstyled. The trigger and its own parts stay nested under `&` — the
|
|
17
|
+
// trigger is NOT portaled, it stays where it was authored. `font-family`/
|
|
18
|
+
// smoothing are restated on the listbox's own rule (its children pick font
|
|
19
|
+
// up via their own `font-family: inherit`, which still works — that
|
|
20
|
+
// inheritance is intact WITHIN the portaled subtree, only the link back to
|
|
21
|
+
// the trigger-holding root broke).
|
|
11
22
|
const config = defineRecipe({
|
|
12
23
|
name: "select",
|
|
13
24
|
base: `
|
|
@@ -28,31 +39,33 @@ const config = defineRecipe({
|
|
|
28
39
|
& .crisp-select-placeholder { color: ${c.fgMuted}; }
|
|
29
40
|
& .crisp-select-chevron { flex-shrink: 0; color: ${c.fgMuted}; transition: transform .15s ease; }
|
|
30
41
|
& .crisp-select-trigger[data-open] .crisp-select-chevron { transform: rotate(180deg); }
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
`,
|
|
43
|
+
globalCss: `
|
|
44
|
+
.crisp-select-listbox {
|
|
45
|
+
font-family: ${c.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
33
46
|
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
34
47
|
max-height: 280px; overflow-y: auto; padding: ${c.space["1"]};
|
|
35
48
|
border-radius: ${c.radius.xl}; background: ${c.bgPopover};
|
|
36
49
|
box-shadow: ${e.floating};
|
|
37
50
|
transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
|
|
38
51
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
.crisp-select-listbox[data-up] { transform-origin: bottom; }
|
|
53
|
+
.crisp-select-listbox { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
54
|
+
.crisp-select-search { display: flex; align-items: center; gap: ${c.space["2"]}; height: 34px; flex-shrink: 0; margin: calc(-1 * ${c.space["1"]}) calc(-1 * ${c.space["1"]}) ${c.space["1"]}; padding: 0 ${c.space["2.5"]}; border-bottom: 1px solid ${c.borderSubtle}; color: ${c.fgMuted}; }
|
|
55
|
+
.crisp-select-search svg { flex-shrink: 0; }
|
|
56
|
+
.crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: ${c.text.lg}; color: ${c.fgPrimary}; }
|
|
57
|
+
.crisp-select-search input::placeholder { color: ${c.fgMuted}; }
|
|
58
|
+
.crisp-select-empty { padding: ${c.space["3"]} ${c.space["2"]}; text-align: center; font-size: ${c.text.md}; color: ${c.fgMuted}; }
|
|
59
|
+
.crisp-select-option {
|
|
47
60
|
box-sizing: border-box; display: flex; align-items: center; gap: ${c.space["2"]}; height: ${c.size.menuRow}; flex-shrink: 0;
|
|
48
61
|
padding: 0 ${c.space["2"]}; margin: 0; border: none; background: none; border-radius: ${c.radius.md};
|
|
49
62
|
font-family: inherit; font-size: ${c.text.lg}; color: ${c.fgPrimary}; text-align: start; cursor: pointer; white-space: nowrap;
|
|
50
63
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
.crisp-select-option[data-highlighted] { background: ${c.bgRaised}; }
|
|
65
|
+
.crisp-select-option[data-disabled] { opacity: 0.5; cursor: not-allowed; }
|
|
66
|
+
.crisp-select-option-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: ${c.radius.full}; }
|
|
67
|
+
.crisp-select-option-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
68
|
+
.crisp-select-option-check { flex-shrink: 0; color: ${c.bgBrandSolid}; }
|
|
56
69
|
`,
|
|
57
70
|
variants: {
|
|
58
71
|
// ghost: borderless at rest (transparent), reveals a subtle fill on hover —
|
|
@@ -70,8 +83,21 @@ const config = defineRecipe({
|
|
|
70
83
|
full: `width: 100%;`,
|
|
71
84
|
auto: `width: auto;`,
|
|
72
85
|
},
|
|
86
|
+
// Same ring Input's `invalid` draws, adapted to Select's box-shadow-ring
|
|
87
|
+
// trigger (a real <button>, so it needs no ::after overlay the way
|
|
88
|
+
// Input/Textarea do). Outranks hover/open/focus, same reasoning as
|
|
89
|
+
// Input: a field being corrected stays visibly wrong while it is.
|
|
90
|
+
invalid: {
|
|
91
|
+
true: `
|
|
92
|
+
& .crisp-select-trigger,
|
|
93
|
+
& .crisp-select-trigger:hover,
|
|
94
|
+
& .crisp-select-trigger[data-open],
|
|
95
|
+
& .crisp-select-trigger:focus-visible { box-shadow: inset 0 0 0 1px ${c.bgDanger}; }
|
|
96
|
+
`,
|
|
97
|
+
false: ``,
|
|
98
|
+
},
|
|
73
99
|
},
|
|
74
|
-
defaultVariants: { variant: "default", width: "full" },
|
|
100
|
+
defaultVariants: { variant: "default", width: "full", invalid: false },
|
|
75
101
|
compoundVariants: [],
|
|
76
102
|
});
|
|
77
103
|
export const selectRecipe = Object.assign(resolveRecipe(config), { config });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as React from "react";
|
|
1
2
|
import { createPortal } from "react-dom";
|
|
2
3
|
/**
|
|
3
4
|
* Portals a floating layer (a `position: fixed` listbox/menu/popover
|
|
@@ -19,7 +20,26 @@ import { createPortal } from "react-dom";
|
|
|
19
20
|
* starts `false` and is driven only by client interaction — never a prop a
|
|
20
21
|
* fixture sets true at mount (unlike Dialog/Drawer/Command) — so this never
|
|
21
22
|
* touches `document` during SSR, the same safety Tooltip already had.
|
|
23
|
+
*
|
|
24
|
+
* `sourceRef` is the caller's own root — still in its original DOM position,
|
|
25
|
+
* never portaled — used to carry a `data-theme` set on some ancestor of it
|
|
26
|
+
* onto the portaled content (#357). `[data-theme="dark"]` is a normal
|
|
27
|
+
* attribute selector: it needs the themed element to be an actual DOM
|
|
28
|
+
* ancestor, which a consumer that scopes theming below `<html>`/`<body>`
|
|
29
|
+
* (crisp's own visual-test harness does exactly this, per case) no longer
|
|
30
|
+
* is once the content moves to `document.body` — the popover rendered in
|
|
31
|
+
* the PAGE's theme instead of the SUBTREE's. Re-declaring the attribute
|
|
32
|
+
* directly on the portaled root re-establishes it for CSS attribute
|
|
33
|
+
* selectors AND for `var()` resolution, since a custom property set under
|
|
34
|
+
* `[data-theme="dark"] { --crisp-x: ... }` only reaches descendants of an
|
|
35
|
+
* element carrying that attribute.
|
|
22
36
|
*/
|
|
23
|
-
export function FloatingPortal({ children, }) {
|
|
24
|
-
|
|
37
|
+
export function FloatingPortal({ children, sourceRef, }) {
|
|
38
|
+
const theme = sourceRef.current
|
|
39
|
+
?.closest("[data-theme]")
|
|
40
|
+
?.getAttribute("data-theme");
|
|
41
|
+
const content = theme
|
|
42
|
+
? React.cloneElement(children, { "data-theme": theme })
|
|
43
|
+
: children;
|
|
44
|
+
return createPortal(content, document.body);
|
|
25
45
|
}
|
|
@@ -57,4 +57,27 @@ export const palette = {
|
|
|
57
57
|
cyan600: { light: "#00b9eb", dark: "#00b9eb" },
|
|
58
58
|
purple600: { light: "#9b69ff", dark: "#9b69ff" },
|
|
59
59
|
graySidebar: { light: "#fbfbfb", dark: "#0e0f10" },
|
|
60
|
+
// Soft Badge's text colour (#323): the *600 tones above, used directly as
|
|
61
|
+
// soft-badge text, fail AA on their own soft tint in light mode (2.97-3.87)
|
|
62
|
+
// and brand fails in dark too (3.83) -- everything else already brightens
|
|
63
|
+
// enough in dark to pass (measured: 5.60-6.77). Attio's own soft tag pills
|
|
64
|
+
// (a company's Categories field, app.attio.com, 2026-09-23) don't reuse the
|
|
65
|
+
// accent colour as text either: they shift it toward black (light) or white
|
|
66
|
+
// (dark) at roughly the same relative luminance regardless of hue --
|
|
67
|
+
// measured 5 different category colours in dark mode (L 0.61-0.75) and two
|
|
68
|
+
// in light (L 0.08-0.10), a tight enough cluster to generalise the SHIFT,
|
|
69
|
+
// not the exact colour, to crisp's own four accent hues. Computed to clear
|
|
70
|
+
// AA with the same margin Attio's pills measured at (5.5-6.5:1) against
|
|
71
|
+
// crisp's EXISTING soft-tint background -- the tint itself is unchanged.
|
|
72
|
+
// Dark values that already passed keep their *600 dark value unchanged.
|
|
73
|
+
softBrandText: { light: "#2057bd", dark: "#568df3" },
|
|
74
|
+
softSuccessText: { light: "#186b3d", dark: "#2ea968" },
|
|
75
|
+
softWarningText: { light: "#80520d", dark: "#e0982a" },
|
|
76
|
+
softDangerText: { light: "#a33539", dark: "#ff5a5f" },
|
|
77
|
+
// Same reasoning, for Badge's neutral tone: fg-muted on bg-raised measures
|
|
78
|
+
// 4.40 in light (just under AA) and 6.77 in dark (already fine). Unlike
|
|
79
|
+
// fg-muted/bg-raised themselves (system-wide, measured from Attio, kept
|
|
80
|
+
// as-is per build/spec-check.mjs's own note), this token exists only for
|
|
81
|
+
// Badge's soft-neutral text, so darkening it doesn't move any other surface.
|
|
82
|
+
softNeutralText: { light: "#686870", dark: "#9a9aa2" },
|
|
60
83
|
};
|
|
@@ -51,4 +51,11 @@ export const semantic = {
|
|
|
51
51
|
// #fbfbfb — the subtle raised fill; the active tab pill uses the same
|
|
52
52
|
// value as the sidebar, so it shares the palette entry under a neutral name.
|
|
53
53
|
bgSubtle: "graySidebar",
|
|
54
|
+
/** Soft Badge's text colour (#323) — see palette.ts's comment on the
|
|
55
|
+
* soft*Text entries for the Attio measurement this is derived from. */
|
|
56
|
+
fgBrandSoft: "softBrandText",
|
|
57
|
+
fgSuccessSoft: "softSuccessText",
|
|
58
|
+
fgWarningSoft: "softWarningText",
|
|
59
|
+
fgDangerSoft: "softDangerText",
|
|
60
|
+
fgNeutralSoft: "softNeutralText",
|
|
54
61
|
};
|
package/dist/menu.css
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
.crisp-menu-content {
|
|
3
|
+
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
+
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
5
|
+
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
6
|
+
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
7
|
+
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);
|
|
8
|
+
transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
|
|
9
|
+
}
|
|
10
|
+
.crisp-menu-content[data-align="end"] { transform-origin: top right; }
|
|
11
|
+
.crisp-menu-content[data-up] { transform-origin: bottom left; }
|
|
12
|
+
.crisp-menu-content[data-up][data-align="end"] { transform-origin: bottom right; }
|
|
13
|
+
.crisp-menu-content { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
14
|
+
|
|
15
|
+
.crisp-menu-item {
|
|
16
|
+
box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: var(--crisp-size-menuRow); flex-shrink: 0;
|
|
17
|
+
margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md);
|
|
18
|
+
font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); text-align: start; cursor: pointer; white-space: nowrap;
|
|
19
|
+
}
|
|
20
|
+
.crisp-menu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
21
|
+
.crisp-menu-item:focus { outline: none; }
|
|
22
|
+
.crisp-menu-item:hover:not([data-disabled]), .crisp-menu-item:focus-visible:not([data-disabled]), .crisp-menu-item[data-highlighted]:not([data-disabled]) { background: var(--crisp-bg-raised); }
|
|
23
|
+
.crisp-menu-item[data-disabled] { opacity: 0.5; cursor: not-allowed; }
|
|
24
|
+
.crisp-menu-item--danger { color: var(--crisp-bg-danger); }
|
|
25
|
+
.crisp-menu-item--danger svg { color: var(--crisp-bg-danger); }
|
|
26
|
+
.crisp-menu-item--danger:hover, .crisp-menu-item--danger:focus-visible, .crisp-menu-item--danger[data-highlighted] { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
27
|
+
.crisp-menu-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
28
|
+
.crisp-menu-item-shortcut { flex-shrink: 0; margin-inline-start: var(--crisp-space-3); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); letter-spacing: 0.02em; }
|
|
29
|
+
.crisp-menu-item-check { flex-shrink: 0; color: var(--crisp-bg-brand-solid); }
|
|
30
|
+
.crisp-menu-item-check--placeholder { width: 15px; }
|
|
31
|
+
|
|
32
|
+
.crisp-menu-sep { height: 1px; flex-shrink: 0; border: none; margin: var(--crisp-space-1) calc(-1 * var(--crisp-space-1)); background: var(--crisp-border-subtle); }
|
|
33
|
+
.crisp-menu-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
34
|
+
|
|
1
35
|
.crisp-menu {
|
|
2
36
|
position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
3
|
-
& .crisp-menu-content { position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px); min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1); 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); transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; }
|
|
4
|
-
& .crisp-menu-content[data-align="end"] { transform-origin: top right; }
|
|
5
|
-
& .crisp-menu-content[data-up] { transform-origin: bottom left; }
|
|
6
|
-
& .crisp-menu-content[data-up][data-align="end"] { transform-origin: bottom right; }
|
|
7
|
-
& .crisp-menu-content { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
8
|
-
& .crisp-menu-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: var(--crisp-size-menuRow); flex-shrink: 0; 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); color: var(--crisp-fg-primary); text-align: start; cursor: pointer; white-space: nowrap; }
|
|
9
|
-
& .crisp-menu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
10
|
-
& .crisp-menu-item:focus { outline: none; }
|
|
11
|
-
& .crisp-menu-item:hover:not([data-disabled]), & .crisp-menu-item:focus-visible:not([data-disabled]), & .crisp-menu-item[data-highlighted]:not([data-disabled]) { background: var(--crisp-bg-raised); }
|
|
12
|
-
& .crisp-menu-item[data-disabled] { opacity: 0.5; cursor: not-allowed; }
|
|
13
|
-
& .crisp-menu-item--danger { color: var(--crisp-bg-danger); }
|
|
14
|
-
& .crisp-menu-item--danger svg { color: var(--crisp-bg-danger); }
|
|
15
|
-
& .crisp-menu-item--danger:hover, & .crisp-menu-item--danger:focus-visible, & .crisp-menu-item--danger[data-highlighted] { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
16
|
-
& .crisp-menu-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
17
|
-
& .crisp-menu-item-shortcut { flex-shrink: 0; margin-inline-start: var(--crisp-space-3); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); letter-spacing: 0.02em; }
|
|
18
|
-
& .crisp-menu-item-check { flex-shrink: 0; color: var(--crisp-bg-brand-solid); }
|
|
19
|
-
& .crisp-menu-item-check--placeholder { width: 15px; }
|
|
20
|
-
& .crisp-menu-sep { height: 1px; flex-shrink: 0; border: none; margin: var(--crisp-space-1) calc(-1 * var(--crisp-space-1)); background: var(--crisp-border-subtle); }
|
|
21
|
-
& .crisp-menu-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
22
37
|
}
|
|
23
38
|
|
|
24
39
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/menu.layered.css
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
|
+
|
|
3
|
+
.crisp-menu-content {
|
|
4
|
+
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
5
|
+
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
6
|
+
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
7
|
+
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
8
|
+
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);
|
|
9
|
+
transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
|
|
10
|
+
}
|
|
11
|
+
.crisp-menu-content[data-align="end"] { transform-origin: top right; }
|
|
12
|
+
.crisp-menu-content[data-up] { transform-origin: bottom left; }
|
|
13
|
+
.crisp-menu-content[data-up][data-align="end"] { transform-origin: bottom right; }
|
|
14
|
+
.crisp-menu-content { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
15
|
+
|
|
16
|
+
.crisp-menu-item {
|
|
17
|
+
box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: var(--crisp-size-menuRow); flex-shrink: 0;
|
|
18
|
+
margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md);
|
|
19
|
+
font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); text-align: start; cursor: pointer; white-space: nowrap;
|
|
20
|
+
}
|
|
21
|
+
.crisp-menu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
22
|
+
.crisp-menu-item:focus { outline: none; }
|
|
23
|
+
.crisp-menu-item:hover:not([data-disabled]), .crisp-menu-item:focus-visible:not([data-disabled]), .crisp-menu-item[data-highlighted]:not([data-disabled]) { background: var(--crisp-bg-raised); }
|
|
24
|
+
.crisp-menu-item[data-disabled] { opacity: 0.5; cursor: not-allowed; }
|
|
25
|
+
.crisp-menu-item--danger { color: var(--crisp-bg-danger); }
|
|
26
|
+
.crisp-menu-item--danger svg { color: var(--crisp-bg-danger); }
|
|
27
|
+
.crisp-menu-item--danger:hover, .crisp-menu-item--danger:focus-visible, .crisp-menu-item--danger[data-highlighted] { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
28
|
+
.crisp-menu-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
29
|
+
.crisp-menu-item-shortcut { flex-shrink: 0; margin-inline-start: var(--crisp-space-3); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); letter-spacing: 0.02em; }
|
|
30
|
+
.crisp-menu-item-check { flex-shrink: 0; color: var(--crisp-bg-brand-solid); }
|
|
31
|
+
.crisp-menu-item-check--placeholder { width: 15px; }
|
|
32
|
+
|
|
33
|
+
.crisp-menu-sep { height: 1px; flex-shrink: 0; border: none; margin: var(--crisp-space-1) calc(-1 * var(--crisp-space-1)); background: var(--crisp-border-subtle); }
|
|
34
|
+
.crisp-menu-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
35
|
+
|
|
2
36
|
.crisp-menu {
|
|
3
37
|
position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
-
& .crisp-menu-content { position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px); min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1); 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); transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; }
|
|
5
|
-
& .crisp-menu-content[data-align="end"] { transform-origin: top right; }
|
|
6
|
-
& .crisp-menu-content[data-up] { transform-origin: bottom left; }
|
|
7
|
-
& .crisp-menu-content[data-up][data-align="end"] { transform-origin: bottom right; }
|
|
8
|
-
& .crisp-menu-content { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
9
|
-
& .crisp-menu-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: var(--crisp-size-menuRow); flex-shrink: 0; 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); color: var(--crisp-fg-primary); text-align: start; cursor: pointer; white-space: nowrap; }
|
|
10
|
-
& .crisp-menu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
11
|
-
& .crisp-menu-item:focus { outline: none; }
|
|
12
|
-
& .crisp-menu-item:hover:not([data-disabled]), & .crisp-menu-item:focus-visible:not([data-disabled]), & .crisp-menu-item[data-highlighted]:not([data-disabled]) { background: var(--crisp-bg-raised); }
|
|
13
|
-
& .crisp-menu-item[data-disabled] { opacity: 0.5; cursor: not-allowed; }
|
|
14
|
-
& .crisp-menu-item--danger { color: var(--crisp-bg-danger); }
|
|
15
|
-
& .crisp-menu-item--danger svg { color: var(--crisp-bg-danger); }
|
|
16
|
-
& .crisp-menu-item--danger:hover, & .crisp-menu-item--danger:focus-visible, & .crisp-menu-item--danger[data-highlighted] { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
17
|
-
& .crisp-menu-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
18
|
-
& .crisp-menu-item-shortcut { flex-shrink: 0; margin-inline-start: var(--crisp-space-3); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); letter-spacing: 0.02em; }
|
|
19
|
-
& .crisp-menu-item-check { flex-shrink: 0; color: var(--crisp-bg-brand-solid); }
|
|
20
|
-
& .crisp-menu-item-check--placeholder { width: 15px; }
|
|
21
|
-
& .crisp-menu-sep { height: 1px; flex-shrink: 0; border: none; margin: var(--crisp-space-1) calc(-1 * var(--crisp-space-1)); background: var(--crisp-border-subtle); }
|
|
22
|
-
& .crisp-menu-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
23
38
|
}
|
|
24
39
|
|
|
25
40
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/multiselect.css
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
.crisp-multiselect-listbox {
|
|
3
|
+
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
+
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
5
|
+
max-height: 300px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
6
|
+
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
7
|
+
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);
|
|
8
|
+
transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
|
|
9
|
+
}
|
|
10
|
+
.crisp-multiselect-listbox[data-up] { transform-origin: bottom left; }
|
|
11
|
+
.crisp-multiselect-listbox { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
12
|
+
.crisp-multiselect-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 34px; flex-shrink: 0; margin: calc(-1 * var(--crisp-space-1)) calc(-1 * var(--crisp-space-1)) var(--crisp-space-1); padding: 0 var(--crisp-space-2-5); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
|
|
13
|
+
.crisp-multiselect-search svg { flex-shrink: 0; }
|
|
14
|
+
.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-primary); }
|
|
15
|
+
.crisp-multiselect-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
16
|
+
.crisp-multiselect-option {
|
|
17
|
+
box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-menuRow); flex-shrink: 0;
|
|
18
|
+
padding: 0 var(--crisp-space-2); margin: 0; border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; cursor: pointer; text-align: start;
|
|
19
|
+
}
|
|
20
|
+
.crisp-multiselect-option[data-highlighted] { background: var(--crisp-bg-raised); }
|
|
21
|
+
.crisp-multiselect-option-chip { flex: 0 1 auto; min-width: 0; overflow: hidden; }
|
|
22
|
+
.crisp-multiselect-check { flex-shrink: 0; margin-inline-start: auto; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: var(--crisp-radius-sm); box-shadow: inset 0 0 0 1.5px var(--crisp-border-default); color: transparent; }
|
|
23
|
+
.crisp-multiselect-option[aria-selected="true"] .crisp-multiselect-check { background: var(--crisp-bg-brand-solid); box-shadow: none; color: #fff; }
|
|
24
|
+
.crisp-multiselect-empty { padding: var(--crisp-space-3) var(--crisp-space-2); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
25
|
+
|
|
26
|
+
.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; overflow: hidden; text-overflow: ellipsis; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
27
|
+
.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)); }
|
|
28
|
+
.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)); }
|
|
29
|
+
.crisp-recordstable-tag[data-tone="warning"] { background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); }
|
|
30
|
+
.crisp-recordstable-tag[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); }
|
|
31
|
+
.crisp-recordstable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); }
|
|
32
|
+
.crisp-recordstable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); }
|
|
33
|
+
.crisp-recordstable-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)); }
|
|
34
|
+
|
|
1
35
|
.crisp-multiselect {
|
|
2
36
|
position: relative; display: inline-flex; width: 100%; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
3
37
|
& .crisp-multiselect-trigger { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; min-width: 0; min-height: var(--crisp-size-menuRow); margin: 0; padding: var(--crisp-space-0-5) var(--crisp-space-1-5) var(--crisp-space-0-5) 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; text-align: start; transition: background-color .12s ease, box-shadow .12s ease; }
|
|
@@ -8,27 +42,12 @@
|
|
|
8
42
|
& .crisp-multiselect-placeholder { color: var(--crisp-fg-muted); }
|
|
9
43
|
& .crisp-multiselect-chevron { flex-shrink: 0; color: var(--crisp-fg-muted); transition: transform .15s ease; }
|
|
10
44
|
& .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); }
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
& .crisp-multiselect-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
18
|
-
& .crisp-multiselect-option { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-menuRow); flex-shrink: 0; padding: 0 var(--crisp-space-2); margin: 0; border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; cursor: pointer; text-align: start; }
|
|
19
|
-
& .crisp-multiselect-option[data-highlighted] { background: var(--crisp-bg-raised); }
|
|
20
|
-
& .crisp-multiselect-option-chip { flex: 0 1 auto; min-width: 0; overflow: hidden; }
|
|
21
|
-
& .crisp-multiselect-check { flex-shrink: 0; margin-inline-start: auto; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: var(--crisp-radius-sm); box-shadow: inset 0 0 0 1.5px var(--crisp-border-default); color: transparent; }
|
|
22
|
-
& .crisp-multiselect-option[aria-selected="true"] .crisp-multiselect-check { background: var(--crisp-bg-brand-solid); box-shadow: none; color: #fff; }
|
|
23
|
-
& .crisp-multiselect-empty { padding: var(--crisp-space-3) var(--crisp-space-2); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
24
|
-
& .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; overflow: hidden; text-overflow: ellipsis; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
25
|
-
& .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)); }
|
|
26
|
-
& .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)); }
|
|
27
|
-
& .crisp-recordstable-tag[data-tone="warning"] { background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); }
|
|
28
|
-
& .crisp-recordstable-tag[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); }
|
|
29
|
-
& .crisp-recordstable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); }
|
|
30
|
-
& .crisp-recordstable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); }
|
|
31
|
-
& .crisp-recordstable-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)); }
|
|
45
|
+
}
|
|
46
|
+
.crisp-multiselect--invalid_true {
|
|
47
|
+
& .crisp-multiselect-trigger, & .crisp-multiselect-trigger:hover, & .crisp-multiselect-trigger[data-open], & .crisp-multiselect-trigger:focus-visible { box-shadow: inset 0 0 0 1px var(--crisp-bg-danger); }
|
|
48
|
+
}
|
|
49
|
+
.crisp-multiselect--invalid_false {
|
|
50
|
+
|
|
32
51
|
}
|
|
33
52
|
|
|
34
53
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/multiselect.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RecipeFn } from "../core/types";
|
|
2
2
|
|
|
3
3
|
export interface MultiselectVariants {
|
|
4
|
-
|
|
4
|
+
invalid?: boolean;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export declare const multiselectRecipe: RecipeFn<{
|
|
7
|
+
export declare const multiselectRecipe: RecipeFn<{ invalid: { true: string; false: string } }>;
|
|
@@ -1,4 +1,38 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
|
+
|
|
3
|
+
.crisp-multiselect-listbox {
|
|
4
|
+
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
5
|
+
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
6
|
+
max-height: 300px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
7
|
+
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
8
|
+
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);
|
|
9
|
+
transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
|
|
10
|
+
}
|
|
11
|
+
.crisp-multiselect-listbox[data-up] { transform-origin: bottom left; }
|
|
12
|
+
.crisp-multiselect-listbox { @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
13
|
+
.crisp-multiselect-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 34px; flex-shrink: 0; margin: calc(-1 * var(--crisp-space-1)) calc(-1 * var(--crisp-space-1)) var(--crisp-space-1); padding: 0 var(--crisp-space-2-5); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
|
|
14
|
+
.crisp-multiselect-search svg { flex-shrink: 0; }
|
|
15
|
+
.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-primary); }
|
|
16
|
+
.crisp-multiselect-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
17
|
+
.crisp-multiselect-option {
|
|
18
|
+
box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-menuRow); flex-shrink: 0;
|
|
19
|
+
padding: 0 var(--crisp-space-2); margin: 0; border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; cursor: pointer; text-align: start;
|
|
20
|
+
}
|
|
21
|
+
.crisp-multiselect-option[data-highlighted] { background: var(--crisp-bg-raised); }
|
|
22
|
+
.crisp-multiselect-option-chip { flex: 0 1 auto; min-width: 0; overflow: hidden; }
|
|
23
|
+
.crisp-multiselect-check { flex-shrink: 0; margin-inline-start: auto; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: var(--crisp-radius-sm); box-shadow: inset 0 0 0 1.5px var(--crisp-border-default); color: transparent; }
|
|
24
|
+
.crisp-multiselect-option[aria-selected="true"] .crisp-multiselect-check { background: var(--crisp-bg-brand-solid); box-shadow: none; color: #fff; }
|
|
25
|
+
.crisp-multiselect-empty { padding: var(--crisp-space-3) var(--crisp-space-2); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
26
|
+
|
|
27
|
+
.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; overflow: hidden; text-overflow: ellipsis; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
28
|
+
.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)); }
|
|
29
|
+
.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)); }
|
|
30
|
+
.crisp-recordstable-tag[data-tone="warning"] { background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); }
|
|
31
|
+
.crisp-recordstable-tag[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); }
|
|
32
|
+
.crisp-recordstable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); }
|
|
33
|
+
.crisp-recordstable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); }
|
|
34
|
+
.crisp-recordstable-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)); }
|
|
35
|
+
|
|
2
36
|
.crisp-multiselect {
|
|
3
37
|
position: relative; display: inline-flex; width: 100%; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
38
|
& .crisp-multiselect-trigger { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; min-width: 0; min-height: var(--crisp-size-menuRow); margin: 0; padding: var(--crisp-space-0-5) var(--crisp-space-1-5) var(--crisp-space-0-5) 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; text-align: start; transition: background-color .12s ease, box-shadow .12s ease; }
|
|
@@ -9,27 +43,12 @@
|
|
|
9
43
|
& .crisp-multiselect-placeholder { color: var(--crisp-fg-muted); }
|
|
10
44
|
& .crisp-multiselect-chevron { flex-shrink: 0; color: var(--crisp-fg-muted); transition: transform .15s ease; }
|
|
11
45
|
& .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); }
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
& .crisp-multiselect-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
19
|
-
& .crisp-multiselect-option { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-menuRow); flex-shrink: 0; padding: 0 var(--crisp-space-2); margin: 0; border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; cursor: pointer; text-align: start; }
|
|
20
|
-
& .crisp-multiselect-option[data-highlighted] { background: var(--crisp-bg-raised); }
|
|
21
|
-
& .crisp-multiselect-option-chip { flex: 0 1 auto; min-width: 0; overflow: hidden; }
|
|
22
|
-
& .crisp-multiselect-check { flex-shrink: 0; margin-inline-start: auto; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: var(--crisp-radius-sm); box-shadow: inset 0 0 0 1.5px var(--crisp-border-default); color: transparent; }
|
|
23
|
-
& .crisp-multiselect-option[aria-selected="true"] .crisp-multiselect-check { background: var(--crisp-bg-brand-solid); box-shadow: none; color: #fff; }
|
|
24
|
-
& .crisp-multiselect-empty { padding: var(--crisp-space-3) var(--crisp-space-2); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
25
|
-
& .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; overflow: hidden; text-overflow: ellipsis; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
|
|
26
|
-
& .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)); }
|
|
27
|
-
& .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)); }
|
|
28
|
-
& .crisp-recordstable-tag[data-tone="warning"] { background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); }
|
|
29
|
-
& .crisp-recordstable-tag[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); }
|
|
30
|
-
& .crisp-recordstable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); }
|
|
31
|
-
& .crisp-recordstable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); }
|
|
32
|
-
& .crisp-recordstable-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)); }
|
|
46
|
+
}
|
|
47
|
+
.crisp-multiselect--invalid_true {
|
|
48
|
+
& .crisp-multiselect-trigger, & .crisp-multiselect-trigger:hover, & .crisp-multiselect-trigger[data-open], & .crisp-multiselect-trigger:focus-visible { box-shadow: inset 0 0 0 1px var(--crisp-bg-danger); }
|
|
49
|
+
}
|
|
50
|
+
.crisp-multiselect--invalid_false {
|
|
51
|
+
|
|
33
52
|
}
|
|
34
53
|
|
|
35
54
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/native/tokens.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// The same tokens the CSS custom properties carry, resolved per theme, with
|
|
3
3
|
// dimensions as numbers for React Native and Lynx style objects.
|
|
4
4
|
export type Theme = "light" | "dark";
|
|
5
|
-
export type ColorTokens = Record<"bgBrandSolid" | "bgBrandSolidPressed" | "fgOnBrand" | "fgOnTone" | "bgSurface" | "bgRaised" | "borderDefault" | "borderSubtle" | "ringNeutral" | "bgTileActive" | "shadowTileActive" | "bgOverlayFrost" | "shadowOverlay1" | "shadowOverlay2" | "shadowOverlay3" | "bgPopover" | "ringPopover" | "shadowPopover1" | "shadowPopover2" | "shadowPopover3" | "fgPrimary" | "fgMuted" | "bgDanger" | "bgDangerSolid" | "strokeFieldFocus" | "fgDisabled" | "bgNeutralWeak" | "bgNeutralInverted" | "fgOnNeutralInverted" | "fgNeutralSubtle" | "fgNeutralMuted" | "strokeFocusRing" | "bgSuccess" | "bgWarning" | "bgOrange" | "bgCyan" | "bgPurple" | "bgSidebar" | "bgSubtle", string>;
|
|
5
|
+
export type ColorTokens = Record<"bgBrandSolid" | "bgBrandSolidPressed" | "fgOnBrand" | "fgOnTone" | "bgSurface" | "bgRaised" | "borderDefault" | "borderSubtle" | "ringNeutral" | "bgTileActive" | "shadowTileActive" | "bgOverlayFrost" | "shadowOverlay1" | "shadowOverlay2" | "shadowOverlay3" | "bgPopover" | "ringPopover" | "shadowPopover1" | "shadowPopover2" | "shadowPopover3" | "fgPrimary" | "fgMuted" | "bgDanger" | "bgDangerSolid" | "strokeFieldFocus" | "fgDisabled" | "bgNeutralWeak" | "bgNeutralInverted" | "fgOnNeutralInverted" | "fgNeutralSubtle" | "fgNeutralMuted" | "strokeFocusRing" | "bgSuccess" | "bgWarning" | "bgOrange" | "bgCyan" | "bgPurple" | "bgSidebar" | "bgSubtle" | "fgBrandSoft" | "fgSuccessSoft" | "fgWarningSoft" | "fgDangerSoft" | "fgNeutralSoft", string>;
|
|
6
6
|
export declare const tokens: {
|
|
7
7
|
color: Record<Theme, ColorTokens>;
|
|
8
8
|
palette: Record<Theme, Record<string, string>>;
|
package/dist/native/tokens.js
CHANGED
|
@@ -42,7 +42,12 @@ export const tokens = {
|
|
|
42
42
|
"bgCyan": "#00b9eb",
|
|
43
43
|
"bgPurple": "#9b69ff",
|
|
44
44
|
"bgSidebar": "#fbfbfb",
|
|
45
|
-
"bgSubtle": "#fbfbfb"
|
|
45
|
+
"bgSubtle": "#fbfbfb",
|
|
46
|
+
"fgBrandSoft": "#2057bd",
|
|
47
|
+
"fgSuccessSoft": "#186b3d",
|
|
48
|
+
"fgWarningSoft": "#80520d",
|
|
49
|
+
"fgDangerSoft": "#a33539",
|
|
50
|
+
"fgNeutralSoft": "#686870"
|
|
46
51
|
},
|
|
47
52
|
"dark": {
|
|
48
53
|
"bgBrandSolid": "#266df0",
|
|
@@ -83,7 +88,12 @@ export const tokens = {
|
|
|
83
88
|
"bgCyan": "#00b9eb",
|
|
84
89
|
"bgPurple": "#9b69ff",
|
|
85
90
|
"bgSidebar": "#0e0f10",
|
|
86
|
-
"bgSubtle": "#0e0f10"
|
|
91
|
+
"bgSubtle": "#0e0f10",
|
|
92
|
+
"fgBrandSoft": "#568df3",
|
|
93
|
+
"fgSuccessSoft": "#2ea968",
|
|
94
|
+
"fgWarningSoft": "#e0982a",
|
|
95
|
+
"fgDangerSoft": "#ff5a5f",
|
|
96
|
+
"fgNeutralSoft": "#9a9aa2"
|
|
87
97
|
}
|
|
88
98
|
},
|
|
89
99
|
"palette": {
|
|
@@ -125,7 +135,12 @@ export const tokens = {
|
|
|
125
135
|
"orange600": "#f97514",
|
|
126
136
|
"cyan600": "#00b9eb",
|
|
127
137
|
"purple600": "#9b69ff",
|
|
128
|
-
"graySidebar": "#fbfbfb"
|
|
138
|
+
"graySidebar": "#fbfbfb",
|
|
139
|
+
"softBrandText": "#2057bd",
|
|
140
|
+
"softSuccessText": "#186b3d",
|
|
141
|
+
"softWarningText": "#80520d",
|
|
142
|
+
"softDangerText": "#a33539",
|
|
143
|
+
"softNeutralText": "#686870"
|
|
129
144
|
},
|
|
130
145
|
"dark": {
|
|
131
146
|
"gray00": "#0a0a0a",
|
|
@@ -165,7 +180,12 @@ export const tokens = {
|
|
|
165
180
|
"orange600": "#f97514",
|
|
166
181
|
"cyan600": "#00b9eb",
|
|
167
182
|
"purple600": "#9b69ff",
|
|
168
|
-
"graySidebar": "#0e0f10"
|
|
183
|
+
"graySidebar": "#0e0f10",
|
|
184
|
+
"softBrandText": "#568df3",
|
|
185
|
+
"softSuccessText": "#2ea968",
|
|
186
|
+
"softWarningText": "#e0982a",
|
|
187
|
+
"softDangerText": "#ff5a5f",
|
|
188
|
+
"softNeutralText": "#9a9aa2"
|
|
169
189
|
}
|
|
170
190
|
},
|
|
171
191
|
"space": {
|
package/dist/popover.css
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
.crisp-popover-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); 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; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
3
|
+
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
4
|
+
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
5
|
+
|
|
1
6
|
.crisp-popover {
|
|
2
7
|
display: contents; font-family: var(--crisp-font-sans);
|
|
3
|
-
& .crisp-popover-content { position: fixed; z-index: 70; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); 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; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
4
|
-
& .crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
5
|
-
& .crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/popover.layered.css
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
|
+
|
|
3
|
+
.crisp-popover-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); 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; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
4
|
+
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
5
|
+
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
6
|
+
|
|
2
7
|
.crisp-popover {
|
|
3
8
|
display: contents; font-family: var(--crisp-font-sans);
|
|
4
|
-
& .crisp-popover-content { position: fixed; z-index: 70; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); 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; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
5
|
-
& .crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
6
|
-
& .crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
@media (prefers-reduced-motion: reduce) {
|