@crisp-ui-kit/crisp 0.33.3 → 0.33.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/checkbox.css +1 -1
  2. package/dist/checkbox.layered.css +1 -1
  3. package/dist/cjs/components/avatargroup/avatargroup.recipe.js +21 -8
  4. package/dist/cjs/components/barchart/barchart.js +6 -1
  5. package/dist/cjs/components/checkbox/checkbox.recipe.js +50 -17
  6. package/dist/cjs/components/datatable/datatable.recipe.js +1 -1
  7. package/dist/cjs/components/datepicker/datepicker.js +7 -1
  8. package/dist/cjs/components/kbd/kbd.recipe.js +22 -9
  9. package/dist/cjs/components/linechart/linechart.js +6 -1
  10. package/dist/cjs/components/skeleton/skeleton.recipe.js +14 -8
  11. package/dist/cjs/components/table/table.js +6 -2
  12. package/dist/cjs/components/textarea/textarea.js +9 -2
  13. package/dist/cjs/components/textarea/textarea.recipe.js +14 -5
  14. package/dist/cjs/components/tooltip/tooltip.recipe.js +27 -6
  15. package/dist/command.css +1 -1
  16. package/dist/command.layered.css +1 -1
  17. package/dist/datatable.css +2 -2
  18. package/dist/datatable.layered.css +2 -2
  19. package/dist/esm/components/avatargroup/avatargroup.recipe.js +21 -8
  20. package/dist/esm/components/barchart/barchart.js +6 -1
  21. package/dist/esm/components/checkbox/checkbox.recipe.js +50 -17
  22. package/dist/esm/components/datatable/datatable.recipe.js +1 -1
  23. package/dist/esm/components/datepicker/datepicker.js +7 -1
  24. package/dist/esm/components/kbd/kbd.recipe.js +22 -9
  25. package/dist/esm/components/linechart/linechart.js +6 -1
  26. package/dist/esm/components/skeleton/skeleton.recipe.js +14 -8
  27. package/dist/esm/components/table/table.js +6 -2
  28. package/dist/esm/components/textarea/textarea.js +9 -2
  29. package/dist/esm/components/textarea/textarea.recipe.js +14 -5
  30. package/dist/esm/components/tooltip/tooltip.recipe.js +27 -6
  31. package/dist/navitem.css +1 -1
  32. package/dist/navitem.layered.css +1 -1
  33. package/dist/sidebar.css +1 -1
  34. package/dist/sidebar.layered.css +1 -1
  35. package/dist/styles.css +8 -8
  36. package/dist/styles.layered.css +8 -8
  37. package/dist/textarea.css +2 -2
  38. package/dist/textarea.layered.css +2 -2
  39. package/dist/types/components/avatargroup/avatargroup.recipe.d.ts +25 -2
  40. package/dist/types/components/checkbox/checkbox.recipe.d.ts +51 -3
  41. package/dist/types/components/kbd/kbd.recipe.d.ts +24 -3
  42. package/dist/types/components/skeleton/skeleton.recipe.d.ts +19 -2
  43. package/dist/types/components/tooltip/tooltip.recipe.d.ts +30 -2
  44. package/package.json +5 -2
