You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 1ed7e8e
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: packages/pretui/components/combobox.md
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,18 +32,20 @@ The difference from **Autocomplete** is what counts as a value. A combobox's val
32
32
33
33
Where Pretui is better: the explicit split from Autocomplete. Most kits ship one component with a `freeSolo` or `allowsCustomValue` flag, which means the value's _type_ changes with a boolean — a caller has to handle both shapes everywhere. Two components with two contracts is the clearer answer.
34
34
35
-
Where it is thinner: no async loading, no grouped or sectioned options, no multi-select, and no virtualisation — a very long option list renders in full. There is also no "create this" affordance, which is what a `freeSolo` flag usually buys.
35
+
Where it is thinner: no async loading, no grouped or sectioned options, no multi-select, and no virtualization — a very long option list renders in full. There is also no "create this" affordance, which is what a `freeSolo` flag usually buys.
36
36
37
37
## Accessibility
38
38
39
39
-**The input is the combobox** and carries `aria-invalid` when `@invalid`, so the error state is announced rather than only dressed.
40
-
-**`@label` names the input.** Without a wrapper supplying a label, an unnamed combobox is announced as an unlabelled text field with a popup.
40
+
-**`@label` names the input.** Without a wrapper supplying a label, an unnamed combobox is announced as an unlabeled text field with a popup.
41
41
-**`<:option>` is rendered into a row whose accessible name is computed**, so custom markup in the block cannot corrupt what the option announces.
42
42
-**Open and close are reported through `@onOpenChange`**, which a caller needs if it is coordinating with anything else on screen — two popovers open at once is a focus problem.
43
43
-**Local filtering means the list is complete and stable**, so a reader arrowing through options is not racing a fetch.
44
44
45
45
## Theming
46
46
47
-
`--pretui-combobox-max-height` bounds the dropdown, over the kit's shared overlay tokens — `--pretui-shadow-overlay` for the layer, `--pretui-shadow-control` and `--pretui-shadow-inset` for the field, `--pretui-destructive-ink` for the invalid state, and `--pretui-dur-snap` / `--pretui-ease-snap` for the open transition.
47
+
The trigger has Input's field style: a `--field` face with `--foreground` text, an `--input` edge, a `--muted-foreground` placeholder, Button's corner (`calc(var(--radius) - 2px)`), a 1.75rem height (`--boxel-form-control-height-sm`) and `--boxel-font-size-xs` text. On touch screens (`pointer: coarse`) the text and placeholder are at least 16px (`--boxel-form-control-touch-font-size`), so iOS doesn't zoom into the field on focus.
48
+
49
+
Focus is a 1.5px `--ring`, as on Select; invalid is a `--destructive` edge. `--pretui-combobox-max-height` bounds the dropdown, and `--pretui-shadow-overlay` draws its layer.
48
50
49
51
The rules for the combobox's own elements sit in `@layer PretComponent`, so a caller's unlayered CSS overrides them without a more specific selector. The `:deep()` rules that restyle BoxelMultiSelect's power-select markup stay unlayered, because its own rules are unlayered and would beat them from inside a layer.
Copy file name to clipboardExpand all lines: packages/pretui/components/email-input.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,7 +20,7 @@ This is a **thin runtime wrap of boxel-ui's email input**, per the kit's standin
20
20
21
21
Against the field: **Web Awesome** has no email input — `wa-input type="email"` plus native constraint validation, with `label`/`hint` props and slots. **React Spectrum** likewise has no dedicated email field; `TextField type="email"` with a `validate` function. **shadcn** has none.
22
22
23
-
So the honest comparison is against native `type="email"` plus the browser's validation, and the difference is **when the error appears**. Native constraint validation fires on submit and shows a UA bubble that cannot be styled, positioned or announced consistently. The boxel engine's blur-gated, debounced feedback is the behaviour every serious form eventually implements by hand — showing an error while someone is still typing "chris@" is the single most common form-UX mistake.
23
+
So the honest comparison is against native `type="email"` plus the browser's validation, and the difference is **when the error appears**. Native constraint validation fires on submit and shows a UA bubble that cannot be styled, positioned or announced consistently. The boxel engine's blur-gated, debounced feedback is the behavior every serious form eventually implements by hand — showing an error while someone is still typing "chris@" is the single most common form-UX mistake.
24
24
25
25
Where Pretui adds value over boxel-ui: the callback split (above) and API consistency with the rest of the typed-input family — **PhoneInput**, **UrlInput**, **NumberInput** and **PasswordInput** all take the same shape, so they are interchangeable at a call site.
Input's field style: a `--field` face with `--foreground` text, an `--input` edge, a`--muted-foreground`placeholder, Button's corner (`calc(var(--radius) - 2px)`), a 1.75rem height (`--boxel-form-control-height-sm`) and `--boxel-font-size-xs` text. On touch screens (`pointer: coarse`) the text and placeholder are at least 16px (`--boxel-form-control-touch-font-size`), so iOS doesn't zoom into the field on focus.
47
47
48
-
Forwarded into boxel-ui through the `--boxel-*` channel: the form-control height, radius, font sizes and spacing knobs, exactly as **Input** does — the two are dressed to be pixel-identical, so an email field and a text field in the same form align.
48
+
Forwarded into boxel-ui through the `--boxel-*` channel: the form-control height, radius, font sizes and spacing knobs, as **Input** does, so an email field and a text field in the same form line up.
49
49
50
50
An inline `style` carries the font inheritance, because the UA font on native controls is one of the two places the custom-property channel cannot reach. The invalid dress arrives through the token channel from an enclosing **Field** (`--border` → `--destructive`), so it works here without the component knowing about it.
Copy file name to clipboardExpand all lines: packages/pretui/components/input-group.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,7 +32,7 @@ Where it is behind Bootstrap's version: no size axis, and the two-mode API is mo
32
32
33
33
## Accessibility
34
34
35
-
No APG pattern; it is a labelled control plus decorations, governed by WCAG **1.3.1**, **3.3.2** and **4.1.2**.
35
+
No APG pattern; it is a labeled control plus decorations, governed by WCAG **1.3.1**, **3.3.2** and **4.1.2**.
36
36
37
37
Gaps, and the affix one is the interesting one:
38
38
@@ -46,7 +46,7 @@ Gaps, and the affix one is the interesting one:
46
46
47
47
## Theming
48
48
49
-
Consumed: `--field`, `--input`, `--primary` (focus ring via `--ring`), `--ink-3`, `--control-h`, `--radius`, `--text-ui-md`, `--track-ui`, plus **Button**/**IconButton**/**Select**tokens for whatever accessories you place.
49
+
Input's field style: a `--field` face with `--foreground` text, an `--input` edge, Button's corner (`calc(var(--radius) - 2px)`), a 1.75rem height (`--boxel-form-control-height-sm`) and `--boxel-font-size-xs` text. On touch screens (`pointer: coarse`) the text and placeholder are at least 16px (`--boxel-form-control-touch-font-size`), so iOS doesn't zoom into the field on focus. BoxelInputGroup has no placeholder setting, so the placeholder keeps the browser's color. Text accessories and the helper row are `--boxel-font-size-2xs`, a step below the field's text; **Button**/**IconButton**/**Select**accessories bring their own tokens.
50
50
51
51
Forwarded into boxel-ui through the `--boxel-*` channel. `data-state` (the validation enum) and `data-disabled` are reflected on the wrapper, so a stylesheet can dress both without reaching inside.
0 commit comments