Skip to content

Prior study: Uhura element and widget candidate landscape #19

Description

@softmarshmallow

Status

Prior study / research handoff. Decision open.

This issue is a non-normative evidence map for a future owner. It does not reserve names or syntax, classify any candidate permanently, add a built-in, authorize implementation, establish a roadmap, or create an RFC.

The sources and repository observations below are a snapshot. Whoever takes up a candidate should verify that the platform standards, toolkit APIs, provider policies, and Uhura implementation have not changed, then make the decision in that candidate's own context.

Purpose

Uhura wants practical, accessible defaults without turning every familiar UI pattern, native control, or branded service into language law.

The canonical widget documentation distinguishes:

  • primary forms: Element, Surface, and Pattern;
  • cross-cutting facets: Integration and Behavior; and
  • availability, decision status, and implementation status.

Those categories are the vocabulary for the investigation, not predetermined answers. A first-party capability can be useful and officially maintained without necessarily becoming a base-language Element.

This issue collects prior evidence and unanswered questions so that later work does not have to restart from a list of names.

Current Uhura snapshot

Repository evidence at the time of this study:

  • The canonical catalogue home is docs/widgets/README.md.
  • Canonical entries currently cover button, scroll, icon, img, and view.
  • The project-pinned base machine catalog also declares video and pager, but their presence is implementation evidence rather than acceptance: base.toml.
  • The browser currently realizes video as native HTML video in Play and a poster-only representation in Editor: appliers.ts.
  • The current catalog schema has layout/content/interactive classes; a small fixed set of child models; text, bool, int, enum, asset, and icon-related property types; input/observe events; and limited event payload types: catalog.rs.
  • The deterministic value model deliberately has no binary floating-point value: value.rs.

Consequences to re-check before designing any candidate:

  • There is no exact fraction, general decimal, date, URL, geographic, or ink/document value type.
  • There are no general named slots, part/anatomy declarations, media controllers, or behavior/modifier attachments.
  • Controlled promotion currently describes one prop/event pair rather than a compound widget with several controlled aspects.
  • Editor preview data and runtime Core state are intentionally different authorities.

These are constraints of the studied revision, not permanent requirements.

Cross-cutting findings to carry forward

These are framing observations, not decisions.

Semantic value versus proportional pose

A useful distinction emerged between:

  • a dimensionless proportion or pose, such as opacity, scroll position, media progress, reveal amount, or animation progress; and
  • a domain value, such as temperature, price, a civil date, an OTP string, latitude, or a selected row ID.

The existing proposal that unitless proportions use normalized exact values in the range 0 through 1 remains coherent. It should not be applied merely because a property happens to be named “value.” A future owner still needs to decide the exact scalar representation and where normalization is appropriate.

Content, state machine, and chrome are separate contracts

Media demonstrated that a content element, its live playback/controller state, and its visible controls can have different owners. HTML can bundle them; native toolkits often expose them as layers. This distinction may also matter for maps, charts, date pickers, and data grids.

“Good default” does not require base syntax

A maintained Pattern or opt-in catalogue can supply composition, accessibility, validation, and styling defaults without making the capability part of the smallest base catalog. Conversely, an Element may be warranted when renderer-owned interaction cannot be reproduced safely from existing primitives.

Provider integrations are not ordinary assets

YouTube, Google Maps, arbitrary web content, and similar services bring provider policy, credentials, privacy, failure, mutable remote state, and renderer support. A provider-neutral semantic subset may or may not exist; it should be demonstrated rather than assumed.

Static preview pose is not runtime application state

A preview may need to show a scrolled viewport, selected page, partially revealed action, media progress, validation error, displayed calendar month, or chart selection. The future owner should state whether that pose is Editor-only, renderer-owned at runtime, or authored Core state, and should not silently conflate them.

Accessibility is part of the contract

For compound widgets, a role or accessible label alone is insufficient. Focus movement, keyboard operation, announcements, reduced motion, non-drag alternatives, inactive-content exposure, validation timing, and provider-owned controls may determine whether a candidate needs first-party behavior.

Candidate research notes

Every disposition below remains open.

Timed media

Video / video player / controls