@@ -90,7 +90,13 @@ const DatePickerImplementation = React.forwardRef((props, forwardedRef) => {
90
90
  }, ...mergeProps(api.rootProps, rootProps), "aria-label": rootAriaLabel, "aria-labelledby": ariaLabelledby, className: datepickerRecipe({
91
91
  visibleRange: api.visibleRange,
92
92
  className,
93
- }), style: styleOf({ height, minHeight, maxHeight }), children: [api.visibleRange === "continuous" ? (_jsxs("div", { ref: api.refs.continuousScroll, ...api.continuousScrollProps, "data-date-picker-continuous-scroll": "", className: "crisp-datepicker-continuous-scroll", children: [_jsx(WeekdayRow, { api: api, semantic: false }), _jsxs("div", { className: "crisp-datepicker-continuous-content", children: [_jsx("div", { "aria-hidden": "true", className: "datepicker-continuous-spacer", style: { height: api.virtual.topHeight } }), api.months.map((month) => (_jsx(MonthView, { api: api, month: month, renderDateCellContent: renderDateCellContent, renderDateCellSupplement: renderDateCellSupplement, showWeekdays: false, showMonthLabel: true, monthRef: api.refs.continuousMonth(month.key) }, month.key))), _jsx("div", { "aria-hidden": "true", className: "datepicker-continuous-spacer", style: { height: api.virtual.bottomHeight } })] })] })) : (_jsxs(_Fragment, { children: [api.visibleRange !== "twoMonths" && _jsx(Header, { api: api }), _jsx("div", { "data-wheel-open": api.isWheelOpen && api.visibleRange !== "twoMonths"
93
+ }),
94
+ // merged: this sits after the spread above, so assigning it plainly
95
+ // dropped any style the consumer passed. Theirs wins on collision.
96
+ style: {
97
+ ...styleOf({ height, minHeight, maxHeight }),
98
+ ...rootProps?.style,
99
+ }, children: [api.visibleRange === "continuous" ? (_jsxs("div", { ref: api.refs.continuousScroll, ...api.continuousScrollProps, "data-date-picker-continuous-scroll": "", className: "crisp-datepicker-continuous-scroll", children: [_jsx(WeekdayRow, { api: api, semantic: false }), _jsxs("div", { className: "crisp-datepicker-continuous-content", children: [_jsx("div", { "aria-hidden": "true", className: "datepicker-continuous-spacer", style: { height: api.virtual.topHeight } }), api.months.map((month) => (_jsx(MonthView, { api: api, month: month, renderDateCellContent: renderDateCellContent, renderDateCellSupplement: renderDateCellSupplement, showWeekdays: false, showMonthLabel: true, monthRef: api.refs.continuousMonth(month.key) }, month.key))), _jsx("div", { "aria-hidden": "true", className: "datepicker-continuous-spacer", style: { height: api.virtual.bottomHeight } })] })] })) : (_jsxs(_Fragment, { children: [api.visibleRange !== "twoMonths" && _jsx(Header, { api: api }), _jsx("div", { "data-wheel-open": api.isWheelOpen && api.visibleRange !== "twoMonths"
94
100
  ? ""
95
101
  : undefined, "aria-hidden": api.isWheelOpen && api.visibleRange !== "twoMonths"
96
102
  ? true
@@ -1,13 +1,26 @@
1
- import { defineRecipe, resolveRecipe } from "../../core/index.js";
1
+ import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- const config = defineRecipe({
3
+ const spec = defineSpec({
4
4
  name: "kbd",
5
- base: `box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; gap: ${c.space["0.5"]}; min-width: 20px; height: 20px; padding-inline: ${c.space["1"]}; border-radius: ${c.radius.sm}; font-family: ${c.font.sans}; font-size: ${c.text.xs}; font-weight: ${c.weight.regular}; color: color-mix(in srgb, ${c.fgPrimary} 50%, transparent); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 6%, transparent);`,
6
- variants: {},
7
- defaultVariants: {},
8
- compoundVariants: [],
9
- });
10
- export const kbdRecipe = Object.assign(resolveRecipe(config), {
11
- config,
5
+ base: {
6
+ boxSizing: "border-box",
7
+ display: "inline-flex",
8
+ alignItems: "center",
9
+ justifyContent: "center",
10
+ gap: c.space["0.5"],
11
+ minWidth: "20px",
12
+ height: "20px",
13
+ paddingInline: c.space["1"],
14
+ borderRadius: c.radius.sm,
15
+ fontFamily: c.font.sans,
16
+ fontSize: c.text.xs,
17
+ fontWeight: c.weight.regular,
18
+ color: `color-mix(in srgb, ${c.fgPrimary} 50%, transparent)`,
19
+ background: "transparent",
20
+ boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 6%, transparent)`,
21
+ },
12
22
  });
23
+ const config = specToRecipe(spec);
24
+ export const kbdRecipe = Object.assign(resolveRecipe(config), { config });
25
+ export { spec };
13
26
  export default config;
@@ -41,9 +41,14 @@ export function LineChart({ data, height = 240, max, ticks = 5, color, area = tr
41
41
  : "";
42
42
  const summary = ariaLabel ??
43
43
  `Line chart: ${data.map((d) => `${d.label} ${format(d.value)}`).join(", ")}`;
44
- return (_jsxs("div", { className: linechartRecipe({ className }), ...rest, style: {
44
+ return (_jsxs("div", { className: linechartRecipe({ className }), ...rest,
45
+ // merged, not assigned: written plainly this sits AFTER `{...rest}` and
46
+ // overwrites whatever style the consumer passed, so `style={{ maxWidth }}`
47
+ // on the chart did nothing at all. The consumer's wins on collision.
48
+ style: {
45
49
  height,
46
50
  "--crisp-linechart-yaxis-width": yAxisWidthValue,
51
+ ...rest.style,
47
52
  }, role: "img", "aria-label": summary, children: [_jsxs("div", { className: "crisp-linechart-body", children: [_jsx("div", { className: "crisp-linechart-yaxis", children: tickValues.map((t) => (_jsx("span", { className: "crisp-linechart-ytick", style: { bottom: `${(t / top) * 100}%` }, children: format(t) }, t))) }), _jsxs("div", { className: "crisp-linechart-plot", children: [tickValues.map((t) => (_jsx("div", { className: "crisp-linechart-grid", style: { bottom: `${(t / top) * 100}%` } }, t))), pts.length > 1 && (_jsxs("svg", { className: "crisp-linechart-svg", viewBox: "0 0 100 100", preserveAspectRatio: "none", "aria-hidden": "true", children: [area && _jsx("path", { className: "crisp-linechart-area", d: areaPath }), _jsx("polyline", { className: "crisp-linechart-line", points: line, style: { stroke: color } })] })), dots &&
48
53
  pts.map((p, i) => (_jsx("span", { className: "crisp-linechart-dot-html", style: {
49
54
  left: `${p.x}%`,
@@ -1,14 +1,20 @@
1
- import { defineRecipe, resolveRecipe } from "../../core/index.js";
1
+ import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
3
  // A pulsing placeholder block for loading states.
4
- const config = defineRecipe({
4
+ const spec = defineSpec({
5
5
  name: "skeleton",
6
- globalCss: `@keyframes crisp-skeleton { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }`,
7
- base: `display: block; background: color-mix(in srgb, ${c.fgPrimary} 8%, transparent); border-radius: ${c.radius.md}; animation: crisp-skeleton 1.4s ease-in-out infinite;
8
- &[data-circle] { border-radius: ${c.radius.full}; }`,
9
- variants: {},
10
- defaultVariants: {},
11
- compoundVariants: [],
6
+ globalCss: "@keyframes crisp-skeleton { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }",
7
+ base: {
8
+ display: "block",
9
+ background: `color-mix(in srgb, ${c.fgPrimary} 8%, transparent)`,
10
+ borderRadius: c.radius.md,
11
+ animation: "crisp-skeleton 1.4s ease-in-out infinite",
12
+ },
13
+ parts: [
14
+ { selector: "&[data-circle]", decls: { borderRadius: c.radius.full } },
15
+ ],
12
16
  });
17
+ const config = specToRecipe(spec);
13
18
  export const skeletonRecipe = resolveRecipe(config);
19
+ export { spec };
14
20
  export default config;
@@ -8,11 +8,15 @@ import { tableRecipe } from "./table.recipe.js";
8
8
  * `TableHeader`, `TableBody`, `TableFooter`, `TableRow`, `TableHead`,
9
9
  * `TableCell`, and `TableCaption`.
10
10
  */
11
- export const Table = React.forwardRef(({ interactive, surface, className, wrapperClassName, scrollProps, children, ...props }, ref) => (_jsx("div", { className: tableRecipe({
11
+ export const Table = React.forwardRef(({ interactive, surface, className, wrapperClassName, scrollProps, children,
12
+ // on the root for the same reason as Textarea: the wrapper is the box a
13
+ // consumer sees and the scroll container they want to size. Native
14
+ // table attributes still reach the <table> below.
15
+ style, ...props }, ref) => (_jsx("div", { className: tableRecipe({
12
16
  interactive,
13
17
  surface,
14
18
  className: wrapperClassName,
15
- }), children: _jsx("div", { ...scrollProps, className: `crisp-table-scroll${scrollProps?.className ? ` ${scrollProps.className}` : ""}`, children: _jsx("table", { ref: ref, className: className, ...props, children: children }) }) })));
19
+ }), style: style, children: _jsx("div", { ...scrollProps, className: `crisp-table-scroll${scrollProps?.className ? ` ${scrollProps.className}` : ""}`, children: _jsx("table", { ref: ref, className: className, ...props, children: children }) }) })));
16
20
  Table.displayName = "Table";
17
21
  export const TableHeader = React.forwardRef((props, ref) => _jsx("thead", { ref: ref, ...props }));
18
22
  TableHeader.displayName = "TableHeader";
@@ -6,12 +6,19 @@ import { textareaRecipe } from "./textarea.recipe.js";
6
6
  * `<textarea>` prop; pass `showCount` with `maxLength` to render a live
7
7
  * character counter (which turns red if the value exceeds the limit).
8
8
  */
9
- export const Textarea = React.forwardRef(({ showCount, maxLength, className, wrapperClassName, value, defaultValue, onChange, ...props }, ref) => {
9
+ export const Textarea = React.forwardRef(({ showCount, maxLength, className, wrapperClassName, value, defaultValue, onChange,
10
+ // `style` is pulled out and put on the ROOT, the way Input does it.
11
+ // Everything else belongs on the <textarea> -- id, name, form
12
+ // association, aria -- but `style` sizes the visual box, and the box is
13
+ // the root: it carries the focus ring (an ::after on the wrap) and the
14
+ // character counter. Left on the field, `style={{ maxWidth: 480 }}` gave
15
+ // a 480px control inside a full-width ring with the counter stranded.
16
+ style, ...props }, ref) => {
10
17
  const initial = String(value ?? defaultValue ?? "").length;
11
18
  const [count, setCount] = React.useState(initial);
12
19
  const len = value !== undefined ? String(value).length : count;
13
20
  const counted = showCount && maxLength != null;
14
- return (_jsxs("div", { className: textareaRecipe({ className: wrapperClassName }), "data-counted": counted ? "" : undefined, children: [_jsx("span", { className: "crisp-textarea-wrap", children: _jsx("textarea", { ref: ref, className: `crisp-textarea-field${className ? ` ${className}` : ""}`, maxLength: maxLength, value: value, defaultValue: defaultValue, onChange: (e) => {
21
+ return (_jsxs("div", { className: textareaRecipe({ className: wrapperClassName }), style: style, "data-counted": counted ? "" : undefined, children: [_jsx("span", { className: "crisp-textarea-wrap", children: _jsx("textarea", { ref: ref, className: `crisp-textarea-field${className ? ` ${className}` : ""}`, maxLength: maxLength, value: value, defaultValue: defaultValue, onChange: (e) => {
15
22
  if (value === undefined)
16
23
  setCount(e.target.value.length);
17
24
  onChange?.(e);
@@ -1,8 +1,17 @@
1
1
  import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- // A multiline text field, measured from a settings "Personal context" field: an
4
- // inset 1px ring (radius 8), 14px text, 6/10 padding, and an optional character
5
- // counter pinned bottom-right (12px, muted). Focus rings the field brand.
3
+ // A multiline text field: an inset 1px ring (radius 8), 14px text, and an
4
+ // optional character counter pinned bottom-right (12px, muted). Focus rings
5
+ // the field brand.
6
+ //
7
+ // The inset is seed-design's, not Attio's -- the second deliberate divergence
8
+ // after the focus treatment. seed's text-input sets its inline inset to
9
+ // `$dimension.x3_5`, which rootage/dimension.yaml gives as **14px**, against
10
+ // the 10px this had. seed ships no textarea, so only the horizontal inset is
11
+ // theirs to copy; the vertical is derived from it: 10px above and below a
12
+ // 20px line makes a single-line box 40px tall, which is exactly seed's
13
+ // `$dimension.x10` medium field height. The counter's own inset moves to 14px
14
+ // with it, so it lines up with the text rather than sitting 4px inside it.
6
15
  const config = defineRecipe({
7
16
  name: "textarea",
8
17
  base: `
@@ -10,7 +19,7 @@ const config = defineRecipe({
10
19
 
11
20
  & .crisp-textarea-field {
12
21
  box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical;
13
- margin: 0; padding: ${c.space["1.5"]} ${c.space["2.5"]}; border: none; border-radius: ${c.radius.md};
22
+ margin: 0; padding: ${c.space["2.5"]} 14px; border: none; border-radius: ${c.radius.md};
14
23
  background: ${c.bgSurface}; box-shadow: ${e.field};
15
24
  font-family: inherit; font-size: ${c.text.lg}; line-height: 20px; color: ${c.fgPrimary};
16
25
  outline: none; transition: box-shadow .15s ease;
@@ -32,7 +41,7 @@ const config = defineRecipe({
32
41
  &[data-invalid] .crisp-textarea-wrap::after { border-color: ${c.bgDanger}; }
33
42
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: ${c.bgDanger}; }
34
43
  &[data-counted] .crisp-textarea-field { padding-bottom: ${c.space["5"]}; }
35
- & .crisp-textarea-count { position: absolute; inset-inline-end: ${c.space["2.5"]}; bottom: ${c.space["1.5"]}; font-size: ${c.text.sm}; color: ${c.fgMuted}; pointer-events: none; }
44
+ & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: ${c.space["2.5"]}; font-size: ${c.text.sm}; color: ${c.fgMuted}; pointer-events: none; }
36
45
  & .crisp-textarea-count[data-over] { color: ${c.bgDanger}; }
37
46
  `,
38
47
  variants: {},
@@ -1,13 +1,34 @@
1
- import { defineRecipe, resolveRecipe } from "../../core/index.js";
1
+ import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
3
  // The floating bubble for a Tooltip — a dark hint chip. Applied to the
4
4
  // portaled bubble itself (not a wrapper), so its styles survive the portal.
5
- const config = defineRecipe({
5
+ const spec = defineSpec({
6
6
  name: "tooltip",
7
- base: `position: fixed; z-index: 70; box-sizing: border-box; pointer-events: none; max-width: 260px; padding: ${c.space["1"]} ${c.space["2"]}; border-radius: ${c.radius.sm}; background: #20242c; color: #fff; font-family: ${c.font.sans}; font-size: ${c.text.sm}; font-weight: ${c.weight.medium}; line-height: 1.45; box-shadow: 0 4px 14px -2px rgba(28,40,64,0.28), 0 0 0 1px rgba(255,255,255,0.04); opacity: 1; transition: opacity 0.12s ease; @starting-style { opacity: 0; }`,
8
- variants: {},
9
- defaultVariants: {},
10
- compoundVariants: [],
7
+ base: {
8
+ position: "fixed",
9
+ zIndex: 70,
10
+ boxSizing: "border-box",
11
+ pointerEvents: "none",
12
+ maxWidth: "260px",
13
+ padding: `${c.space["1"]} ${c.space["2"]}`,
14
+ borderRadius: c.radius.sm,
15
+ background: "#20242c",
16
+ color: "#fff",
17
+ fontFamily: c.font.sans,
18
+ fontSize: c.text.sm,
19
+ fontWeight: c.weight.medium,
20
+ lineHeight: "1.45",
21
+ boxShadow: "0 4px 14px -2px rgba(28,40,64,0.28), 0 0 0 1px rgba(255,255,255,0.04)",
22
+ opacity: 1,
23
+ transition: "opacity 0.12s ease",
24
+ },
25
+ parts: [
26
+ // An at-rule whose body is declarations rather than rules, so a part
27
+ // expresses it directly: the entry state the overlay animates from.
28
+ { selector: "@starting-style", decls: { opacity: 0 } },
29
+ ],
11
30
  });
31
+ const config = specToRecipe(spec);
12
32
  export const tooltipRecipe = resolveRecipe(config);
33
+ export { spec };
13
34
  export default config;
package/dist/navitem.css CHANGED
@@ -1,5 +1,5 @@
1
1
  .crisp-navitem {
2
- box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5) ; height: 28px; padding-inline: var(--crisp-space-2) ; padding-inline-end: var(--crisp-space-1) ; border-radius: var(--crisp-radius-lg) ; font-family: var(--crisp-font-sans) ; font-size: var(--crisp-text-lg) ; font-weight: var(--crisp-weight-medium) ; letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary) ; text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
2
+ box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding-inline: var(--crisp-space-2); padding-inline-end: var(--crisp-space-1); border-radius: var(--crisp-radius-lg); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary); text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
3
3
  & .crisp-navitem-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4
4
  & .crisp-navitem-trailing { margin-inline-start: auto; display: inline-flex; align-items: center; flex-shrink: 0; }
5
5
  &:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
@@ -1,6 +1,6 @@
1
1
  @layer crisp-components {
2
2
  .crisp-navitem {
3
- box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5) ; height: 28px; padding-inline: var(--crisp-space-2) ; padding-inline-end: var(--crisp-space-1) ; border-radius: var(--crisp-radius-lg) ; font-family: var(--crisp-font-sans) ; font-size: var(--crisp-text-lg) ; font-weight: var(--crisp-weight-medium) ; letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary) ; text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
3
+ box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding-inline: var(--crisp-space-2); padding-inline-end: var(--crisp-space-1); border-radius: var(--crisp-radius-lg); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary); text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
4
4
  & .crisp-navitem-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
5
5
  & .crisp-navitem-trailing { margin-inline-start: auto; display: inline-flex; align-items: center; flex-shrink: 0; }
6
6
  &:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
package/dist/sidebar.css CHANGED
@@ -1,5 +1,5 @@
1
1
  .crisp-sidebar {
2
- box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar) ; border-inline-end: 1px solid var(--crisp-border-subtle) ; padding: var(--crisp-space-2) ; font-family: var(--crisp-font-sans) ; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
2
+ box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar); border-inline-end: 1px solid var(--crisp-border-subtle); padding: var(--crisp-space-2); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
3
3
  & .crisp-sidebar-section { display: flex; flex-direction: column; gap: var(--crisp-space-px); margin-top: var(--crisp-space-2); }
4
4
  & .crisp-sidebar-section[data-collapsed] { display: none; }
5
5
  & .crisp-sidebar-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); }
@@ -1,6 +1,6 @@
1
1
  @layer crisp-components {
2
2
  .crisp-sidebar {
3
- box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar) ; border-inline-end: 1px solid var(--crisp-border-subtle) ; padding: var(--crisp-space-2) ; font-family: var(--crisp-font-sans) ; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
3
+ box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar); border-inline-end: 1px solid var(--crisp-border-subtle); padding: var(--crisp-space-2); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
4
4
  & .crisp-sidebar-section { display: flex; flex-direction: column; gap: var(--crisp-space-px); margin-top: var(--crisp-space-2); }
5
5
  & .crisp-sidebar-section[data-collapsed] { display: none; }
6
6
  & .crisp-sidebar-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); }
package/dist/styles.css CHANGED
@@ -483,7 +483,7 @@
483
483
  }
484
484
 
485
485
  .crisp-checkbox {
486
- appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: var(--crisp-radius-sm) ; background: var(--crisp-bg-surface) ; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s;
486
+ appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s;
487
487
  &:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 30%, transparent); }
488
488
  &:checked, &:indeterminate { background: var(--crisp-bg-brand-solid) center / 10px no-repeat; box-shadow: none; }
489
489
  &:checked { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
@@ -559,9 +559,9 @@
559
559
  & .crisp-datatable-search input::placeholder { color: var(--crisp-fg-muted); }
560
560
  & .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
561
561
  & .crisp-datatable-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
562
- /* The header cell has no padding of its own -- the button owns the /* announced, never drawn */
562
+ /* announced, never drawn */
563
563
  & .crisp-datatable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
564
- full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. */
564
+ /* The header cell has no padding of its own -- the button owns the full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. */
565
565
  & th { padding: 0; }
566
566
  /* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
567
567
  Menu wraps its trigger in a flex div that sizes to its content, so a
@@ -1531,7 +1531,7 @@
1531
1531
 
1532
1532
  .crisp-textarea {
1533
1533
  position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
1534
- & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-1-5) var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1534
+ & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1535
1535
  & .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
1536
1536
  & .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
1537
1537
  /* seed-design's focus treatment, same as Input: a 2px ring on an ::after
@@ -1547,7 +1547,7 @@
1547
1547
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
1548
1548
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
1549
1549
  &[data-counted] .crisp-textarea-field { padding-bottom: var(--crisp-space-5); }
1550
- & .crisp-textarea-count { position: absolute; inset-inline-end: var(--crisp-space-2-5); bottom: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
1550
+ & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: var(--crisp-space-2-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
1551
1551
  & .crisp-textarea-count[data-over] { color: var(--crisp-bg-danger); }
1552
1552
  }
1553
1553
 
@@ -1717,7 +1717,7 @@
1717
1717
  }
1718
1718
 
1719
1719
  .crisp-command {
1720
- display: contents; font-family: var(--crisp-font-sans) ;
1720
+ display: contents; font-family: var(--crisp-font-sans);
1721
1721
  & .crisp-command-content, & .crisp-command-card { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1722
1722
  & .crisp-command-backdrop { position: fixed; inset: 0; z-index: 50; background: transparent; }
1723
1723
  & .crisp-command-positioner { position: fixed; inset: 0; z-index: 51; display: flex; align-items: flex-start; justify-content: center; padding: 15vh var(--crisp-space-4) var(--crisp-space-4); }
@@ -1859,7 +1859,7 @@
1859
1859
  }
1860
1860
 
1861
1861
  .crisp-navitem {
1862
- box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5) ; height: 28px; padding-inline: var(--crisp-space-2) ; padding-inline-end: var(--crisp-space-1) ; border-radius: var(--crisp-radius-lg) ; font-family: var(--crisp-font-sans) ; font-size: var(--crisp-text-lg) ; font-weight: var(--crisp-weight-medium) ; letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary) ; text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
1862
+ box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding-inline: var(--crisp-space-2); padding-inline-end: var(--crisp-space-1); border-radius: var(--crisp-radius-lg); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary); text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
1863
1863
  & .crisp-navitem-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1864
1864
  & .crisp-navitem-trailing { margin-inline-start: auto; display: inline-flex; align-items: center; flex-shrink: 0; }
1865
1865
  &:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
@@ -2380,7 +2380,7 @@
2380
2380
  }
2381
2381
 
2382
2382
  .crisp-sidebar {
2383
- box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar) ; border-inline-end: 1px solid var(--crisp-border-subtle) ; padding: var(--crisp-space-2) ; font-family: var(--crisp-font-sans) ; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
2383
+ box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar); border-inline-end: 1px solid var(--crisp-border-subtle); padding: var(--crisp-space-2); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
2384
2384
  & .crisp-sidebar-section { display: flex; flex-direction: column; gap: var(--crisp-space-px); margin-top: var(--crisp-space-2); }
2385
2385
  & .crisp-sidebar-section[data-collapsed] { display: none; }
2386
2386
  & .crisp-sidebar-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); }
@@ -484,7 +484,7 @@
484
484
  }
485
485
 
486
486
  .crisp-checkbox {
487
- appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: var(--crisp-radius-sm) ; background: var(--crisp-bg-surface) ; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s;
487
+ appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s;
488
488
  &:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 30%, transparent); }
489
489
  &:checked, &:indeterminate { background: var(--crisp-bg-brand-solid) center / 10px no-repeat; box-shadow: none; }
490
490
  &:checked { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
@@ -560,9 +560,9 @@
560
560
  & .crisp-datatable-search input::placeholder { color: var(--crisp-fg-muted); }
561
561
  & .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
562
562
  & .crisp-datatable-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
563
- /* The header cell has no padding of its own -- the button owns the /* announced, never drawn */
563
+ /* announced, never drawn */
564
564
  & .crisp-datatable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
565
- full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. */
565
+ /* The header cell has no padding of its own -- the button owns the full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. */
566
566
  & th { padding: 0; }
567
567
  /* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
568
568
  Menu wraps its trigger in a flex div that sizes to its content, so a
@@ -1532,7 +1532,7 @@
1532
1532
 
1533
1533
  .crisp-textarea {
1534
1534
  position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
1535
- & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-1-5) var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1535
+ & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1536
1536
  & .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
1537
1537
  & .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
1538
1538
  /* seed-design's focus treatment, same as Input: a 2px ring on an ::after
@@ -1548,7 +1548,7 @@
1548
1548
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
1549
1549
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
1550
1550
  &[data-counted] .crisp-textarea-field { padding-bottom: var(--crisp-space-5); }
1551
- & .crisp-textarea-count { position: absolute; inset-inline-end: var(--crisp-space-2-5); bottom: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
1551
+ & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: var(--crisp-space-2-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
1552
1552
  & .crisp-textarea-count[data-over] { color: var(--crisp-bg-danger); }
1553
1553
  }
1554
1554
 
@@ -1718,7 +1718,7 @@
1718
1718
  }
1719
1719
 
1720
1720
  .crisp-command {
1721
- display: contents; font-family: var(--crisp-font-sans) ;
1721
+ display: contents; font-family: var(--crisp-font-sans);
1722
1722
  & .crisp-command-content, & .crisp-command-card { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1723
1723
  & .crisp-command-backdrop { position: fixed; inset: 0; z-index: 50; background: transparent; }
1724
1724
  & .crisp-command-positioner { position: fixed; inset: 0; z-index: 51; display: flex; align-items: flex-start; justify-content: center; padding: 15vh var(--crisp-space-4) var(--crisp-space-4); }
@@ -1860,7 +1860,7 @@
1860
1860
  }
1861
1861
 
1862
1862
  .crisp-navitem {
1863
- box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5) ; height: 28px; padding-inline: var(--crisp-space-2) ; padding-inline-end: var(--crisp-space-1) ; border-radius: var(--crisp-radius-lg) ; font-family: var(--crisp-font-sans) ; font-size: var(--crisp-text-lg) ; font-weight: var(--crisp-weight-medium) ; letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary) ; text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
1863
+ box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding-inline: var(--crisp-space-2); padding-inline-end: var(--crisp-space-1); border-radius: var(--crisp-radius-lg); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; line-height: 20px; color: var(--crisp-fg-primary); text-decoration: none; cursor: pointer; user-select: none; width: 100%; transition: background-color 0.16s;
1864
1864
  & .crisp-navitem-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1865
1865
  & .crisp-navitem-trailing { margin-inline-start: auto; display: inline-flex; align-items: center; flex-shrink: 0; }
1866
1866
  &:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); }
@@ -2381,7 +2381,7 @@
2381
2381
  }
2382
2382
 
2383
2383
  .crisp-sidebar {
2384
- box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar) ; border-inline-end: 1px solid var(--crisp-border-subtle) ; padding: var(--crisp-space-2) ; font-family: var(--crisp-font-sans) ; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
2384
+ box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--crisp-bg-sidebar); border-inline-end: 1px solid var(--crisp-border-subtle); padding: var(--crisp-space-2); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto;
2385
2385
  & .crisp-sidebar-section { display: flex; flex-direction: column; gap: var(--crisp-space-px); margin-top: var(--crisp-space-2); }
2386
2386
  & .crisp-sidebar-section[data-collapsed] { display: none; }
2387
2387
  & .crisp-sidebar-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-0-5); }
package/dist/textarea.css CHANGED
@@ -1,6 +1,6 @@
1
1
  .crisp-textarea {
2
2
  position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
3
- & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-1-5) var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
3
+ & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
4
4
  & .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
5
5
  & .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
6
6
  /* seed-design's focus treatment, same as Input: a 2px ring on an ::after
@@ -16,7 +16,7 @@
16
16
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
17
17
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
18
18
  &[data-counted] .crisp-textarea-field { padding-bottom: var(--crisp-space-5); }
19
- & .crisp-textarea-count { position: absolute; inset-inline-end: var(--crisp-space-2-5); bottom: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
19
+ & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: var(--crisp-space-2-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
20
20
  & .crisp-textarea-count[data-over] { color: var(--crisp-bg-danger); }
21
21
  }
22
22
 
@@ -1,7 +1,7 @@
1
1
  @layer crisp-components {
2
2
  .crisp-textarea {
3
3
  position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
4
- & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-1-5) var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
4
+ & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
5
5
  & .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
6
6
  & .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
7
7
  /* seed-design's focus treatment, same as Input: a 2px ring on an ::after
@@ -17,7 +17,7 @@
17
17
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
18
18
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
19
19
  &[data-counted] .crisp-textarea-field { padding-bottom: var(--crisp-space-5); }
20
- & .crisp-textarea-count { position: absolute; inset-inline-end: var(--crisp-space-2-5); bottom: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
20
+ & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: var(--crisp-space-2-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
21
21
  & .crisp-textarea-count[data-over] { color: var(--crisp-bg-danger); }
22
22
  }
23
23
 
@@ -1,3 +1,26 @@
1
- declare const config: import("../..").RecipeConfig<{}>;
2
- export declare const avatargroupRecipe: import("../..").RecipeFn<{}>;
1
+ declare const spec: {
2
+ readonly name: "avatargroup";
3
+ readonly base: {
4
+ readonly display: "inline-flex";
5
+ readonly alignItems: "center";
6
+ };
7
+ readonly parts: [{
8
+ readonly slot: "member";
9
+ readonly selector: "& > *";
10
+ readonly decls: {
11
+ readonly marginInlineStart: `-var(--${string})`;
12
+ readonly boxShadow: `0 0 0 2px var(--${string})`;
13
+ readonly position: "relative";
14
+ };
15
+ }, {
16
+ readonly slot: "member";
17
+ readonly selector: "& > *:first-child";
18
+ readonly decls: {
19
+ readonly marginInlineStart: 0;
20
+ };
21
+ }];
22
+ };
23
+ declare const config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
24
+ export declare const avatargroupRecipe: import("../..").RecipeFn<Record<string, Record<string, string>>>;
25
+ export { spec };
3
26
  export default config;
@@ -1,5 +1,53 @@
1
- declare const config: import("../..").RecipeConfig<{}>;
2
- export declare const checkboxRecipe: import("../..").RecipeFn<{}> & {
3
- config: import("../..").RecipeConfig<{}>;
1
+ declare const spec: {
2
+ readonly name: "checkbox";
3
+ readonly base: {
4
+ readonly appearance: "none";
5
+ readonly WebkitAppearance: "none";
6
+ readonly boxSizing: "border-box";
7
+ readonly flexShrink: 0;
8
+ readonly margin: 0;
9
+ readonly width: "16px";
10
+ readonly height: "16px";
11
+ readonly border: "none";
12
+ readonly borderRadius: `var(--${string})`;
13
+ readonly background: `var(--${string})`;
14
+ readonly boxShadow: `inset 0 0 0 1px color-mix(in srgb, var(--${string}) 9%, transparent)`;
15
+ readonly cursor: "pointer";
16
+ readonly transition: "background-color .12s, box-shadow .12s";
17
+ };
18
+ readonly parts: [{
19
+ readonly selector: "&:hover";
20
+ readonly decls: {
21
+ readonly boxShadow: `inset 0 0 0 1px color-mix(in srgb, var(--${string}) 30%, transparent)`;
22
+ };
23
+ }, {
24
+ readonly selector: "&:checked, &:indeterminate";
25
+ readonly decls: {
26
+ readonly background: `var(--${string}) center / 10px no-repeat`;
27
+ readonly boxShadow: "none";
28
+ };
29
+ }, {
30
+ readonly selector: "&:checked";
31
+ readonly decls: {
32
+ backgroundImage: "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\")";
33
+ };
34
+ }, {
35
+ readonly selector: "&:indeterminate";
36
+ readonly decls: {
37
+ readonly backgroundImage: `linear-gradient(var(--${string}), var(--${string}))`;
38
+ readonly backgroundSize: "8px 2px";
39
+ };
40
+ }, {
41
+ readonly selector: "&:focus-visible";
42
+ readonly decls: {
43
+ readonly outline: `2px solid var(--${string})`;
44
+ readonly outlineOffset: "1px";
45
+ };
46
+ }];
4
47
  };
48
+ declare const config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
49
+ export declare const checkboxRecipe: import("../..").RecipeFn<Record<string, Record<string, string>>> & {
50
+ config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
51
+ };
52
+ export { spec };
5
53
  export default config;
@@ -1,5 +1,26 @@
1
- declare const config: import("../..").RecipeConfig<{}>;
2
- export declare const kbdRecipe: import("../..").RecipeFn<{}> & {
3
- config: import("../..").RecipeConfig<{}>;
1
+ declare const spec: {
2
+ readonly name: "kbd";
3
+ readonly base: {
4
+ readonly boxSizing: "border-box";
5
+ readonly display: "inline-flex";
6
+ readonly alignItems: "center";
7
+ readonly justifyContent: "center";
8
+ readonly gap: `var(--${string})`;
9
+ readonly minWidth: "20px";
10
+ readonly height: "20px";
11
+ readonly paddingInline: `var(--${string})`;
12
+ readonly borderRadius: `var(--${string})`;
13
+ readonly fontFamily: `var(--${string})`;
14
+ readonly fontSize: `var(--${string})`;
15
+ readonly fontWeight: `var(--${string})`;
16
+ readonly color: `color-mix(in srgb, var(--${string}) 50%, transparent)`;
17
+ readonly background: "transparent";
18
+ readonly boxShadow: `inset 0 0 0 1px color-mix(in srgb, var(--${string}) 6%, transparent)`;
19
+ };
4
20
  };
21
+ declare const config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
22
+ export declare const kbdRecipe: import("../..").RecipeFn<Record<string, Record<string, string>>> & {
23
+ config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
24
+ };
25
+ export { spec };
5
26
  export default config;
@@ -1,3 +1,20 @@
1
- declare const config: import("../..").RecipeConfig<{}>;
2
- export declare const skeletonRecipe: import("../..").RecipeFn<{}>;
1
+ declare const spec: {
2
+ readonly name: "skeleton";
3
+ readonly globalCss: "@keyframes crisp-skeleton { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }";
4
+ readonly base: {
5
+ readonly display: "block";
6
+ readonly background: `color-mix(in srgb, var(--${string}) 8%, transparent)`;
7
+ readonly borderRadius: `var(--${string})`;
8
+ readonly animation: "crisp-skeleton 1.4s ease-in-out infinite";
9
+ };
10
+ readonly parts: [{
11
+ readonly selector: "&[data-circle]";
12
+ readonly decls: {
13
+ borderRadius: `var(--${string})`;
14
+ };
15
+ }];
16
+ };
17
+ declare const config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
18
+ export declare const skeletonRecipe: import("../..").RecipeFn<Record<string, Record<string, string>>>;
19
+ export { spec };
3
20
  export default config;