@signal9/era-ui 30.8.0 → 32.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 (116) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/ai/artifact/artifact.svelte +1 -1
  3. package/dist/ai/conversations/conversations-item.svelte +1 -1
  4. package/dist/ai/plan/plan-header.svelte +1 -1
  5. package/dist/ai/prompt-input/prompt-input-attachments.svelte +2 -6
  6. package/dist/ai/swarm/swarm-node.svelte +1 -1
  7. package/dist/ai/todo/todo-header.svelte +1 -1
  8. package/dist/ai/todo/todo-item.svelte +1 -1
  9. package/dist/ai/tool/tool-chip.svelte +1 -1
  10. package/dist/ai/web-preview/web-preview.svelte +2 -2
  11. package/dist/ai/workflow/node.svelte +1 -1
  12. package/dist/dev/audit/audits/wall-is-isotropic.js +1 -1
  13. package/dist/docs/css-utilities.js +9 -5
  14. package/dist/era-ui.css +1 -1
  15. package/dist/generated-docs/badge.md +1 -1
  16. package/dist/generated-docs/bar.md +22 -4
  17. package/dist/generated-docs/button.md +38 -4
  18. package/dist/generated-docs/card.md +35 -5
  19. package/dist/generated-docs/chip.md +16 -0
  20. package/dist/generated-docs/llms-full.txt +370 -70
  21. package/dist/generated-docs/llms.txt +8 -4
  22. package/dist/generated-docs/manifest.json +85 -28
  23. package/dist/generated-docs/meter.md +79 -1
  24. package/dist/generated-docs/nav.md +8 -1
  25. package/dist/generated-docs/separator.md +18 -0
  26. package/dist/generated-docs/utilities.json +68 -15
  27. package/dist/generated-docs/utilities.md +145 -50
  28. package/dist/os/notification-center.svelte +1 -1
  29. package/dist/os/taskbar.svelte +1 -1
  30. package/dist/os/toast.svelte +1 -1
  31. package/dist/styles/density.css +15 -25
  32. package/dist/styles/index.css +74 -48
  33. package/dist/styles/motion.css +1 -1
  34. package/dist/styles/prose.css +1 -1
  35. package/dist/styles/surfaces/bevel.css +16 -19
  36. package/dist/styles/surfaces/contract.css +50 -0
  37. package/dist/styles/surfaces/flat.css +27 -0
  38. package/dist/styles/surfaces/glass.css +11 -8
  39. package/dist/ui/accordion/accordion-trigger.svelte +1 -1
  40. package/dist/ui/alert-dialog/alert-dialog-content.svelte +1 -1
  41. package/dist/ui/badge/badge.svelte +8 -2
  42. package/dist/ui/badge/badge.svelte.d.ts +1 -1
  43. package/dist/ui/bar/bar.svelte +95 -26
  44. package/dist/ui/bar/bar.svelte.d.ts +71 -31
  45. package/dist/ui/button/button.svelte +6 -0
  46. package/dist/ui/button/button.svelte.d.ts +2 -0
  47. package/dist/ui/button/variants.d.ts +3 -3
  48. package/dist/ui/button/variants.js +6 -11
  49. package/dist/ui/calendar/calendar-day.svelte +1 -1
  50. package/dist/ui/card/card.svelte +23 -10
  51. package/dist/ui/card/card.svelte.d.ts +19 -7
  52. package/dist/ui/chip/chip.svelte +5 -2
  53. package/dist/ui/chip/chip.svelte.d.ts +6 -6
  54. package/dist/ui/collapsible/collapsible-trigger.svelte +1 -1
  55. package/dist/ui/combobox/combobox-content.svelte +1 -1
  56. package/dist/ui/combobox/combobox-trigger.svelte +1 -1
  57. package/dist/ui/command/command-item.svelte +1 -1
  58. package/dist/ui/command/command-link-item.svelte +1 -1
  59. package/dist/ui/command/command-root.svelte +5 -7
  60. package/dist/ui/command-bar/command-bar.svelte +3 -3
  61. package/dist/ui/context-menu/context-menu-content.svelte +1 -4
  62. package/dist/ui/context-menu/context-menu-sub-content.svelte +1 -4
  63. package/dist/ui/date-field/date-field-segment.svelte +1 -1
  64. package/dist/ui/date-picker/date-picker-content.svelte +1 -1
  65. package/dist/ui/date-picker/date-picker-day.svelte +1 -1
  66. package/dist/ui/date-picker/date-picker-segment.svelte +1 -1
  67. package/dist/ui/date-picker/date-picker-trigger.svelte +1 -1
  68. package/dist/ui/date-range-field/date-range-field-segment.svelte +1 -1
  69. package/dist/ui/date-range-picker/date-range-picker-content.svelte +1 -1
  70. package/dist/ui/date-range-picker/date-range-picker-day.svelte +1 -1
  71. package/dist/ui/date-range-picker/date-range-picker-segment.svelte +1 -1
  72. package/dist/ui/date-range-picker/date-range-picker-trigger.svelte +1 -1
  73. package/dist/ui/dialog/dialog-content.svelte +20 -2
  74. package/dist/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
  75. package/dist/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -4
  76. package/dist/ui/dropdown-menu/dropdown-menu-trigger.svelte +1 -1
  77. package/dist/ui/file-upload/file-upload.svelte +1 -1
  78. package/dist/ui/input/variants.d.ts +6 -6
  79. package/dist/ui/input/variants.js +2 -2
  80. package/dist/ui/kv/kv.svelte +1 -1
  81. package/dist/ui/link-preview/link-preview-content.svelte +1 -1
  82. package/dist/ui/menubar/menubar-content.svelte +1 -1
  83. package/dist/ui/menubar/menubar-root.svelte +1 -1
  84. package/dist/ui/menubar/menubar-sub-content.svelte +1 -4
  85. package/dist/ui/menubar/menubar-trigger.svelte +1 -1
  86. package/dist/ui/meter/meter.svelte +1 -2
  87. package/dist/ui/nav/nav-bar.svelte +9 -4
  88. package/dist/ui/nav/nav-bar.svelte.d.ts +2 -1
  89. package/dist/ui/nav/nav-item.svelte +1 -0
  90. package/dist/ui/pane/pane-root.svelte +3 -12
  91. package/dist/ui/pane/pane-tab.svelte +1 -1
  92. package/dist/ui/popover/popover-content.svelte +1 -1
  93. package/dist/ui/provider/surfaces.d.ts +1 -1
  94. package/dist/ui/provider/surfaces.js +1 -1
  95. package/dist/ui/select/select-content.svelte +1 -1
  96. package/dist/ui/select/select-trigger.svelte +1 -1
  97. package/dist/ui/sheet/sheet-content.svelte +1 -1
  98. package/dist/ui/sheet/sheet-content.svelte.d.ts +1 -1
  99. package/dist/ui/slider/slider-thumb.svelte +1 -1
  100. package/dist/ui/step/step-summary.svelte +1 -1
  101. package/dist/ui/switch/switch.svelte +3 -3
  102. package/dist/ui/time-field/time-field-segment.svelte +1 -1
  103. package/dist/ui/time-range-field/time-range-field-segment.svelte +1 -1
  104. package/dist/ui/timeline/timeline-step.svelte +1 -1
  105. package/dist/ui/toggle-group/toggle-group-item.svelte +2 -2
  106. package/dist/ui/toggle-group/toggle-group-item.svelte.d.ts +6 -6
  107. package/dist/ui/toggle-group/toggle-group-root.svelte +1 -2
  108. package/dist/ui/toggle-group/toggle-group-root.svelte.d.ts +3 -3
  109. package/dist/ui/tooltip/tooltip-content.svelte +1 -1
  110. package/dist/ui/tree/tree-item.svelte +1 -1
  111. package/dist/ui/video-player/video-player.svelte +2 -2
  112. package/dist/utils/tw-merge-config.d.ts +6 -1
  113. package/dist/utils/tw-merge-config.js +6 -2
  114. package/package.json +5 -3
  115. package/skill/SKILL.md +26 -21
  116. package/dist/styles/surfaces/base.css +0 -257