Current evidence:

  • Uhura already declares video and maps it to native HTML video, but exposes only a small property set and no playback commands, lifecycle events, timed-text tracks, alternative sources, or error/loading contract.
  • HTML video is built on the shared HTMLMediaElement state machine. The controls attribute asks the user agent to supply its own UI; custom controls are a separate authoring problem: WHATWG media.
  • Flutter, Android Media3, and Apple AVFoundation/AVKit expose raw playback, rendering, and player chrome in separate layers: Flutter video_player, Android PlayerSurface, Apple AVPlayer.

Questions left for the owner:

  • Is video accepted as a base Element, moved to an opt-in catalog, or otherwise revised?
  • Are default controls absent, present as Uhura's good default, or selected by an explicit mode?
  • What is the smallest semantic command/observation contract?
  • Which state remains renderer-owned rather than mirrored into deterministic Core state?
  • How are captions, descriptions, tracks, fullscreen, picture-in-picture, autoplay, audio focus, errors, live streams, and alternative sources represented?
  • Does a normalized preview position pose only the controls, or may it request a decoded frame? The current poster-only Editor avoids remote fetch and decode.

Audio / audio player / controls

Evidence:

  • HTML audio and video share HTMLMediaElement, while raw audio has no visual playback area when controls are absent: WHATWG media.
  • Native playback systems likewise separate a nonvisual player from application or system chrome.
  • Background playback adds media-session, lock-screen, headset, interruption, and audio-focus behavior beyond a basic content element.

Questions:

  • Should audio share one media behavior/controller with video?
  • What deterministic Editor representation exists for raw audio?
  • Is an audio-player UI a Pattern, a compound opt-in widget, or part of the Element's contract?
  • How are transcripts, artwork, metadata, playlists, waveform data, and background playback handled?

Embedded content and external services

Webview / iframe

Evidence:

  • HTML iframe is a nested browsing context with sandbox, Permissions Policy, referrer policy, loading policy, and CSP framing restrictions: WHATWG iframe.
  • Native WebViews additionally expose navigation, history, storage, cookies, scripts, platform delegates, and potentially dangerous native bridges: Android WebView security.

Questions:

  • Is the intended capability specifically an HTML iframe or a narrower renderer-neutral webview?
  • What URL type, origin/navigation allowlist, storage policy, permission policy, bridge policy, popup/download policy, and failure fallback are required?
  • Is arbitrary remote content allowed at all in the base catalog?
  • What does a non-web renderer do?
  • Should Editor always use a placeholder or explicit local screenshot?

YouTube player

Evidence:

  • YouTube is a remote, branded player with provider-specific states, errors, captions, playlists, autoplay behavior, privacy implications, branding, and minimum-functionality requirements: IFrame API, required minimum functionality.
  • It is not equivalent to a local video asset and cannot necessarily share a fully custom visual-control contract.

Questions:

  • Is the first capability a simple embed or a controllable player?
  • Which shared media commands and observations, if any, are provider-portable?
  • What are the consent, click-to-load, privacy-enhanced, failure, regional, age, and unembeddable-content policies?
  • Is the authoring surface explicitly provider-branded?
  • What static placeholder or preview asset is required?

Maps / Google Maps

Evidence:

  • Google Maps Embed and full Maps SDKs are materially different capabilities: Embed API, JavaScript Map API.
  • Full map APIs converge somewhat around camera/region, annotations, paths, gestures, controls, and selection, but provider zoom scales, tiles, POIs, routing, imagery, styling, attribution, credentials, and policy differ.
  • HTML already defines a map element for image maps, creating a naming conflict for geographic maps.

Questions:

  • Is the target a simple branded embed or a full geographic scene?
  • Can a provider-neutral contract be demonstrated around bounds/region and labelled annotations?
  • Who owns camera state after user gestures?
  • How are coordinates represented in Uhura's deterministic value model?
  • How are credentials, attribution, user-location permission, mock location, offline/error state, and Editor preview handled?
  • What name remains honest about provider and semantics?

Values and form controls

Progress

Evidence:

  • HTML progress represents task completion, with omitted value meaning indeterminate, and explicitly differs from a gauge/meter: WHATWG progress.
  • Flutter and Compose commonly use a normalized determinate fraction and a separate indeterminate state: Compose progress.
  • ARIA omits aria-valuenow for indeterminate progress.

Questions:

  • Does Uhura accept only a normalized completion fraction or also arbitrary value/max units?
  • What exact scalar type represents it?
  • Is accessible value text separate from machine completion?
  • How is indeterminate motion represented in Play and frozen deterministically in Editor?
  • Is meter/gauge explicitly a separate future capability?

