@signal9/era-ui 30.7.0 → 31.0.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/ai/conversations/conversations-item.svelte +1 -1
  3. package/dist/ai/plan/plan-header.svelte +1 -1
  4. package/dist/ai/prompt-input/prompt-input-attachments.svelte +2 -6
  5. package/dist/ai/swarm/swarm-node.svelte +1 -1
  6. package/dist/ai/todo/todo-header.svelte +1 -1
  7. package/dist/ai/todo/todo-item.svelte +1 -1
  8. package/dist/ai/tool/tool-chip.svelte +1 -1
  9. package/dist/ai/web-preview/web-preview.svelte +1 -1
  10. package/dist/dev/audit/audits/wall-is-isotropic.js +1 -1
  11. package/dist/docs/css-utilities.js +7 -3
  12. package/dist/era-ui.css +1 -1
  13. package/dist/generated-docs/badge.md +1 -1
  14. package/dist/generated-docs/bar.md +22 -4
  15. package/dist/generated-docs/button.md +38 -4
  16. package/dist/generated-docs/card.md +35 -5
  17. package/dist/generated-docs/chip.md +16 -0
  18. package/dist/generated-docs/llms-full.txt +310 -49
  19. package/dist/generated-docs/llms.txt +4 -3
  20. package/dist/generated-docs/manifest.json +45 -21
  21. package/dist/generated-docs/meter.md +79 -1
  22. package/dist/generated-docs/nav.md +8 -1
  23. package/dist/generated-docs/separator.md +18 -0
  24. package/dist/generated-docs/utilities.json +32 -9
  25. package/dist/generated-docs/utilities.md +89 -30
  26. package/dist/styles/density.css +15 -25
  27. package/dist/styles/index.css +32 -27
  28. package/dist/ui/accordion/accordion-trigger.svelte +1 -1
  29. package/dist/ui/alert-dialog/alert-dialog-action.svelte +2 -0
  30. package/dist/ui/alert-dialog/alert-dialog-cancel.svelte +2 -0
  31. package/dist/ui/badge/badge.svelte +8 -2
  32. package/dist/ui/badge/badge.svelte.d.ts +1 -1
  33. package/dist/ui/bar/bar.svelte +95 -26
  34. package/dist/ui/bar/bar.svelte.d.ts +71 -31
  35. package/dist/ui/button/button.svelte +38 -2
  36. package/dist/ui/button/button.svelte.d.ts +29 -0
  37. package/dist/ui/button/index.d.ts +2 -0
  38. package/dist/ui/button/variants.js +4 -9
  39. package/dist/ui/calendar/calendar-day.svelte +1 -1
  40. package/dist/ui/card/card.svelte +22 -9
  41. package/dist/ui/card/card.svelte.d.ts +19 -7
  42. package/dist/ui/chip/chip.svelte +5 -2
  43. package/dist/ui/chip/chip.svelte.d.ts +6 -6
  44. package/dist/ui/collapsible/collapsible-trigger.svelte +1 -1
  45. package/dist/ui/combobox/combobox-trigger.svelte +1 -1
  46. package/dist/ui/command/command-item.svelte +1 -1
  47. package/dist/ui/command/command-link-item.svelte +1 -1
  48. package/dist/ui/command/command-root.svelte +3 -5
  49. package/dist/ui/date-field/date-field-segment.svelte +1 -1
  50. package/dist/ui/date-picker/date-picker-day.svelte +1 -1
  51. package/dist/ui/date-picker/date-picker-segment.svelte +1 -1
  52. package/dist/ui/date-picker/date-picker-trigger.svelte +1 -1
  53. package/dist/ui/date-range-field/date-range-field-segment.svelte +1 -1
  54. package/dist/ui/date-range-picker/date-range-picker-day.svelte +1 -1
  55. package/dist/ui/date-range-picker/date-range-picker-segment.svelte +1 -1
  56. package/dist/ui/date-range-picker/date-range-picker-trigger.svelte +1 -1
  57. package/dist/ui/dialog/dialog-close.svelte +2 -0
  58. package/dist/ui/dialog/dialog-content.svelte +19 -1
  59. package/dist/ui/dropdown-menu/dropdown-menu-trigger.svelte +1 -1
  60. package/dist/ui/file-upload/file-upload.svelte +1 -1
  61. package/dist/ui/input/variants.d.ts +6 -6
  62. package/dist/ui/input/variants.js +2 -2
  63. package/dist/ui/kv/kv.svelte +1 -1
  64. package/dist/ui/menubar/menubar-root.svelte +1 -1
  65. package/dist/ui/menubar/menubar-trigger.svelte +1 -1
  66. package/dist/ui/nav/nav-bar.svelte +9 -4
  67. package/dist/ui/nav/nav-bar.svelte.d.ts +2 -1
  68. package/dist/ui/pane/pane-root.svelte +3 -12
  69. package/dist/ui/pane/pane-tab.svelte +1 -1
  70. package/dist/ui/select/select-trigger.svelte +1 -1
  71. package/dist/ui/slider/slider-thumb.svelte +1 -1
  72. package/dist/ui/step/step-summary.svelte +1 -1
  73. package/dist/ui/switch/switch.svelte +2 -2
  74. package/dist/ui/time-field/time-field-segment.svelte +1 -1
  75. package/dist/ui/time-range-field/time-range-field-segment.svelte +1 -1
  76. package/dist/ui/timeline/timeline-step.svelte +1 -1
  77. package/dist/ui/toggle-group/toggle-group-item.svelte +2 -2
  78. package/dist/ui/toggle-group/toggle-group-item.svelte.d.ts +6 -6
  79. package/dist/ui/toggle-group/toggle-group-root.svelte +1 -2
  80. package/dist/ui/toggle-group/toggle-group-root.svelte.d.ts +3 -3
  81. package/dist/ui/tooltip/tooltip-content.svelte +1 -1
  82. package/dist/ui/tree/tree-item.svelte +1 -1
  83. package/dist/ui/video-player/video-player.svelte +1 -1
  84. package/dist/utils/tw-merge-config.d.ts +3 -0
  85. package/dist/utils/tw-merge-config.js +4 -0
  86. package/package.json +4 -3
  87. package/skill/SKILL.md +17 -17