@@ -19,6 +19,7 @@
19
19
  lead,
20
20
  trail,
21
21
  caps = false,
22
+ topology = 'bounded',
22
23
  children,
23
24
  class: className,
24
25
  ...restProps
@@ -126,6 +127,8 @@
126
127
  * which is the whole reason those snippets exist.
127
128
  */
128
129
  caps?: boolean;
130
+ /** `docked` joins this control to a neighbour and removes one or more curves. */
131
+ topology?: 'bounded' | 'docked';
129
132
  children?: Snippet;
130
133
  } = $props();
131
134
 
@@ -156,6 +159,8 @@
156
159
  aria-busy={inFlight || undefined}
157
160
  data-state={active ? 'on' : undefined}
158
161
  data-size={size}
162
+ data-era-geometry={variant === 'filled' ? topology : undefined}
163
+ data-era-tier={variant === 'filled' ? size : undefined}
159
164
  class={cn(
160
165
  buttonVariants({ variant, tone, size, icon, active }),
161
166
  // Positioned only while loading — the spinner overlay below needs a
@@ -195,6 +200,7 @@
195
200
  -->
196
201
  <span
197
202
  data-button-content
203
+ data-era-press-content
198
204
  class={cn(
199
205
  'inline-flex items-center justify-center [gap:inherit]',
200
206
  // THE LABEL KEEPS ITS BOX AND LOSES ITS INK. opacity, not `hidden` or
@@ -104,6 +104,8 @@ type $$ComponentProps = Button.RootProps & {
104
104
  * which is the whole reason those snippets exist.
105
105
  */
106
106
  caps?: boolean;
107
+ /** `docked` joins this control to a neighbour and removes one or more curves. */
108
+ topology?: 'bounded' | 'docked';
107
109
  children?: Snippet;
108
110
  };
109
111
  declare const Button: import("svelte").Component<$$ComponentProps, {}, "ref">;
@@ -1,6 +1,6 @@
1
1
  export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
2
2
  variant: {
3
- filled: "flex justify-center shadow-sm hover:shadow-highlight active:shadow-pressed [&:active>*]:translate-x-(--era-press-sink-x) [&:active>*]:translate-y-(--era-press-sink-y)";
3
+ filled: "pressable flex justify-center shadow-sm hover:shadow-highlight";
4
4
  link: "inline era-link [line-height:inherit]";
5
5
  };
6
6
  tone: {
@@ -25,7 +25,7 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
25
25
  };
26
26
  }, undefined, "items-center gap-gutter text-body era-interactive leading-none", {
27
27
  variant: {
28
- filled: "flex justify-center shadow-sm hover:shadow-highlight active:shadow-pressed [&:active>*]:translate-x-(--era-press-sink-x) [&:active>*]:translate-y-(--era-press-sink-y)";
28
+ filled: "pressable flex justify-center shadow-sm hover:shadow-highlight";
29
29
  link: "inline era-link [line-height:inherit]";
30
30
  };
31
31
  tone: {
@@ -50,7 +50,7 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
50
50
  };
51
51
  }, undefined, import("tailwind-variants").TVReturnTypeLike<{
52
52
  variant: {
53
- filled: "flex justify-center shadow-sm hover:shadow-highlight active:shadow-pressed [&:active>*]:translate-x-(--era-press-sink-x) [&:active>*]:translate-y-(--era-press-sink-y)";
53
+ filled: "pressable flex justify-center shadow-sm hover:shadow-highlight";
54
54
  link: "inline era-link [line-height:inherit]";
55
55
  };
56
56
  tone: {
@@ -9,10 +9,10 @@ export const buttonVariants = tv({
9
9
  // The active: press treatment is inert outside the bevel surface —
10
10
  // flat/glass define --era-shadow-pressed as the resting shadow and 0px
11
11
  // sinks. Bevel inverts the chisel and sinks the CONTENT straight down
12
- // (press-sink, `[&:active>*]` the one content-wrapper span from
12
+ // (`pressable` targets the one content-wrapper span from
13
13
  // button.svelte) so the icon AND label depress together like a keycap
14
14
  // while the frame holds still.
15
- filled: 'flex justify-center shadow-sm hover:shadow-highlight active:shadow-pressed [&:active>*]:translate-x-(--era-press-sink-x) [&:active>*]:translate-y-(--era-press-sink-y)',
15
+ filled: 'pressable flex justify-center shadow-sm hover:shadow-highlight',
16
16
  // THE LINK VARIANT IS era-link, not a second implementation of it.
17
17
  // It used to hand-roll `underline-offset-2 hover:underline`, which is a
18
18
  // different link from the one `era-link` defines for prose: no underline
@@ -40,27 +40,22 @@ export const buttonVariants = tv({
40
40
  {
41
41
  variant: 'filled',
42
42
  size: 'control',
43
- class: 'h-control min-w-control rounded-control'
43
+ class: 'min-w-control tier-control'
44
44
  },
45
45
  {
46
46
  variant: 'filled',
47
47
  size: 'chip',
48
- class: 'h-chip min-w-chip rounded-chip'
48
+ class: 'min-w-chip tier-chip'
49
49
  },
50
50
  {
51
51
  variant: 'filled',
52
52
  size: 'pill',
53
- class: 'h-pill min-w-pill rounded-pill'
53
+ class: 'min-w-pill tier-pill'
54
54
  },
55
55
  {
56
56
  variant: 'filled',
57
57
  size: 'icon',
58
- class: 'h-icon min-w-icon rounded-icon'
59
- },
60
- {
61
- variant: 'filled',
62
- size: 'icon',
63
- class: 'h-icon min-w-icon rounded-icon'
58
+ class: 'min-w-icon tier-icon [--era-press-effective-x:var(--era-press-sink-compact-x)] [--era-press-effective-y:var(--era-press-sink-compact-y)]'
64
59
  },
65
60
  // filled insets; icon buttons go square instead. When an icon is present,
66
61
  // gap widens to match the wall inset so the icon sits in rhythm with it.
@@ -15,7 +15,7 @@
15
15
  <Calendar.Day
16
16
  bind:ref
17
17
  class={cn(
18
- 'era-token-ink size-control cursor-default 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',
18
+ 'era-token-ink tier-control w-control cursor-default 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',
19
19
  className
20
20
  )}
21
21
  {...restProps}
@@ -32,17 +32,18 @@
32
32
  // was: the even-gap law, broken by default, in the component that
33
33
  // bounds more consumer content than any other.
34
34
  sectioned: { true: 'p-0', false: 'p-card' },
35
- // A CARD YOU CAN PRESS DEPRESSES. `active:shadow-pressed` is on every
35
+ // A CARD YOU CAN PRESS DEPRESSES. The pressed material is on every
36
36
  // other era control and was missing here, so a pressable card was the
37
37
  // one thing in the library that lit up on hover and then did nothing
38
38
  // under the finger — on bevel, where the pressed face is an inverted
39
39
  // chisel, that is the difference between a control and a picture of
40
40
  // one. Inert on flat (the token is `none`) and on glass (it resolves
41
41
  // to the resting shadow), so only the surface that has a pressed face
42
- // shows it. No content sink to go with it: the sink moves a control's
43
- // single content wrapper, and a card's children are the consumer's.
42
+ // shows it. Move one library-owned content layer with the face: transforming
43
+ // consumer children separately would pull a card's sections apart, while no
44
+ // wrapper leaves the frame depressed around stationary ink.
44
45
  interactive: {
45
- 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'
46
+ true: 'pressable cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight era-interactive aria-disabled:cursor-not-allowed aria-disabled:opacity-50'
46
47
  }
47
48
  },
48
49
  defaultVariants: { tone: 'elevated', sectioned: false, interactive: false }
@@ -124,10 +125,22 @@
124
125
  * A CARD THAT IS PRESSABLE SHOULD USUALLY BE `elevated`. Passing `href`
125
126
  * or `onclick` turns on the interactive face — hover, focus, press — but
126
127
  * it deliberately does NOT override the tier you asked for, so a
127
- * `surface` link card has no resting lift and reads flatter than the
128
- * static cards around it. That combination was reported as a bug and it
129
- * is a choice: a tone that silently changed under an event handler would
130
- * be a worse one.
128
+ * `surface` link card does not get the raised tier's separation and can
129
+ * read flatter than the static cards around it. That combination was
130
+ * reported as a bug and it is a choice: a tone that silently changed
131
+ * under an event handler would be a worse one.
132
+ *
133
+ * HOW THE TIERS DIFFER IS SURFACE-DEPENDENT, so do not go looking for a
134
+ * fill difference on every surface. `base` mixes the elevated fill 6%
135
+ * toward `--color-bright` and adds a resting shadow, so there the tiers
136
+ * differ in COLOUR. `bevel` sets `--era-surface-bg-elevated` to
137
+ * `--era-surface-bg` outright — elevation is a chisel, not a tone, which
138
+ * is bevel's whole premise — so `surface` and `elevated` paint the
139
+ * IDENTICAL fill there and differ only in relief. A consumer measured
140
+ * exactly that on 30.8.0 bevel: both tones `oklch(0.195 0 none)` in dark,
141
+ * `0.863` in light, one variable, side by side. `glass` splits the tiers
142
+ * its own way again. So the tier is real on every surface; the thing
143
+ * carrying it is not always the fill.
131
144
  */
132
145
  tone?: 'elevated' | 'surface' | 'well' | 'flat';
133
146
  /** Rendered above the body with a subtle divider. */
@@ -178,7 +191,7 @@
178
191
  class={cn(cardVariants({ tone, sectioned, interactive: true }), className)}
179
192
  {...restProps}
180
193
  >
181
- {@render body()}
194
+ <div data-card-content data-era-press-content>{@render body()}</div>
182
195
  </a>
183
196
  <!-- eslint-enable svelte/no-navigation-without-resolve -->
184
197
  {:else if onclick != null}
@@ -198,7 +211,7 @@
198
211
  class={cn(cardVariants({ tone, sectioned, interactive: true }), className)}
199
212
  {...restProps}
200
213
  >
201
- {@render body()}
214
+ <div data-card-content data-era-press-content>{@render body()}</div>
202
215
  </button>
203
216
  {:else}
204
217
  <div
@@ -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: "pressable cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight 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: "pressable cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight 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: "pressable cursor-pointer hover:bg-highlight hover:shadow-highlight focus-visible:bg-highlight 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}
@@ -15,7 +15,7 @@
15
15
  bind:ref
16
16
  align="start"
17
17
  class={cn(
18
- 'z-overlay w-max min-w-(--bits-combobox-anchor-width) overflow-hidden rounded-control bg-elevated p-menu shadow-lg glass-blur data-[side=bottom]:rounded-t-none data-[side=top]:rounded-b-none',
18
+ 'z-overlay w-max min-w-(--bits-combobox-anchor-width) overflow-hidden rounded-control material-popover p-menu data-[side=bottom]:rounded-t-none data-[side=top]:rounded-b-none',
19
19
  className
20
20
  )}
21
21
  {sideOffset}
@@ -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}
@@ -21,16 +21,14 @@
21
21
  bind:value
22
22
  class={cn(
23
23
  'flex flex-col gap-gutter',
24
- // glass-blur, like every other floating panel (menus, dialogs, pickers):
25
- // inert on opaque surfaces, blurs the backdrop when the palette floats.
24
+ // material-panel, like every persistent floating surface: opaque on flat/
25
+ // bevel and frosted on glass without naming an implementation here.
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 material-panel p-gutter',
34
32
  className
35
33
  )}
36
34
  {...restProps}
@@ -186,8 +186,8 @@
186
186
 
187
187
  <!-- The terminal command bar: a bare prompt line, not a floating palette. The
188
188
  dropdown anchors under it with no radius (a full-width sheet, like the shell
189
- it mirrors), but its chrome is surface-adaptive via --era-shadow-lg +
190
- glass-blur: a 1px hairline at the divider colour on flat, the chisel frame
189
+ it mirrors), but its chrome is surface-adaptive via material-popover:
190
+ a tone step on flat, the chisel frame
191
191
  on bevel, frost on glass — so it reads as "dedicated" on every surface, not
192
192
  an undifferentiated rectangle.
193
193
 
@@ -273,7 +273,7 @@
273
273
  role="listbox"
274
274
  tabindex="-1"
275
275
  aria-label="Commands"
276
- class="absolute top-full left-0 z-overlay max-h-64 w-full overflow-x-hidden overflow-y-auto bg-elevated shadow-lg glass-blur"
276
+ class="absolute top-full left-0 z-overlay max-h-64 w-full overflow-x-hidden overflow-y-auto material-popover"
277
277
  onmousedown={(e) => e.preventDefault()}
278
278
  >
279
279
  {#if !filtered.length}
@@ -24,10 +24,7 @@
24
24
  // anchor bar (the reference terminal look) — while glass and bevel keep the
25
25
  // 2px frame that stops a full-width highlight from breaking their chrome.
26
26
  // A fixed gutter was tried here and rejected: it padded flat menus too.
27
- class={cn(
28
- 'z-overlay w-max overflow-hidden rounded-control bg-elevated p-menu shadow-lg glass-blur',
29
- className
30
- )}
27
+ class={cn('z-overlay w-max overflow-hidden rounded-control material-popover p-menu', className)}
31
28
  {sideOffset}
32
29
  {...restProps}
33
30
  >
@@ -18,10 +18,7 @@
18
18
  <ContextMenu.SubContent
19
19
  bind:ref
20
20
  {...relay?.attrs}
21
- class={cn(
22
- 'z-overlay w-max overflow-hidden rounded-control bg-elevated p-menu shadow-lg glass-blur',
23
- className
24
- )}
21
+ class={cn('z-overlay w-max overflow-hidden rounded-control material-popover p-menu', className)}
25
22
  {sideOffset}
26
23
  {...restProps}
27
24
  >
@@ -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}
@@ -14,7 +14,7 @@
14
14
  <DatePicker.Content
15
15
  bind:ref
16
16
  align="start"
17
- class={cn('z-overlay rounded-bar bg-elevated p-content shadow-lg glass-blur', className)}
17
+ class={cn('z-overlay rounded-bar material-popover p-content', className)}
18
18
  {sideOffset}
19
19
  {...restProps}
20
20
  >
@@ -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}
@@ -14,7 +14,7 @@
14
14
  <DateRangePicker.Content
15
15
  bind:ref
16
16
  align="start"
17
- class={cn('z-overlay rounded-bar bg-elevated p-content shadow-lg glass-blur', className)}
17
+ class={cn('z-overlay rounded-bar material-popover p-content', className)}
18
18
  {sideOffset}
19
19
  {...restProps}
20
20
  >
@@ -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}
@@ -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. -->
@@ -57,7 +75,7 @@
57
75
  {...relay?.attrs}
58
76
  class={cn(
59
77
  relay?.schemeClass,
60
- 'fixed top-1/2 left-1/2 z-overlay flex max-h-[85dvh] w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col bg-well shadow-lg glass-blur',
78
+ 'fixed top-1/2 left-1/2 z-overlay flex max-h-[85dvh] w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col material-panel',
61
79
  // No header: the panel itself is the body, so the panel scrolls.
62
80
  header ? 'rounded-control' : 'gap-gutter overflow-y-auto rounded-bar p-card',
63
81
  className
@@ -33,7 +33,7 @@
33
33
  // floating menu, like the context menu it should match: full radius, a
34
34
  // gutter of air, shadow doing the separating.
35
35
  class={cn(
36
- 'z-overlay w-max min-w-(--bits-dropdown-menu-anchor-width) overflow-hidden rounded-control bg-elevated p-menu shadow-lg glass-blur',
36
+ 'z-overlay w-max min-w-(--bits-dropdown-menu-anchor-width) overflow-hidden rounded-control material-popover p-menu',
37
37
  className
38
38
  )}
39
39
  {sideOffset}
@@ -18,10 +18,7 @@
18
18
  <DropdownMenu.SubContent
19
19
  bind:ref
20
20
  {...relay?.attrs}
21
- class={cn(
22
- 'z-overlay w-max overflow-hidden rounded-control bg-elevated p-menu shadow-lg glass-blur',
23
- className
24
- )}
21
+ class={cn('z-overlay w-max overflow-hidden rounded-control material-popover p-menu', className)}
25
22
  {sideOffset}
26
23
  {...restProps}
27
24
  >
@@ -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}