Slider

Evidence:

  • HTML, ARIA, Flutter, Compose, Radix, and Base UI treat slider value as an actual numeric domain with min, max, step, orientation, and human-readable value text where needed: WHATWG range, ARIA slider, Radix Slider.

Questions:

  • What exact numeric/domain type is required?
  • If min/max are omitted, should Uhura's default domain be normalized 0 through 1?
  • Are continuous change and terminal commit distinct events?
  • Which transient drag state is renderer-owned?
  • Are ticks, labelled values, orientation, RTL behavior, and value text in the base contract?
  • Is a multi-thumb range slider a separate later candidate?

OTP input

Evidence:

  • HTML has no OTP element; it supplies a one-time-code autofill hint to a text control.
  • Existing component systems generally present visual slots while preserving one logical string value and one logical input: shadcn OTP.

Questions:

  • Can a future textfield contract express correct autofill, paste, IME, caret, maxlength, and slotted presentation, or is an opt-in Element required?
  • What length and character policies exist?
  • Are codes allowed to be alphanumeric and unmasked?
  • Does completion merely emit an event, or may it submit?
  • Who owns invalid/error state and active-slot preview pose?

Form / form validation

Evidence:

  • HTML form defines ownership, submission, reset, and constraint validation rather than merely layout: WHATWG forms.
  • Other UI systems differ: some aggregate form fields, some use form primarily for platform grouping, and some rely on hoisted application validation.

Questions:

  • What is a form in Uhura: semantic grouping, value aggregation, validation scope, submit-intent owner, or several separable contracts?
  • How are labels, descriptions, errors, summaries, focus, attempted/touched state, pending state, reset, and server outcomes represented?
  • Which validation is deterministic Core logic, and which external validation returns through effects?
  • Does submit emit typed values without inheriting HTML action/method network behavior?
  • How does Enter in textfield interact with form submission and IME composition?

Signature / freehand / general drawing

Evidence:

  • HTML canvas is a scriptable bitmap with fallback obligations, not a semantic signature control: WHATWG canvas.
  • Pointer Events expose coordinates, pressure, tilt, and coalesced events but do not define a stored drawing document: Pointer Events.
  • Platform ink systems use different stroke and document models.

Questions:

  • Is signature a specialized form Pattern, an opt-in widget, or outside the first-party catalog?
  • Is there a reusable lower ink/freehand surface, and if so what is its serialization, coordinate space, pressure/brush model, undo ownership, export type, and fallback?
  • Can the renderer keep live strokes locally and commit one typed asset/document to Core?
  • What accessible clear/undo and non-signature acknowledgment alternatives are required?
  • Does general drawing belong in the language at all?

Button / icon button

Evidence:

  • Uhura already has a generic button Element with explicit accessible label and content children: button catalogue entry.
  • HTML and ARIA use the same semantic button for text, icon, or combined content. Toolkit-specific IconButton APIs often add presentation, hit-target, tooltip, and selected-state conveniences rather than a distinct action role.

Questions:

  • Is icon-only presentation fully covered by button plus icon and a maintained style/profile?
  • Should the checker derive or compare visible text and accessible label?
  • How should nested content be constrained?
  • Which toggle/current/form-submit semantics belong on generic button versus separate controls?

Calendar / date

Evidence:

  • HTML date input stores a civil date separately from localized display: WHATWG date input.
  • The ARIA date-picker example composes a field, trigger, dialog, calendar grid, focus management, selection, and displayed month: APG date picker.
  • Toolkits also distinguish date field, inline month grid, popup/dialog picker, multi-date selection, and scheduling calendars.

Questions:

  • Which candidate is actually being designed: date field, date picker, inline month grid, multi-date/range control, or event calendar?
  • What is Uhura's civil-date/instant/calendar/time-zone model?
  • Who owns selected date, focused day, displayed month, and open Surface?
  • What preview inputs pin “today,” locale, calendar, time zone, first weekday, and selected/displayed state?
  • What declarative min/max/selectability rules are portable?

Viewports, gestures, and motion

Carousel and existing pager

Evidence:

  • Uhura's current pager supplies a visual scroll-snap viewport with optional dots, but lacks a settled controlled/current-page, preview, event, and accessibility contract.
  • ARIA carousel adds slide semantics, previous/next controls, optional direct slide pickers, and strict auto-rotation behavior: APG Carousel.
  • CSS Scroll Snap supplies a paging mechanic while deliberately leaving exact physics to the user agent: CSS Scroll Snap.