@@ -10,7 +10,7 @@ export declare const cardVariants: import("tailwind-variants").TVReturnType<{
10
10
  false: "p-card";
11
11
  };
12
12
  interactive: {
13
- true: "cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight active:shadow-pressed era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
13
+ true: "cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight active:shadow-pressed [&:active>[data-card-content]]:translate-x-(--era-press-sink-x) [&:active>[data-card-content]]:translate-y-(--era-press-sink-y) era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
14
14
  };
15
15
  }, undefined, "block w-full rounded-bar text-left text-fg", {
16
16
  tone: {
@@ -24,7 +24,7 @@ export declare const cardVariants: import("tailwind-variants").TVReturnType<{
24
24
  false: "p-card";
25
25
  };
26
26
  interactive: {
27
- true: "cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight active:shadow-pressed era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
27
+ true: "cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight active:shadow-pressed [&:active>[data-card-content]]:translate-x-(--era-press-sink-x) [&:active>[data-card-content]]:translate-y-(--era-press-sink-y) era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
28
28
  };
29
29
  }, undefined, import("tailwind-variants").TVReturnTypeLike<{
30
30
  tone: {
@@ -38,7 +38,7 @@ export declare const cardVariants: import("tailwind-variants").TVReturnType<{
38
38
  false: "p-card";
39
39
  };
40
40
  interactive: {
41
- true: "cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight active:shadow-pressed era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
41
+ true: "cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight active:shadow-pressed [&:active>[data-card-content]]:translate-x-(--era-press-sink-x) [&:active>[data-card-content]]:translate-y-(--era-press-sink-y) era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
42
42
  };
43
43
  }, undefined>>;
44
44
  import type { Snippet } from 'svelte';
@@ -72,10 +72,22 @@ type $$ComponentProps = HTMLAttributes<HTMLElement> & AnchorBits & ButtonBits &
72
72
  * A CARD THAT IS PRESSABLE SHOULD USUALLY BE `elevated`. Passing `href`
73
73
  * or `onclick` turns on the interactive face — hover, focus, press — but
74
74
  * it deliberately does NOT override the tier you asked for, so a
75
- * `surface` link card has no resting lift and reads flatter than the
76
- * static cards around it. That combination was reported as a bug and it
77
- * is a choice: a tone that silently changed under an event handler would
78
- * be a worse one.
75
+ * `surface` link card does not get the raised tier's separation and can
76
+ * read flatter than the static cards around it. That combination was
77
+ * reported as a bug and it is a choice: a tone that silently changed
78
+ * under an event handler would be a worse one.
79
+ *
80
+ * HOW THE TIERS DIFFER IS SURFACE-DEPENDENT, so do not go looking for a
81
+ * fill difference on every surface. `base` mixes the elevated fill 6%
82
+ * toward `--color-bright` and adds a resting shadow, so there the tiers
83
+ * differ in COLOUR. `bevel` sets `--era-surface-bg-elevated` to
84
+ * `--era-surface-bg` outright — elevation is a chisel, not a tone, which
85
+ * is bevel's whole premise — so `surface` and `elevated` paint the
86
+ * IDENTICAL fill there and differ only in relief. A consumer measured
87
+ * exactly that on 30.8.0 bevel: both tones `oklch(0.195 0 none)` in dark,
88
+ * `0.863` in light, one variable, side by side. `glass` splits the tiers
89
+ * its own way again. So the tier is real on every surface; the thing
90
+ * carrying it is not always the fill.
79
91
  */
80
92
  tone?: 'elevated' | 'surface' | 'well' | 'flat';
81
93
  /** Rendered above the body with a subtle divider. */
@@ -16,8 +16,8 @@
16
16
  base: 'inline-flex shrink-0 items-center bg-fill font-mono text-body leading-none whitespace-nowrap text-fg shadow-sm',
17
17
  variants: {
18
18
  size: {
19
- chip: 'h-chip min-w-chip rounded-chip pl-chip',
20
- pill: 'h-pill min-w-pill rounded-pill pl-pill'
19
+ chip: 'min-w-chip tier-chip pl-chip',
20
+ pill: 'min-w-pill tier-pill pl-pill'
21
21
  },
22
22
  dismissible: { true: '', false: '' }
23
23
  },
@@ -110,6 +110,8 @@
110
110
 
111
111
  <div
112
112
  bind:this={ref}
113
+ data-era-geometry="bounded"
114
+ data-era-tier={size}
113
115
  class={cn(chipVariants({ size, dismissible: !!ondismiss }), className)}
114
116
  {...restProps}
115
117
  >
@@ -156,6 +158,7 @@
156
158
  <Button
157
159
  icon
158
160
  size="pill"
161
+ topology={size === 'pill' ? 'docked' : 'bounded'}
159
162
  tone="destructive"
160
163
  class={size === 'pill' ? 'rounded-l-none' : undefined}
161
164
  onclick={ondismiss}
@@ -1,7 +1,7 @@
1
1
  export declare const chipVariants: import("tailwind-variants").TVReturnType<{
2
2
  size: {
3
- chip: "h-chip min-w-chip rounded-chip pl-chip";
4
- pill: "h-pill min-w-pill rounded-pill pl-pill";
3
+ chip: "min-w-chip tier-chip pl-chip";
4
+ pill: "min-w-pill tier-pill pl-pill";
5
5
  };
6
6
  dismissible: {
7
7
  true: "";
@@ -9,8 +9,8 @@ export declare const chipVariants: import("tailwind-variants").TVReturnType<{
9
9
  };
10
10
  }, undefined, "inline-flex shrink-0 items-center bg-fill font-mono text-body leading-none whitespace-nowrap text-fg shadow-sm", {
11
11
  size: {
12
- chip: "h-chip min-w-chip rounded-chip pl-chip";
13
- pill: "h-pill min-w-pill rounded-pill pl-pill";
12
+ chip: "min-w-chip tier-chip pl-chip";
13
+ pill: "min-w-pill tier-pill pl-pill";
14
14
  };
15
15
  dismissible: {
16
16
  true: "";
@@ -18,8 +18,8 @@ export declare const chipVariants: import("tailwind-variants").TVReturnType<{
18
18
  };
19
19
  }, undefined, import("tailwind-variants").TVReturnTypeLike<{
20
20
  size: {
21
- chip: "h-chip min-w-chip rounded-chip pl-chip";
22
- pill: "h-pill min-w-pill rounded-pill pl-pill";
21
+ chip: "min-w-chip tier-chip pl-chip";
22
+ pill: "min-w-pill tier-pill pl-pill";
23
23
  };
24
24
  dismissible: {
25
25
  true: "";
@@ -13,7 +13,7 @@
13
13
  <Collapsible.Trigger
14
14
  bind:ref
15
15
  class={cn(
16
- 'flex h-control w-full items-center rounded-control px-inset-control text-body text-fg hover:bg-highlight focus:outline-none disabled:opacity-50',
16
+ 'flex tier-control w-full items-center px-inset-control text-body text-fg hover:bg-highlight focus:outline-none disabled:opacity-50',
17
17
  className
18
18
  )}
19
19
  {...restProps}
@@ -14,7 +14,7 @@
14
14
  <Combobox.Trigger
15
15
  bind:ref
16
16
  class={cn(
17
- 'flex size-control shrink-0 items-center justify-center rounded-control text-muted focus:outline-none',
17
+ 'flex tier-control w-control shrink-0 items-center justify-center text-muted focus:outline-none',
18
18
  className
19
19
  )}
20
20
  {...restProps}
@@ -8,7 +8,7 @@
8
8
  <Command.Item
9
9
  bind:ref
10
10
  class={cn(
11
- 'flex h-control cursor-pointer items-center gap-gutter rounded-control px-inset-control text-body leading-none text-fg outline-none select-none not-has-[svg]:era-label-ink data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[selected]:bg-highlight',
11
+ 'flex tier-control cursor-pointer items-center gap-gutter px-inset-control text-body leading-none text-fg outline-none select-none not-has-[svg]:era-label-ink data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[selected]:bg-highlight',
12
12
  className
13
13
  )}
14
14
  {...restProps}
@@ -8,7 +8,7 @@
8
8
  <Command.LinkItem
9
9
  bind:ref
10
10
  class={cn(
11
- 'flex h-control cursor-pointer items-center gap-gutter rounded-control px-inset-control text-body leading-none text-fg no-underline outline-none select-none not-has-[svg]:era-label-ink data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[selected]:bg-highlight',
11
+ 'flex tier-control cursor-pointer items-center gap-gutter px-inset-control text-body leading-none text-fg no-underline outline-none select-none not-has-[svg]:era-label-ink data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[selected]:bg-highlight',
12
12
  className
13
13
  )}
14
14
  {...restProps}
@@ -24,13 +24,11 @@
24
24
  // glass-blur, like every other floating panel (menus, dialogs, pickers):
25
25
  // inert on opaque surfaces, blurs the backdrop when the palette floats.
26
26
  !bare &&
27
- // [--era-container-rd:…] publishes this panel's own radius, so the rows
28
- // inside re-derive against rd-bar rather than the rd-control default.
29
- // rd-bar − gutter IS rd-control, so the palette renders unchanged; what
30
- // changes is that the rows now say WHY they are that radius.
27
+ // The panel is unbounded chrome; its bounded command rows carry their own
28
+ // control tier rather than inheriting geometry from this ancestor.
31
29
  // No border: --era-shadow-lg is the edge on every surface, and a border
32
30
  // alongside it draws two hairlines of the same colour on flat.
33
- 'overflow-hidden rounded-bar bg-well p-gutter shadow-lg glass-blur [--era-container-rd:var(--era-rd-bar)]',
31
+ 'overflow-hidden rounded-bar bg-well p-gutter shadow-lg glass-blur',
34
32
  className
35
33
  )}
36
34
  {...restProps}
@@ -18,7 +18,7 @@
18
18
  <DateField.Segment
19
19
  bind:ref
20
20
  class={cn(
21
- 'era-token-ink h-chip rounded-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
21
+ 'era-token-ink tier-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
22
22
  className
23
23
  )}
24
24
  {...restProps}
@@ -8,7 +8,7 @@
8
8
  <DatePicker.Day
9
9
  bind:ref
10
10
  class={cn(
11
- 'inline-flex size-control cursor-default items-center justify-center rounded-control text-body text-fg hover:bg-highlight focus:outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[outside-month]:pointer-events-none data-[outside-month]:text-muted/40 data-[selected]:bg-hover data-[selected]:text-bright data-[unavailable]:text-muted data-[unavailable]:line-through',
11
+ 'inline-flex tier-control w-control cursor-default items-center justify-center text-body text-fg hover:bg-highlight focus:outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[outside-month]:pointer-events-none data-[outside-month]:text-muted/40 data-[selected]:bg-hover data-[selected]:text-bright data-[unavailable]:text-muted data-[unavailable]:line-through',
12
12
  className
13
13
  )}
14
14
  {...restProps}
@@ -18,7 +18,7 @@
18
18
  <DatePicker.Segment
19
19
  bind:ref
20
20
  class={cn(
21
- 'era-token-ink h-chip rounded-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
21
+ 'era-token-ink tier-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
22
22
  className
23
23
  )}
24
24
  {...restProps}
@@ -14,7 +14,7 @@
14
14
  <DatePicker.Trigger
15
15
  bind:ref
16
16
  class={cn(
17
- 'ml-auto flex size-chip shrink-0 items-center justify-center rounded-chip text-muted hover:bg-highlight hover:text-fg focus:outline-none',
17
+ 'ml-auto flex tier-chip w-chip shrink-0 items-center justify-center text-muted hover:bg-highlight hover:text-fg focus:outline-none',
18
18
  className
19
19
  )}
20
20
  {...restProps}
@@ -22,7 +22,7 @@
22
22
  <DateRangeField.Segment
23
23
  bind:ref
24
24
  class={cn(
25
- 'era-token-ink h-chip rounded-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
25
+ 'era-token-ink tier-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
26
26
  className
27
27
  )}
28
28
  {...restProps}
@@ -12,7 +12,7 @@
12
12
  <DateRangePicker.Day
13
13
  bind:ref
14
14
  class={cn(
15
- 'inline-flex size-control cursor-default items-center justify-center rounded-control text-body text-fg hover:bg-highlight focus:outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[outside-month]:pointer-events-none data-[outside-month]:text-muted/40 data-[range-end]:bg-primary data-[range-end]:text-primary-fg data-[range-start]:bg-primary data-[range-start]:text-primary-fg data-[selected]:bg-hover data-[selected]:text-bright data-[unavailable]:text-muted data-[unavailable]:line-through',
15
+ 'inline-flex tier-control w-control cursor-default items-center justify-center text-body text-fg hover:bg-highlight focus:outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[outside-month]:pointer-events-none data-[outside-month]:text-muted/40 data-[range-end]:bg-primary data-[range-end]:text-primary-fg data-[range-start]:bg-primary data-[range-start]:text-primary-fg data-[selected]:bg-hover data-[selected]:text-bright data-[unavailable]:text-muted data-[unavailable]:line-through',
16
16
  className
17
17
  )}
18
18
  {...restProps}
@@ -22,7 +22,7 @@
22
22
  <DateRangePicker.Segment
23
23
  bind:ref
24
24
  class={cn(
25
- 'era-token-ink h-chip rounded-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
25
+ 'era-token-ink tier-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
26
26
  className
27
27
  )}
28
28
  {...restProps}
@@ -14,7 +14,7 @@
14
14
  <DateRangePicker.Trigger
15
15
  bind:ref
16
16
  class={cn(
17
- 'ml-auto flex size-chip shrink-0 items-center justify-center rounded-chip text-muted hover:bg-highlight hover:text-fg focus:outline-none',
17
+ 'ml-auto flex tier-chip w-chip shrink-0 items-center justify-center text-muted hover:bg-highlight hover:text-fg focus:outline-none',
18
18
  className
19
19
  )}
20
20
  {...restProps}
@@ -10,6 +10,7 @@
10
10
  variant,
11
11
  icon,
12
12
  loading,
13
+ busy,
13
14
  loadingLabel,
14
15
  children,
15
16
  class: className,
@@ -30,6 +31,7 @@
30
31
  {variant}
31
32
  {icon}
32
33
  {loading}
34
+ {busy}
33
35
  {loadingLabel}
34
36
  class={className}
35
37
  >
@@ -48,7 +48,25 @@
48
48
 
49
49
  Sheet.Content already had this exact treatment; Dialog and AlertDialog
50
50
  never got it. 85dvh matches Sheet's, deliberately — one ceiling for every
51
- floating panel, not three opinions.
51
+ MODAL panel, not three opinions.
52
+
53
+ SCOPE, and read this before you delete a max-height of your own: this
54
+ covers Dialog, AlertDialog and Sheet. It does NOT cover the anchored
55
+ surfaces — Popover, DropdownMenu, Select, Combobox, Menubar,
56
+ ContextMenu and Tooltip have no ceiling at all today. If you keep a
57
+ local max-height on one of those, KEEP IT; it is load-bearing, not
58
+ vestigial.
59
+
60
+ This paragraph exists because the sentence above it used to read "every
61
+ floating panel", and a consumer reasoned correctly from it: floating
62
+ panels have ceilings, therefore my Popover's max-height is a redundant
63
+ workaround, therefore delete it. Right there, in the exact place you
64
+ come to decide whether a workaround is still needed, and wrong one
65
+ component over. A principle the library does not implement is worse
66
+ than silence — silence sends you to measure. Carrying the ceiling to
67
+ the anchored surfaces (anchor-aware, via bits-ui's
68
+ --bits-*-content-available-height rather than viewport dvh) is the
69
+ actual fix; until it lands, this says what is true instead.
52
70
 
53
71
  The BODY scrolls, not the panel, so a long form's footer stays put
54
72
  instead of scrolling away with the fields. -->
@@ -22,7 +22,7 @@
22
22
  <DropdownMenu.Trigger
23
23
  bind:ref
24
24
  class={cn(
25
- 'flex h-control w-full items-center justify-between gap-icon-inset-chip rounded-control bg-elevated px-inset-control text-body text-fg shadow-sm focus:bg-highlight focus:outline-none disabled:opacity-50 data-[state=open]:rounded-b-none data-[state=open]:shadow-pressed',
25
+ 'flex tier-control w-full items-center justify-between gap-icon-inset-chip bg-elevated px-inset-control text-body text-fg shadow-sm focus:bg-highlight focus:outline-none disabled:opacity-50 data-[state=open]:rounded-b-none data-[state=open]:shadow-pressed',
26
26
  className
27
27
  )}
28
28
  {...restProps}
@@ -74,7 +74,7 @@
74
74
  data-dragging={dragging || undefined}
75
75
  data-disabled={disabled || undefined}
76
76
  class={cn(
77
- 'flex h-control w-full items-center gap-gutter rounded-control bg-elevated px-inset-control font-mono text-body leading-none text-fg shadow-well transition-colors duration-base focus-within:bg-highlight hover:bg-highlight data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[dragging]:bg-highlight data-[dragging]:text-bright',
77
+ 'flex tier-control w-full items-center gap-gutter bg-elevated px-inset-control font-mono text-body leading-none text-fg shadow-well transition-colors duration-base focus-within:bg-highlight hover:bg-highlight data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[dragging]:bg-highlight data-[dragging]:text-bright',
78
78
  className
79
79
  )}
80
80
  ondragenter={onDragEnter}
@@ -60,8 +60,8 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
60
60
  * on this tier read as one family.
61
61
  */
62
62
  size: {
63
- control: "h-control rounded-control px-field";
64
- pill: "h-pill rounded-pill px-pill";
63
+ control: "tier-control px-field";
64
+ pill: "tier-pill px-pill";
65
65
  };
66
66
  /**
67
67
  * Height OVERRIDES, for the fields that are not their tier's height. No
@@ -128,8 +128,8 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
128
128
  * on this tier read as one family.
129
129
  */
130
130
  size: {
131
- control: "h-control rounded-control px-field";
132
- pill: "h-pill rounded-pill px-pill";
131
+ control: "tier-control px-field";
132
+ pill: "tier-pill px-pill";
133
133
  };
134
134
  /**
135
135
  * Height OVERRIDES, for the fields that are not their tier's height. No
@@ -196,8 +196,8 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
196
196
  * on this tier read as one family.
197
197
  */
198
198
  size: {
199
- control: "h-control rounded-control px-field";
200
- pill: "h-pill rounded-pill px-pill";
199
+ control: "tier-control px-field";
200
+ pill: "tier-pill px-pill";
201
201
  };
202
202
  /**
203
203
  * Height OVERRIDES, for the fields that are not their tier's height. No
@@ -63,8 +63,8 @@ export const inputVariants = tv({
63
63
  * on this tier read as one family.
64
64
  */
65
65
  size: {
66
- control: 'h-control rounded-control px-field',
67
- pill: 'h-pill rounded-pill px-pill'
66
+ control: 'tier-control px-field',
67
+ pill: 'tier-pill px-pill'
68
68
  },
69
69
  /**
70
70
  * Height OVERRIDES, for the fields that are not their tier's height. No
@@ -24,7 +24,7 @@
24
24
  // shrink-0 + nowrap like Badge/Chip: the overflow-hidden here is for the
25
25
  // key cell's squared corners, not a licence to crush — squeezed, this pill
26
26
  // clipped its value instead of bleeding it, which is quieter but no truer.
27
- 'inline-flex h-pill shrink-0 items-center overflow-hidden rounded-pill bg-fill font-mono text-body leading-none whitespace-nowrap shadow-sm',
27
+ 'inline-flex tier-pill shrink-0 items-center overflow-hidden bg-fill font-mono text-body leading-none whitespace-nowrap shadow-sm',
28
28
  className
29
29
  )}
30
30
  {...restProps}
@@ -32,6 +32,6 @@
32
32
  <Menubar.Root
33
33
  bind:ref
34
34
  bind:value
35
- class={cn('flex h-bar items-center rounded-bar bg-well px-gutter shadow-sm', className)}
35
+ class={cn('flex tier-bar items-center bg-well px-gutter shadow-sm', className)}
36
36
  {...restProps}
37
37
  />
@@ -13,7 +13,7 @@
13
13
  <Menubar.Trigger
14
14
  bind:ref
15
15
  class={cn(
16
- 'flex h-control items-center gap-gutter rounded-control px-inset-control text-body text-fg hover:bg-highlight focus:outline-none disabled:opacity-50 has-[svg]:gap-inset-control data-[state=open]:rounded-b-none data-[state=open]:bg-hover',
16
+ 'flex tier-control items-center gap-gutter px-inset-control text-body text-fg hover:bg-highlight focus:outline-none disabled:opacity-50 has-[svg]:gap-inset-control data-[state=open]:rounded-b-none data-[state=open]:bg-hover',
17
17
  className
18
18
  )}
19
19
  {...restProps}
@@ -5,12 +5,12 @@
5
5
  // Bar's geometry, imported rather than restated. A re-export here would be a
6
6
  // second name for one thing; anyone who wants the variants imports them from
7
7
  // Bar, which is where they are defined.
8
- import { barVariants } from '../bar/bar.svelte';
8
+ import { barVariants, resolveBarContent, type BarContent, type BarSize } from '../bar/bar.svelte';
9
9
 
10
10
  let {
11
11
  ref = $bindable(null),
12
12
  size = 'bar',
13
- content = 'tier',
13
+ content,
14
14
  divider = false,
15
15
  label = 'Main',
16
16
  children,
@@ -21,7 +21,7 @@
21
21
  /** Height tier, exactly as Bar's — the geometry is Bar's, not a second copy. */
22
22
  size?: 'chip' | 'control' | 'bar';
23
23
  /** Tier of the items inside, so the wall stays concentric to them. */
24
- content?: 'tier' | 'pill';
24
+ content?: BarContent;
25
25
  /**
26
26
  * Draw Bar's flush cap-a-panel rule beneath the bar. Off by default,
27
27
  * because a nav that sits in a page already has whatever separation the
@@ -40,6 +40,8 @@
40
40
  label?: string;
41
41
  children?: Snippet;
42
42
  } = $props();
43
+
44
+ const resolvedContent = $derived(resolveBarContent(size as BarSize, content));
43
45
  </script>
44
46
 
45
47
  <!--
@@ -53,7 +55,10 @@
53
55
  <nav
54
56
  bind:this={ref}
55
57
  aria-label={label}
56
- class={cn(barVariants({ size, content, divider }), className)}
58
+ data-era-geometry={divider ? 'docked' : 'nested'}
59
+ data-era-tier={size}
60
+ data-era-contains={resolvedContent}
61
+ class={cn(barVariants({ size, content: resolvedContent, divider }), className)}
57
62
  {...restProps}
58
63
  >
59
64
  {@render children?.()}
@@ -1,11 +1,12 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
+ import { type BarContent } from '../bar/bar.svelte';
3
4
  type $$ComponentProps = HTMLAttributes<HTMLElement> & {
4
5
  ref?: HTMLElement | null;
5
6
  /** Height tier, exactly as Bar's — the geometry is Bar's, not a second copy. */
6
7
  size?: 'chip' | 'control' | 'bar';
7
8
  /** Tier of the items inside, so the wall stays concentric to them. */
8
- content?: 'tier' | 'pill';
9
+ content?: BarContent;
9
10
  /**
10
11
  * Draw Bar's flush cap-a-panel rule beneath the bar. Off by default,
11
12
  * because a nav that sits in a page already has whatever separation the
@@ -530,18 +530,9 @@
530
530
  // content until the grip sets a size, and size containment would collapse
531
531
  // that to zero) and NOT `paint` (the resize handles deliberately bleed
532
532
  // outward, and paint containment clips them).
533
- // --era-container-rd publishes this pane's ACTUAL radius, so any
534
- // `rounded-row` descendant derives from the pane instead of from the
535
- // utility's fallback. It used to be unset, and that fallback was silently
536
- // deciding the geometry of every list in the app.
537
- //
538
- // The radius is rd-control and stays there. It was briefly raised to rd-bar
539
- // to make `rounded-row` produce rd-control for the nav rows — which worked,
540
- // and broke the corner it is measured against: the close button sits 4px
541
- // from this corner, so at rd-bar it needed a 8.056 radius and had a pill's
542
- // 5.056. Chasing the container was the wrong end. A row should carry the
543
- // radius of its OWN tier, which is what the command items do now.
544
- 'group/pane absolute isolate flex flex-col rounded-control border border-divider bg-elevated shadow-lg glass-blur [contain:layout_style] [--era-container-rd:var(--era-rd-control)]',
533
+ // The pane is unbounded chrome. Bounded descendants carry their own tier;
534
+ // no inherited radius is allowed to rewrite a row from the outside in.
535
+ 'group/pane absolute isolate flex flex-col rounded-control border border-divider bg-elevated shadow-lg glass-blur [contain:layout_style]',
545
536
  // Auto-size to content until an explicit size is set (by the grip or a preset).
546
537
  size ? '' : 'w-max',
547
538
  // While Ctrl is held the whole pane is grabbable: a grab cursor hints it, and
@@ -23,7 +23,7 @@
23
23
  // trim pulls the box up to the alphabetic baseline, so the clip then slices
24
24
  // every descender (the "logs" g, the "history" y). [text-box:normal] cancels
25
25
  // it; leading-none + the strip's items-center still centre the label.
26
- 'flex h-pill cursor-pointer items-center gap-gutter rounded-pill px-pill text-body leading-none text-muted outline-none select-none [text-box:normal] hover:text-fg focus-visible:bg-highlight data-[state=active]:bg-hover data-[state=active]:text-bright',
26
+ 'flex tier-pill cursor-pointer items-center gap-gutter px-pill text-body leading-none text-muted outline-none select-none [text-box:normal] hover:text-fg focus-visible:bg-highlight data-[state=active]:bg-hover data-[state=active]:text-bright',
27
27
  className
28
28
  )}
29
29
  {...restProps}
@@ -14,7 +14,7 @@
14
14
  <Select.Trigger
15
15
  bind:ref
16
16
  class={cn(
17
- 'flex h-control w-full items-center justify-between gap-icon-inset-chip rounded-control bg-elevated px-inset-control text-body leading-none text-fg shadow-sm hover:bg-highlight focus:bg-highlight focus:outline-none disabled:opacity-50 data-[state=open]:rounded-b-none data-[state=open]:shadow-pressed',
17
+ 'flex tier-control w-full items-center justify-between gap-icon-inset-chip bg-elevated px-inset-control text-body leading-none text-fg shadow-sm hover:bg-highlight focus:bg-highlight focus:outline-none disabled:opacity-50 data-[state=open]:rounded-b-none data-[state=open]:shadow-pressed',
18
18
  className
19
19
  )}
20
20
  {...restProps}
@@ -8,7 +8,7 @@
8
8
  <Slider.Thumb
9
9
  bind:ref
10
10
  class={cn(
11
- "relative block size-icon cursor-pointer rounded-icon bg-fg shadow-sm transition-transform duration-base will-change-transform after:absolute after:inset-[-13px] after:content-[''] hover:scale-105 focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:scale-[0.96]",
11
+ "relative block tier-icon w-icon cursor-pointer bg-fg shadow-sm transition-transform duration-base will-change-transform after:absolute after:inset-[-13px] after:content-[''] hover:scale-105 focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:scale-[0.96]",
12
12
  className
13
13
  )}
14
14
  {...restProps}
@@ -26,7 +26,7 @@
26
26
  <Collapsible.Trigger
27
27
  bind:ref
28
28
  class={cn(
29
- 'flex h-control w-full min-w-0 era-interactive cursor-pointer items-center gap-gutter rounded-control px-inset-control text-body leading-none text-muted transition-colors duration-base ease-base hover:text-fg',
29
+ 'flex tier-control w-full min-w-0 era-interactive cursor-pointer items-center gap-gutter px-inset-control text-body leading-none text-muted transition-colors duration-base ease-base hover:text-fg',
30
30
  className
31
31
  )}
32
32
  {...restProps}
@@ -32,7 +32,7 @@
32
32
  // component that had worked around it with the border below rather than
33
33
  // moving tier. This moves tier; the border stays, since a track needs a
34
34
  // closed shape at chip size on every surface, not just the flat one.
35
- 'inline-flex h-chip w-[calc(var(--era-h-chip)+var(--era-h-icon))] shrink-0 era-interactive cursor-pointer items-center justify-center rounded-chip border border-divider bg-field shadow-well hover:bg-highlight data-[state=checked]:bg-fg',
35
+ 'inline-flex tier-chip w-[calc(var(--era-h-chip)+var(--era-h-icon))] shrink-0 era-interactive cursor-pointer items-center justify-center border border-divider bg-field shadow-well hover:bg-highlight data-[state=checked]:bg-fg',
36
36
  className
37
37
  )}
38
38
  {...restProps}
@@ -43,6 +43,6 @@
43
43
  vs bevel track-slide) scopes a rule to its own surface — see the
44
44
  surface-animation recipe in surfaces/base.css. -->
45
45
  <Switch.Thumb
46
- class="pointer-events-none block size-icon -translate-x-[calc(var(--era-h-icon)/2)] rounded-icon bg-fg transition-transform duration-base ease-base data-[state=checked]:translate-x-[calc(var(--era-h-icon)/2)] data-[state=checked]:bg-2"
46
+ class="pointer-events-none block tier-icon w-icon -translate-x-[calc(var(--era-h-icon)/2)] bg-fg transition-transform duration-base ease-base data-[state=checked]:translate-x-[calc(var(--era-h-icon)/2)] data-[state=checked]:bg-2"
47
47
  />
48
48
  </Switch.Root>
@@ -18,7 +18,7 @@
18
18
  <TimeField.Segment
19
19
  bind:ref
20
20
  class={cn(
21
- 'era-token-ink h-chip rounded-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
21
+ 'era-token-ink tier-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
22
22
  className
23
23
  )}
24
24
  {...restProps}
@@ -22,7 +22,7 @@
22
22
  <TimeRangeField.Segment
23
23
  bind:ref
24
24
  class={cn(
25
- 'era-token-ink h-chip rounded-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
25
+ 'era-token-ink tier-chip px-[calc(var(--era-sp)/2)] focus:bg-highlight focus:text-bright focus:outline-none aria-[valuetext=Empty]:text-muted data-[segment=literal]:text-muted',
26
26
  className
27
27
  )}
28
28
  {...restProps}
@@ -73,7 +73,7 @@
73
73
 
74
74
  <div
75
75
  class={cn(
76
- 'flex h-control items-center justify-end gap-inset-control rounded-control px-inset-control shadow-sm outline outline-divider',
76
+ 'flex tier-control items-center justify-end gap-inset-control px-inset-control shadow-sm outline outline-divider',
77
77
  tone.bar,
78
78
  className
79
79
  )}
@@ -14,8 +14,8 @@
14
14
  variants: {
15
15
  variant: {
16
16
  plain:
17
- 'h-control min-w-control rounded-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed',
18
- segmented: 'h-chip min-w-chip rounded-chip px-inset-chip'
17
+ 'min-w-control tier-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed',
18
+ segmented: 'min-w-chip tier-chip px-inset-chip'
19
19
  }
20
20
  },
21
21
  defaultVariants: { variant: 'plain' }
@@ -1,17 +1,17 @@
1
1
  export declare const toggleGroupItemVariants: import("tailwind-variants").TVReturnType<{
2
2
  variant: {
3
- plain: "h-control min-w-control rounded-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed";
4
- segmented: "h-chip min-w-chip rounded-chip px-inset-chip";
3
+ plain: "min-w-control tier-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed";
4
+ segmented: "min-w-chip tier-chip px-inset-chip";
5
5
  };
6
6
  }, undefined, "inline-flex items-center justify-center text-body text-fg era-interactive not-has-[svg]:era-label-ink not-has-[svg]:text-center hover:bg-highlight focus:outline-none disabled:opacity-50 data-[state=on]:bg-fill data-[state=on]:text-bright data-[state=on]:shadow-pressed data-[state=on]:hover:shadow-pressed", {
7
7
  variant: {
8
- plain: "h-control min-w-control rounded-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed";
9
- segmented: "h-chip min-w-chip rounded-chip px-inset-chip";
8
+ plain: "min-w-control tier-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed";
9
+ segmented: "min-w-chip tier-chip px-inset-chip";
10
10
  };
11
11
  }, undefined, import("tailwind-variants").TVReturnTypeLike<{
12
12
  variant: {
13
- plain: "h-control min-w-control rounded-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed";
14
- segmented: "h-chip min-w-chip rounded-chip px-inset-chip";
13
+ plain: "min-w-control tier-control px-inset-control shadow-sm hover:shadow-highlight active:shadow-pressed";
14
+ segmented: "min-w-chip tier-chip px-inset-chip";
15
15
  };
16
16
  }, undefined>>;
17
17
  import { ToggleGroup } from 'bits-ui';
@@ -10,8 +10,7 @@
10
10
  variants: {
11
11
  variant: {
12
12
  plain: 'gap-gutter',
13
- segmented:
14
- 'h-control gap-chip-inset-control rounded-control bg-field p-chip-inset-control shadow-well'
13
+ segmented: 'gap-chip-inset-control tier-control bg-field p-chip-inset-control shadow-well'
15
14
  }
16
15
  },
17
16
  defaultVariants: { variant: 'plain' }