@signal9/era-ui 4.7.2 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apps/notes/notes.svelte +22 -10
- package/dist/generated-docs/input.md +3 -1
- package/dist/generated-docs/llms-full.txt +3 -1
- package/dist/generated-docs/manifest.json +1 -1
- package/dist/ui/input/input.svelte +24 -4
- package/dist/ui/input/input.svelte.d.ts +6 -1
- package/dist/ui/input/variants.d.ts +99 -30
- package/dist/ui/input/variants.js +45 -19
- package/package.json +1 -1
|
@@ -151,22 +151,30 @@
|
|
|
151
151
|
>
|
|
152
152
|
<!-- Sidebar: filter + note list -->
|
|
153
153
|
<div class="flex w-56 shrink-0 flex-col border-r border-divider-faded">
|
|
154
|
-
<!--
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
154
|
+
<!-- An md bar holding xxs controls: 24/30/36/48 of chrome around an 18/20/22/26
|
|
155
|
+
field and button. Two tiers apart rather than Bar's usual one, so the
|
|
156
|
+
even gap is --era-xxs-inset-md (3/5/7/11) and the bar's own
|
|
157
|
+
xs-inset-sm padding has to be restated — which is the whole change,
|
|
158
|
+
and why it is spelled here rather than left to the default.
|
|
159
|
+
A notes sidebar is chrome around a list; at the lg/md pairing it was a
|
|
160
|
+
32px bar over 24px rows, and the chrome outweighed the content. This is
|
|
161
|
+
the tier pair term's notes app uses, and its hardcoded 3px IS
|
|
162
|
+
--era-xxs-inset-md at dense. The field keeps its fill: `xxs` is the
|
|
163
|
+
smallest tier a real field fits on. -->
|
|
164
|
+
<Bar
|
|
165
|
+
size="md"
|
|
166
|
+
class="shrink-0 gap-(--era-xxs-inset-md) rounded-none border-b border-divider-faded px-(--era-xxs-inset-md)"
|
|
167
|
+
>
|
|
161
168
|
<Input
|
|
162
169
|
icon={Search}
|
|
170
|
+
size="xxs"
|
|
163
171
|
class="min-w-0 flex-1"
|
|
164
172
|
type="text"
|
|
165
173
|
placeholder="Filter…"
|
|
166
174
|
aria-label="Filter notes"
|
|
167
175
|
bind:value={query}
|
|
168
176
|
/>
|
|
169
|
-
<Button icon aria-label="New note" title="New note" onclick={createNote}>
|
|
177
|
+
<Button icon size="xxs" aria-label="New note" title="New note" onclick={createNote}>
|
|
170
178
|
<Plus />
|
|
171
179
|
</Button>
|
|
172
180
|
</Bar>
|
|
@@ -312,9 +320,12 @@
|
|
|
312
320
|
{#if selected}
|
|
313
321
|
<!-- Matches the sidebar's filter bar exactly — the two headers sit side by
|
|
314
322
|
side across the top of the app, so they must be the same tier. -->
|
|
315
|
-
<Bar
|
|
323
|
+
<Bar
|
|
324
|
+
size="md"
|
|
325
|
+
class="shrink-0 gap-(--era-xxs-inset-md) rounded-none border-b border-divider-faded px-(--era-xxs-inset-md)"
|
|
326
|
+
>
|
|
316
327
|
<Popover.Root bind:open={iconPickerOpen}>
|
|
317
|
-
<Popover.Trigger icon aria-label="Change icon" title="Change icon">
|
|
328
|
+
<Popover.Trigger icon size="xxs" aria-label="Change icon" title="Change icon">
|
|
318
329
|
{#if selected.icon}
|
|
319
330
|
<span aria-hidden="true">{selected.icon}</span>
|
|
320
331
|
{:else}
|
|
@@ -359,6 +370,7 @@
|
|
|
359
370
|
|
|
360
371
|
<Input
|
|
361
372
|
reveal
|
|
373
|
+
size="xxs"
|
|
362
374
|
class="min-w-0 flex-1"
|
|
363
375
|
aria-label="Note title"
|
|
364
376
|
placeholder="Untitled"
|
|
@@ -10,12 +10,14 @@ import { Input } from "$lib/ui/input";
|
|
|
10
10
|
|
|
11
11
|
## Props
|
|
12
12
|
|
|
13
|
-
Inherits all props from `HTMLInputAttributes
|
|
13
|
+
Inherits all props from `Omit<HTMLInputAttributes, 'size'>`.
|
|
14
14
|
|
|
15
15
|
| Prop | Type | Default | Notes |
|
|
16
16
|
|------|------|---------|-------|
|
|
17
17
|
| `ref?` | `HTMLInputElement \| null` | `null` | bindable |
|
|
18
18
|
| `icon?` | `Component<IconProps> \| null` | `null` | Lucide glyph rendered inside the field, left of the text. |
|
|
19
|
+
| `size?` | `'md' \| 'xxs'` | `'md'` | Field tier. `xxs` is badge height — for compact chrome where the field
|
|
20
|
+
sits level with xxs buttons. See inputVariants. |
|
|
19
21
|
| `bare?` | `boolean` | `false` | Drop the field chrome — for an input inside a container that is already the field. |
|
|
20
22
|
| `reveal?` | `boolean` | `false` | Hold the field chrome back until hover — for a title or label that IS the content. |
|
|
21
23
|
| `value?` | `(forwarded)` | `''` | bindable |
|
|
@@ -2848,12 +2848,14 @@ import { Input } from "$lib/ui/input";
|
|
|
2848
2848
|
|
|
2849
2849
|
## Props
|
|
2850
2850
|
|
|
2851
|
-
Inherits all props from `HTMLInputAttributes
|
|
2851
|
+
Inherits all props from `Omit<HTMLInputAttributes, 'size'>`.
|
|
2852
2852
|
|
|
2853
2853
|
| Prop | Type | Default | Notes |
|
|
2854
2854
|
|------|------|---------|-------|
|
|
2855
2855
|
| `ref?` | `HTMLInputElement \| null` | `null` | bindable |
|
|
2856
2856
|
| `icon?` | `Component<IconProps> \| null` | `null` | Lucide glyph rendered inside the field, left of the text. |
|
|
2857
|
+
| `size?` | `'md' \| 'xxs'` | `'md'` | Field tier. `xxs` is badge height — for compact chrome where the field
|
|
2858
|
+
sits level with xxs buttons. See inputVariants. |
|
|
2857
2859
|
| `bare?` | `boolean` | `false` | Drop the field chrome — for an input inside a container that is already the field. |
|
|
2858
2860
|
| `reveal?` | `boolean` | `false` | Hold the field chrome back until hover — for a title or label that IS the content. |
|
|
2859
2861
|
| `value?` | `(forwarded)` | `''` | bindable |
|
|
@@ -9,14 +9,25 @@
|
|
|
9
9
|
ref = $bindable(null),
|
|
10
10
|
value = $bindable(''),
|
|
11
11
|
icon = null,
|
|
12
|
+
size = 'md',
|
|
12
13
|
bare = false,
|
|
13
14
|
reveal = false,
|
|
14
15
|
class: className,
|
|
15
16
|
...restProps
|
|
16
|
-
|
|
17
|
+
// The native `size` attribute (visible width in characters) is shadowed on
|
|
18
|
+
// purpose: era fields size by tier and by flex, never by character count,
|
|
19
|
+
// and `size` is the name every other component in the library uses for its
|
|
20
|
+
// tier. Consumers who genuinely want the HTML attribute can set it via
|
|
21
|
+
// {...restProps} spread from an object.
|
|
22
|
+
}: Omit<HTMLInputAttributes, 'size'> & {
|
|
17
23
|
ref?: HTMLInputElement | null;
|
|
18
24
|
/** Lucide glyph rendered inside the field, left of the text. */
|
|
19
25
|
icon?: Component<IconProps> | null;
|
|
26
|
+
/**
|
|
27
|
+
* Field tier. `xxs` is badge height — for compact chrome where the field
|
|
28
|
+
* sits level with xxs buttons. See inputVariants.
|
|
29
|
+
*/
|
|
30
|
+
size?: 'md' | 'xxs';
|
|
20
31
|
/** Drop the field chrome — for an input inside a container that is already the field. */
|
|
21
32
|
bare?: boolean;
|
|
22
33
|
/** Hold the field chrome back until hover — for a title or label that IS the content. */
|
|
@@ -34,6 +45,13 @@
|
|
|
34
45
|
// chrome" cannot tell a sanctioned exception from a regression — which is the
|
|
35
46
|
// hole the Notes fields sat in. Naming the kind closes it.
|
|
36
47
|
const kind = $derived(reveal ? 'reveal' : bare ? 'bare' : '');
|
|
48
|
+
|
|
49
|
+
// The field's glyph is the icon tier OF ITS OWN TIER, which is what puts it on
|
|
50
|
+
// the same optical footing as the icon button beside it: an md field pairs
|
|
51
|
+
// with a default button (h-xs glyph), an xxs field with an xxs button
|
|
52
|
+
// (icon-xxs). One size for both would leave the two glyphs in one bar drawn at
|
|
53
|
+
// different weights.
|
|
54
|
+
const glyphClass = $derived(size === 'xxs' ? 'size-(--era-icon-xxs)' : 'size-(--era-h-xs)');
|
|
37
55
|
</script>
|
|
38
56
|
|
|
39
57
|
{#if icon}
|
|
@@ -48,9 +66,10 @@
|
|
|
48
66
|
arbitrary container that may carry its own fill. -->
|
|
49
67
|
<div
|
|
50
68
|
data-input-field={kind}
|
|
51
|
-
|
|
69
|
+
data-input-size={size}
|
|
70
|
+
class={cn(inputVariants({ bare, reveal, size }), 'items-center gap-(--era-gap)', className)}
|
|
52
71
|
>
|
|
53
|
-
<Icon class=
|
|
72
|
+
<Icon class={cn('shrink-0 text-muted', glyphClass)} />
|
|
54
73
|
<input
|
|
55
74
|
bind:this={ref}
|
|
56
75
|
bind:value
|
|
@@ -63,7 +82,8 @@
|
|
|
63
82
|
bind:this={ref}
|
|
64
83
|
bind:value
|
|
65
84
|
data-input-field={kind}
|
|
66
|
-
|
|
85
|
+
data-input-size={size}
|
|
86
|
+
class={cn(inputVariants({ bare, reveal, size }), textClass, className)}
|
|
67
87
|
{...restProps}
|
|
68
88
|
/>
|
|
69
89
|
{/if}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
2
|
import type { IconProps } from '@lucide/svelte';
|
|
3
3
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
4
|
-
type $$ComponentProps = HTMLInputAttributes & {
|
|
4
|
+
type $$ComponentProps = Omit<HTMLInputAttributes, 'size'> & {
|
|
5
5
|
ref?: HTMLInputElement | null;
|
|
6
6
|
/** Lucide glyph rendered inside the field, left of the text. */
|
|
7
7
|
icon?: Component<IconProps> | null;
|
|
8
|
+
/**
|
|
9
|
+
* Field tier. `xxs` is badge height — for compact chrome where the field
|
|
10
|
+
* sits level with xxs buttons. See inputVariants.
|
|
11
|
+
*/
|
|
12
|
+
size?: 'md' | 'xxs';
|
|
8
13
|
/** Drop the field chrome — for an input inside a container that is already the field. */
|
|
9
14
|
bare?: boolean;
|
|
10
15
|
/** Hold the field chrome back until hover — for a title or label that IS the content. */
|
|
@@ -24,7 +24,7 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
|
|
|
24
24
|
* edge to edge so the two have no gap between them.
|
|
25
25
|
*/
|
|
26
26
|
bare: {
|
|
27
|
-
false: "
|
|
27
|
+
false: "bg-(--era-field-bg) shadow-(--era-shadow-well) hover:bg-(--era-field-highlight) focus-within:bg-(--era-field-highlight) focus:bg-(--era-field-highlight)";
|
|
28
28
|
true: "bg-transparent shadow-none";
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
@@ -42,21 +42,44 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
|
|
|
42
42
|
true: "bg-transparent shadow-none hover:bg-(--era-field-bg) hover:shadow-(--era-shadow-well) focus-within:shadow-(--era-shadow-well) focus:shadow-(--era-shadow-well)";
|
|
43
43
|
false: "";
|
|
44
44
|
};
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* The field's TIER — height, radius and side padding travel together,
|
|
47
|
+
* because they are one decision. Split them and a field ends up md-tall
|
|
48
|
+
* with xxs corners, which is how the ladder stops being a ladder.
|
|
49
|
+
*
|
|
50
|
+
* - `md` (default) — THE field, and the pairing an md bar's md content
|
|
51
|
+
* expects. Its --era-field-px is glyph-advance derived: the padding a
|
|
52
|
+
* STRING of text wants, not a single centred glyph.
|
|
53
|
+
* - `xxs` — the pill-tier field, at badge height (18/20/22/26). This is the
|
|
54
|
+
* SMALLEST tier that can hold body text at all: its inset is
|
|
55
|
+
* (h-xxs − text)/2, so 2px remain to centre 14px text in, where the tier
|
|
56
|
+
* below (h-xs) IS the text size and has none left. For compact chrome —
|
|
57
|
+
* a filter that sits level with an xxs icon button, a title bar that
|
|
58
|
+
* shouldn't outweigh the document under it. Side padding is
|
|
59
|
+
* --era-pill-xxs, exactly what Badge and Chip use, so a field and a pill
|
|
60
|
+
* on this tier read as one family.
|
|
61
|
+
*/
|
|
62
|
+
size: {
|
|
63
|
+
md: "h-(--era-h-md) rounded-(--era-rd-md) px-(--era-field-px)";
|
|
64
|
+
xxs: "h-(--era-h-xxs) rounded-(--era-rd-xxs) px-(--era-pill-xxs)";
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Height OVERRIDES, for the fields that are not their tier's height. No
|
|
68
|
+
* default: the tier sets the height, and these take it back.
|
|
69
|
+
*/
|
|
46
70
|
height: {
|
|
47
|
-
md: "h-(--era-h-md)";
|
|
48
71
|
full: "h-full";
|
|
49
|
-
auto: "min-h-(--era-h-md)";
|
|
72
|
+
auto: "h-auto min-h-(--era-h-md)";
|
|
50
73
|
};
|
|
51
74
|
/**
|
|
52
|
-
* Side
|
|
53
|
-
* (the date picker's calendar trigger): the leading edge
|
|
54
|
-
* text inset so the text still lines up with every other
|
|
55
|
-
* trailing edge becomes the concentric inset for that
|
|
56
|
-
* its gap to the field edge equals its gap above and
|
|
75
|
+
* Side-padding OVERRIDES, same rule. `trailing` is for a field that holds a
|
|
76
|
+
* control at its end (the date picker's calendar trigger): the leading edge
|
|
77
|
+
* keeps the shared text inset so the text still lines up with every other
|
|
78
|
+
* field, and the trailing edge becomes the concentric inset for that
|
|
79
|
+
* sm-tier control, so its gap to the field edge equals its gap above and
|
|
80
|
+
* below.
|
|
57
81
|
*/
|
|
58
82
|
pad: {
|
|
59
|
-
even: "px-(--era-field-px)";
|
|
60
83
|
trailing: "ps-(--era-field-px) pe-(--era-sm-inset-md)";
|
|
61
84
|
none: "px-0";
|
|
62
85
|
};
|
|
@@ -69,7 +92,7 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
|
|
|
69
92
|
* edge to edge so the two have no gap between them.
|
|
70
93
|
*/
|
|
71
94
|
bare: {
|
|
72
|
-
false: "
|
|
95
|
+
false: "bg-(--era-field-bg) shadow-(--era-shadow-well) hover:bg-(--era-field-highlight) focus-within:bg-(--era-field-highlight) focus:bg-(--era-field-highlight)";
|
|
73
96
|
true: "bg-transparent shadow-none";
|
|
74
97
|
};
|
|
75
98
|
/**
|
|
@@ -87,21 +110,44 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
|
|
|
87
110
|
true: "bg-transparent shadow-none hover:bg-(--era-field-bg) hover:shadow-(--era-shadow-well) focus-within:shadow-(--era-shadow-well) focus:shadow-(--era-shadow-well)";
|
|
88
111
|
false: "";
|
|
89
112
|
};
|
|
90
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* The field's TIER — height, radius and side padding travel together,
|
|
115
|
+
* because they are one decision. Split them and a field ends up md-tall
|
|
116
|
+
* with xxs corners, which is how the ladder stops being a ladder.
|
|
117
|
+
*
|
|
118
|
+
* - `md` (default) — THE field, and the pairing an md bar's md content
|
|
119
|
+
* expects. Its --era-field-px is glyph-advance derived: the padding a
|
|
120
|
+
* STRING of text wants, not a single centred glyph.
|
|
121
|
+
* - `xxs` — the pill-tier field, at badge height (18/20/22/26). This is the
|
|
122
|
+
* SMALLEST tier that can hold body text at all: its inset is
|
|
123
|
+
* (h-xxs − text)/2, so 2px remain to centre 14px text in, where the tier
|
|
124
|
+
* below (h-xs) IS the text size and has none left. For compact chrome —
|
|
125
|
+
* a filter that sits level with an xxs icon button, a title bar that
|
|
126
|
+
* shouldn't outweigh the document under it. Side padding is
|
|
127
|
+
* --era-pill-xxs, exactly what Badge and Chip use, so a field and a pill
|
|
128
|
+
* on this tier read as one family.
|
|
129
|
+
*/
|
|
130
|
+
size: {
|
|
131
|
+
md: "h-(--era-h-md) rounded-(--era-rd-md) px-(--era-field-px)";
|
|
132
|
+
xxs: "h-(--era-h-xxs) rounded-(--era-rd-xxs) px-(--era-pill-xxs)";
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Height OVERRIDES, for the fields that are not their tier's height. No
|
|
136
|
+
* default: the tier sets the height, and these take it back.
|
|
137
|
+
*/
|
|
91
138
|
height: {
|
|
92
|
-
md: "h-(--era-h-md)";
|
|
93
139
|
full: "h-full";
|
|
94
|
-
auto: "min-h-(--era-h-md)";
|
|
140
|
+
auto: "h-auto min-h-(--era-h-md)";
|
|
95
141
|
};
|
|
96
142
|
/**
|
|
97
|
-
* Side
|
|
98
|
-
* (the date picker's calendar trigger): the leading edge
|
|
99
|
-
* text inset so the text still lines up with every other
|
|
100
|
-
* trailing edge becomes the concentric inset for that
|
|
101
|
-
* its gap to the field edge equals its gap above and
|
|
143
|
+
* Side-padding OVERRIDES, same rule. `trailing` is for a field that holds a
|
|
144
|
+
* control at its end (the date picker's calendar trigger): the leading edge
|
|
145
|
+
* keeps the shared text inset so the text still lines up with every other
|
|
146
|
+
* field, and the trailing edge becomes the concentric inset for that
|
|
147
|
+
* sm-tier control, so its gap to the field edge equals its gap above and
|
|
148
|
+
* below.
|
|
102
149
|
*/
|
|
103
150
|
pad: {
|
|
104
|
-
even: "px-(--era-field-px)";
|
|
105
151
|
trailing: "ps-(--era-field-px) pe-(--era-sm-inset-md)";
|
|
106
152
|
none: "px-0";
|
|
107
153
|
};
|
|
@@ -114,7 +160,7 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
|
|
|
114
160
|
* edge to edge so the two have no gap between them.
|
|
115
161
|
*/
|
|
116
162
|
bare: {
|
|
117
|
-
false: "
|
|
163
|
+
false: "bg-(--era-field-bg) shadow-(--era-shadow-well) hover:bg-(--era-field-highlight) focus-within:bg-(--era-field-highlight) focus:bg-(--era-field-highlight)";
|
|
118
164
|
true: "bg-transparent shadow-none";
|
|
119
165
|
};
|
|
120
166
|
/**
|
|
@@ -132,21 +178,44 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
|
|
|
132
178
|
true: "bg-transparent shadow-none hover:bg-(--era-field-bg) hover:shadow-(--era-shadow-well) focus-within:shadow-(--era-shadow-well) focus:shadow-(--era-shadow-well)";
|
|
133
179
|
false: "";
|
|
134
180
|
};
|
|
135
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* The field's TIER — height, radius and side padding travel together,
|
|
183
|
+
* because they are one decision. Split them and a field ends up md-tall
|
|
184
|
+
* with xxs corners, which is how the ladder stops being a ladder.
|
|
185
|
+
*
|
|
186
|
+
* - `md` (default) — THE field, and the pairing an md bar's md content
|
|
187
|
+
* expects. Its --era-field-px is glyph-advance derived: the padding a
|
|
188
|
+
* STRING of text wants, not a single centred glyph.
|
|
189
|
+
* - `xxs` — the pill-tier field, at badge height (18/20/22/26). This is the
|
|
190
|
+
* SMALLEST tier that can hold body text at all: its inset is
|
|
191
|
+
* (h-xxs − text)/2, so 2px remain to centre 14px text in, where the tier
|
|
192
|
+
* below (h-xs) IS the text size and has none left. For compact chrome —
|
|
193
|
+
* a filter that sits level with an xxs icon button, a title bar that
|
|
194
|
+
* shouldn't outweigh the document under it. Side padding is
|
|
195
|
+
* --era-pill-xxs, exactly what Badge and Chip use, so a field and a pill
|
|
196
|
+
* on this tier read as one family.
|
|
197
|
+
*/
|
|
198
|
+
size: {
|
|
199
|
+
md: "h-(--era-h-md) rounded-(--era-rd-md) px-(--era-field-px)";
|
|
200
|
+
xxs: "h-(--era-h-xxs) rounded-(--era-rd-xxs) px-(--era-pill-xxs)";
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Height OVERRIDES, for the fields that are not their tier's height. No
|
|
204
|
+
* default: the tier sets the height, and these take it back.
|
|
205
|
+
*/
|
|
136
206
|
height: {
|
|
137
|
-
md: "h-(--era-h-md)";
|
|
138
207
|
full: "h-full";
|
|
139
|
-
auto: "min-h-(--era-h-md)";
|
|
208
|
+
auto: "h-auto min-h-(--era-h-md)";
|
|
140
209
|
};
|
|
141
210
|
/**
|
|
142
|
-
* Side
|
|
143
|
-
* (the date picker's calendar trigger): the leading edge
|
|
144
|
-
* text inset so the text still lines up with every other
|
|
145
|
-
* trailing edge becomes the concentric inset for that
|
|
146
|
-
* its gap to the field edge equals its gap above and
|
|
211
|
+
* Side-padding OVERRIDES, same rule. `trailing` is for a field that holds a
|
|
212
|
+
* control at its end (the date picker's calendar trigger): the leading edge
|
|
213
|
+
* keeps the shared text inset so the text still lines up with every other
|
|
214
|
+
* field, and the trailing edge becomes the concentric inset for that
|
|
215
|
+
* sm-tier control, so its gap to the field edge equals its gap above and
|
|
216
|
+
* below.
|
|
147
217
|
*/
|
|
148
218
|
pad: {
|
|
149
|
-
even: "px-(--era-field-px)";
|
|
150
219
|
trailing: "ps-(--era-field-px) pe-(--era-sm-inset-md)";
|
|
151
220
|
none: "px-0";
|
|
152
221
|
};
|
|
@@ -27,7 +27,7 @@ export const inputVariants = tv({
|
|
|
27
27
|
* edge to edge so the two have no gap between them.
|
|
28
28
|
*/
|
|
29
29
|
bare: {
|
|
30
|
-
false: '
|
|
30
|
+
false: 'bg-(--era-field-bg) shadow-(--era-shadow-well) hover:bg-(--era-field-highlight) focus-within:bg-(--era-field-highlight) focus:bg-(--era-field-highlight)',
|
|
31
31
|
true: 'bg-transparent shadow-none'
|
|
32
32
|
},
|
|
33
33
|
/**
|
|
@@ -45,34 +45,60 @@ export const inputVariants = tv({
|
|
|
45
45
|
true: 'bg-transparent shadow-none hover:bg-(--era-field-bg) hover:shadow-(--era-shadow-well) focus-within:shadow-(--era-shadow-well) focus:shadow-(--era-shadow-well)',
|
|
46
46
|
false: ''
|
|
47
47
|
},
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* The field's TIER — height, radius and side padding travel together,
|
|
50
|
+
* because they are one decision. Split them and a field ends up md-tall
|
|
51
|
+
* with xxs corners, which is how the ladder stops being a ladder.
|
|
52
|
+
*
|
|
53
|
+
* - `md` (default) — THE field, and the pairing an md bar's md content
|
|
54
|
+
* expects. Its --era-field-px is glyph-advance derived: the padding a
|
|
55
|
+
* STRING of text wants, not a single centred glyph.
|
|
56
|
+
* - `xxs` — the pill-tier field, at badge height (18/20/22/26). This is the
|
|
57
|
+
* SMALLEST tier that can hold body text at all: its inset is
|
|
58
|
+
* (h-xxs − text)/2, so 2px remain to centre 14px text in, where the tier
|
|
59
|
+
* below (h-xs) IS the text size and has none left. For compact chrome —
|
|
60
|
+
* a filter that sits level with an xxs icon button, a title bar that
|
|
61
|
+
* shouldn't outweigh the document under it. Side padding is
|
|
62
|
+
* --era-pill-xxs, exactly what Badge and Chip use, so a field and a pill
|
|
63
|
+
* on this tier read as one family.
|
|
64
|
+
*/
|
|
65
|
+
size: {
|
|
66
|
+
md: 'h-(--era-h-md) rounded-(--era-rd-md) px-(--era-field-px)',
|
|
67
|
+
xxs: 'h-(--era-h-xxs) rounded-(--era-rd-xxs) px-(--era-pill-xxs)'
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* Height OVERRIDES, for the fields that are not their tier's height. No
|
|
71
|
+
* default: the tier sets the height, and these take it back.
|
|
72
|
+
*/
|
|
49
73
|
height: {
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// which is the even-gap law failing by a hair rather than obviously.
|
|
74
|
+
// h-full, NOT a tier height: a bare input's container IS the field, so it
|
|
75
|
+
// takes that container's height. Keeping a tier height here made a bare
|
|
76
|
+
// input inside an h-md Bar overflow it by the bar's border — a −0.5px
|
|
77
|
+
// gap, which is the even-gap law failing by a hair rather than obviously.
|
|
55
78
|
full: 'h-full',
|
|
56
|
-
|
|
79
|
+
// h-auto is load-bearing — it is what outranks the tier's own height so
|
|
80
|
+
// the field can grow with its content (Textarea).
|
|
81
|
+
auto: 'h-auto min-h-(--era-h-md)'
|
|
57
82
|
},
|
|
58
83
|
/**
|
|
59
|
-
* Side
|
|
60
|
-
* (the date picker's calendar trigger): the leading edge
|
|
61
|
-
* text inset so the text still lines up with every other
|
|
62
|
-
* trailing edge becomes the concentric inset for that
|
|
63
|
-
* its gap to the field edge equals its gap above and
|
|
84
|
+
* Side-padding OVERRIDES, same rule. `trailing` is for a field that holds a
|
|
85
|
+
* control at its end (the date picker's calendar trigger): the leading edge
|
|
86
|
+
* keeps the shared text inset so the text still lines up with every other
|
|
87
|
+
* field, and the trailing edge becomes the concentric inset for that
|
|
88
|
+
* sm-tier control, so its gap to the field edge equals its gap above and
|
|
89
|
+
* below.
|
|
64
90
|
*/
|
|
65
91
|
pad: {
|
|
66
|
-
even: 'px-(--era-field-px)',
|
|
67
92
|
trailing: 'ps-(--era-field-px) pe-(--era-sm-inset-md)',
|
|
68
93
|
none: 'px-0'
|
|
69
94
|
}
|
|
70
95
|
},
|
|
71
96
|
compoundVariants: [
|
|
72
|
-
// Chrome and
|
|
73
|
-
// pad. Spelling this as a compound rather
|
|
74
|
-
// what stops `bare` from becoming a
|
|
75
|
-
|
|
97
|
+
// Chrome, padding and corners travel together: a field with no chrome has
|
|
98
|
+
// no box to pad and no corners to round. Spelling this as a compound rather
|
|
99
|
+
// than leaving it to the caller is what stops `bare` from becoming a
|
|
100
|
+
// second, differently-padded field.
|
|
101
|
+
{ bare: true, class: 'h-full rounded-none px-0' }
|
|
76
102
|
],
|
|
77
|
-
defaultVariants: { bare: false, reveal: false,
|
|
103
|
+
defaultVariants: { bare: false, reveal: false, size: 'md' }
|
|
78
104
|
});
|