Questions:

  • What is pager's smallest renderer-neutral contract?
  • Is current page controlled, observed, or renderer-owned?
  • How do stable keys, inactive slides, page size, direction, page change, and static preview work?
  • Is carousel a Pattern over pager, an opt-in compound widget, or a separate Element?
  • How are real controls, interactive indicators, autoplay, focus/hover stopping, reduced motion, and non-drag alternatives guaranteed?

Swipe actions

Evidence:

Questions:

  • Does Uhura need a general behavior/modifier attachment before this capability?
  • Are logical leading/trailing actions named slots?
  • Is full-swipe execution allowed, and how are destructive confirmation/undo handled?
  • What non-gesture route exposes the same actions?
  • Is temporary reveal offset renderer-owned, with an Editor-only normalized reveal pose?
  • If no behavior system exists, is a temporary wrapper honest enough or should syntax wait?

Swipeable stack

Evidence:

  • General toolkit primitives model drag/dismiss thresholds and emit a settled decision; the application removes or reorders data. A Tinder-style deck adds product semantics, stacking, rotation, accept/reject conventions, and undo: Flutter Dismissible.
  • WCAG requires alternatives to dragging/path gestures where the gesture is not essential: Dragging Movements.

Questions:

  • What generic drag/dismiss behavior exists below the product Pattern?
  • Does the renderer own live offset/velocity while Core owns order, meaning, removal, and undo?
  • What typed direction/action event is emitted at settlement?
  • What keyboard and visible-button alternatives are mandatory?
  • What top-card and partial-drag state can Editor pose deterministically?

“Staggered”

Evidence:

  • The term is ambiguous between masonry/grid-lanes layout and delayed animation sequencing.
  • CSS Grid Level 3's masonry/grid-lanes work is evolving and raises reading-order and intrinsic-sizing questions: CSS Grid Level 3.
  • Animation staggering is a timing operation over an ordered/keyed set; CSS tree-counting functions can calculate per-sibling delays without creating an element: CSS Values Level 5.

Questions:

  • Which meaning is intended?
  • For masonry, what source/semantic order, deterministic sizing, scrolling, and renderer fallback are required?
  • For animation, what order, timeline, delay distribution, interruption, reversal, insertion/removal, and reduced-motion rules apply?
  • Does either concept belong in element syntax, CSS/layout, or a shared Behavior?
  • How is normalized static animation progress represented?

Content and data presentation

Markdown

Evidence:

  • Markdown has multiple dialects. CommonMark includes raw HTML; GFM adds tables, task lists, autolinks, and strikethrough: CommonMark, GFM.
  • A renderer-neutral implementation needs a semantic document AST or expansion target, not arbitrary HTML injection.

Questions:

  • Is Markdown static authoring syntax, a dynamic content Element, an imported source-format Integration, or more than one capability?
  • Which dialect and parser version are pinned?
  • Is raw HTML disabled?
  • What are the link, image, code, highlighting, remote-resource, and sanitization policies?
  • Which semantic heading/list/link/table/code elements must exist first?
  • Where does dynamic parsing occur, and how is deterministic output tested?

Chat

Evidence:

  • Existing systems generally compose chat from message rows, transcript scrolling, input, attachments, and application state rather than exposing one universal Chat control.
  • Shadcn's MessageScroller deliberately owns anchoring, streaming follow mode, prepend preservation, and visibility while not owning messages, transport, persistence, branching, or model state: MessageScroller.
  • ARIA log/live-region semantics are relevant to chat transcripts: ARIA log.

Questions:

  • Is chat only a maintained Pattern/kit?
  • Is transcript/message scrolling a reusable first-party behavior or Element?
  • Who owns messages, identity, delivery, branching, persistence, transport, streaming, and busy state?
  • How are stable row IDs, prepended history, follow-latest behavior, announcements, focus preservation, and “reader moved away” handled?
  • What fixed transcript, streaming/completed state, and scroll pose does Editor show?

Data table / data grid

Evidence:

  • ARIA distinguishes static table semantics from the interactive grid composite. A grid owns keyboard focus movement and may add selection, editing, sorting, and virtualization: APG Table, APG Grid.
  • Shadcn intentionally provides a construction guide over Table and TanStack rather than one universal data-table component: shadcn Data Table.

