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
use uhura::ui; — unstyled primitives, essentially html. Behavior-purposeful, things anyone can agree on (button).
Styled kits as separate opt-in modules (use uhura::shadcnui; as an example). Styled/opinionated components (attachment) are effectively themes, not primitives — attachment appears nowhere in the checked catalog today.
Proposed constraint that keeps this safe: a kit composes and skins primitives but cannot introduce new checked elements — aria, event payloads, and determinism stay in the core, and normalization happens once instead of per kit. Kits mirror onto primitives, so they are not a one-day job; the one-day scope below is primitives only.
Scope fence: this issue stays at the primitive vocabulary layer. The reusable presentation / component contract is #27's "UI composition" question; the kit constraint above touches that boundary and should be decided consistently with it.
Enumeration (the current checked vocabulary, ui_catalog/elements.rs)
element
content
interactive
events (payload)
html counterpart
button
children
yes
press (Unit)
<button>
input
void
yes
input (TextField), change (BoundaryNumberField)
<input>
textfield
void
yes
change (TextField), submit (Unit)
<input>
text
children
no
—
span/p
view
children
no
—
div
scroll
children
yes
near-end (Unit)
overflow div
img
void
no
—
<img>
video
void
yes
—
<video>
icon
void
no
—
— (convention)
region
children
yes
activate, activate-double (Unit)
section + button semantics
progress
children
no
—
<progress>
fieldset
children
no
—
<fieldset>
pager
children
yes
page-change (Unit)
none
Link
children
yes
follow (Unit)
<a>
Surface
children
no
—
dialog-ish, spec gap
Decisions this study should make
input vs textfield overlap. Two input-shaped primitives coexist with different event contracts (typed input/change vs change + submit). One should be canonical, or the split needs a stated rule.
Conditional display.<match> (the svg <switch> role) was proposed instead of tabs. Worth enumerating as a candidate; the element name collides with the core match expression keyword, so the markup/expression namespace question needs a call.
Event payload rule. Payload kinds already exist (Unit, TextField, BoundaryNumberField). When is Unit enough (notify) and when must an event carry a value? pager is the current outlier.
Aria ownership. Realizations live in the renderer today (pager → role=group, region → role=button). Is the aria mapping part of the primitive's contract (kits may not override), or renderer discretion?
Out of scope: surfaces/modality. That contract is explicitly undecided in #27, and the play comment-modal misplacement comes from the same gap — it deserves its own track rather than a corner of this one.
Deliverable
One page: primitive × {name + required attributes, event payload, aria realization, static preview pose} — direct input for the ui sub-specification.
Premise (decide first)
From team discussion, ui splits into two systems:
use uhura::ui;— unstyled primitives, essentially html. Behavior-purposeful, things anyone can agree on (button).use uhura::shadcnui;as an example). Styled/opinionated components (attachment) are effectively themes, not primitives —attachmentappears nowhere in the checked catalog today.Proposed constraint that keeps this safe: a kit composes and skins primitives but cannot introduce new checked elements — aria, event payloads, and determinism stay in the core, and normalization happens once instead of per kit. Kits mirror onto primitives, so they are not a one-day job; the one-day scope below is primitives only.
Scope fence: this issue stays at the primitive vocabulary layer. The reusable presentation / component contract is #27's "UI composition" question; the kit constraint above touches that boundary and should be decided consistently with it.
Enumeration (the current checked vocabulary,
ui_catalog/elements.rs)button<button>input<input>textfield<input>textviewscrollimg<img>video<video>iconregionprogress<progress>fieldset<fieldset>pagerLink<a>SurfaceDecisions this study should make
inputvstextfieldoverlap. Two input-shaped primitives coexist with different event contracts (typedinput/changevschange+submit). One should be canonical, or the split needs a stated rule.pager. The only interactive element with no html counterpart (scroll snap is a CSS mechanic, not an element). Itspage-changepayload isUnit— a machine learns that the page changed, never which — and it owns anindicator. Certain set, or does it wait with the compositions (carousel = pager + button, Prior study: Uhura element and widget candidate landscape #19 / docs(studies): carousel and pager candidate study #25)?<match>(the svg<switch>role) was proposed instead of tabs. Worth enumerating as a candidate; the element name collides with the corematchexpression keyword, so the markup/expression namespace question needs a call.Unitenough (notify) and when must an event carry a value?pageris the current outlier.pager→ role=group,region→ role=button). Is the aria mapping part of the primitive's contract (kits may not override), or renderer discretion?Out of scope: surfaces/modality. That contract is explicitly undecided in #27, and the play comment-modal misplacement comes from the same gap — it deserves its own track rather than a corner of this one.
Deliverable
One page: primitive × {name + required attributes, event payload, aria realization, static preview pose} — direct input for the
uisub-specification.