Questions:

  • What foundational semantic table elements and child grammar are needed?
  • Is interactive data grid a separate opt-in subsystem?
  • Which sort, filter, page, selection, edit, column-width, focus, and viewport states are controlled?
  • How are server/query authority, total row counts, virtualization indexes, and accessibility represented?
  • Which static rows and UI poses are required for deterministic examples?
  • Is any monolithic datatable abstraction sufficiently portable?

Chart

Note

Dedicated follow-up: #40. That RFD owns the active Chart decision; the evidence and questions below remain its prior-study handoff.

Evidence:

  • Swift Charts and Vega-Lite model charts compositionally through data, marks, encodings, scales, axes, legends, and interactions rather than only a type switch: Swift Charts, Vega-Lite.
  • Accessible chart descriptions should derive from declared data and series, not reconstructed geometry.

Questions:

  • Does Uhura define a small chart grammar, import a constrained grammar, or support provider-specific integrations?
  • Is the result one Element, an Element family/sub-language, or an Integration?
  • How are data shape, transforms, domains, marks, scales, axes, legends, selections, zoom, locale, time zone, and tick generation represented?
  • What summary and detailed/table alternative is mandatory?
  • Which hover/focus/zoom/animation state remains renderer-owned?
  • What selected datum and animation progress can Editor pose?

Common questions for any future owner

Before promoting or rejecting a candidate, answer:

  1. What user problem requires first-party support?
  2. What is the smallest provider- and renderer-neutral semantic contract?
  3. Is its primary form an Element, Surface, or Pattern? Which Integration or Behavior facets apply?
  4. Can existing elements, components, CSS, and host capabilities express it without losing semantics, accessibility, validation, or deterministic behavior?
  5. Who owns state, effects, lifecycle, failure, and external authority: Core, renderer, host, or service?
  6. What must the checker validate statically?
  7. What are the naming, focus, keyboard, announcement, reduced-motion, and non-gesture requirements?
  8. What deterministic Editor state or pose is needed?
  9. What are the renderer fallback, offline, privacy, sandbox, credential, and security boundaries?
  10. Is it base, opt-in, a maintained library/Pattern, deferred, or rejected?
  11. Is the proposed name language-honest?
  12. What conformance tests would distinguish a real portable contract from one browser implementation?

Possible dispositions

No disposition is chosen in this issue. A future owner may:

  • promote a candidate to a dedicated catalogue entry;
  • record it as a Pattern, Integration, or shared Behavior without adding a primitive;
  • split the name into multiple independently owned capabilities;
  • defer it pending a prerequisite;
  • reject it with a durable reason; or
  • prepare an RFC after a clean conclusion requires durable language/runtime law.

An existing prototype does not force acceptance. A popular toolkit component does not force base syntax. A previous working hypothesis does not bind the future owner.

Possible prerequisite studies

This is a dependency map, not a roadmap or required order:

  • exact proportional and domain numeric values;
  • temporal and URL/resource types;
  • compound-widget anatomy, slots, and accessible relationships;
  • instance identity plus controller/command/observation contracts;
  • attachable Behavior/modifier model;
  • deterministic Editor-only pose addressing;
  • external integration permissions, credentials, privacy, and fallback;
  • richer semantic document/table vocabulary.

A candidate may find a narrower solution without waiting for every item above.

Takeover checklist

When picking up one candidate:

  1. Re-read the current catalog, renderer, Editor, and canonical widget docs.
  2. Re-verify cited standards, APIs, provider policies, and accessibility guidance.
  3. Write the user problem and non-goals before syntax.
  4. Separate semantic state from renderer-local interaction and Editor-only pose.
  5. Compare at least web plus one non-web renderer model.
  6. Identify whether a maintained Pattern or opt-in catalog is sufficient.
  7. Record unresolved alternatives honestly.
  8. Create a dedicated catalogue document only when it improves clarity.
  9. Create an RFC only after a clean decision needs durable authority.
  10. Leave unrelated candidates open rather than deciding them by analogy.

Non-goals

  • implementation or implementation planning;
  • committing to every candidate;
  • preserving the working hypotheses of this study as doctrine;
  • treating popularity as sufficient reason for first-class syntax;
  • designing branded services as though provider policy does not exist;
  • silently promoting prototype behavior into specification; or
  • accepting unrelated widgets through one giant RFC.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions