Skip to content

Components

MeowLynxSea edited this page Jun 13, 2026 · 15 revisions

Components

v0.3: Components live in yororen-ui-core/src/headless/ as factory functions returning XxxProps builders. Every factory has a .render(cx) method that resolves through cx.renderer_arc::<markers::Xxx, dyn XxxRenderer>() and applies the registered TokenXxxRenderer for the default look.

The flat top-level import path yororen_ui::headless::button is sugar: headless/mod.rs does pub use button::button; so callers can write use yororen_ui::headless::button; and get the factory function directly. The fully-qualified form yororen_ui::headless::button::button is the canonical, preferred path — use it when there is any naming-collision risk.

There is no yororen_ui::component module in v0.3. The v0.2-era flat yororen_ui::component::button import path is gone; use yororen_ui::headless::button (or the preferred fully-qualified path) instead.

This page indexes every component shipped under yororen_ui::headless. Each entry links to its dedicated wiki page where one exists; entries without a dedicated page are marked (no dedicated page yet).

Two import shapes

use yororen_ui::headless::button;          // flat re-export (sugar)
use yororen_ui::headless::button::button;  // fully-qualified (preferred)
use yororen_ui::headless::virtual_list::{
    virtual_list, uniform_virtual_list, VirtualListController,
    UniformVirtualListController,
};
use yororen_ui::headless::markers;        // marker types for cx.renderer_arc::<...>()

The two shapes are equivalent — headless/mod.rs does pub use button::button; so callers can choose either.

The factory + .render(cx) pattern

Every headless factory returns a XxxProps builder. Two consumption patterns:

use gpui::div;
use yororen_ui::headless::button::button;

// Pattern A — pure headless. The caller composes the visuals.
div().bg(red).rounded(8).apply(button("save", cx).on_click(...)).child("Save")

// Pattern B — default-rendered look from the installed theme + TokenXxxRenderer.
button("save", cx).on_click(...).render(cx).child("Save")

.render(cx) is a no-op if no TokenXxxRenderer is registered for the component's marker — the caller falls back to apply(div) or .into_element().

State ownership

For composites that own interaction state (Modal, Select, Popover, DropdownMenu, Tooltip, ComboBox, Listbox, Menu, Tree, Table, VirtualList, Form), the factory returns a props builder; the actual state entity lives elsewhere and is wired through:

  • cx.entity().clone() — the v0.3 idiom for handing a callback a handle to your own Entity<MyState>. Use this for on_change / on_submit / on_pick / on_close closures so the component can write into your app state.
  • cx.new(|_| XxxState::new()) — the factory for the component's own state entity when the headless primitive owns internal state (rare; most are props-only).

The component is the single source of truth for interaction state (caret, selection, scroll, animation, open/closed). Your app is the single source of truth for business state (text, validation, submit status). on_change is the only bridge. See State + Inputs for the full pattern.

Picking the right component

  • Select vs ComboBox: use Select for small option sets (< ~20); use ComboBox for large sets that benefit from search.
  • Checkbox vs Switch: both are boolean toggles; use Switch for settings-style toggles.
  • Button vs ClickableSurface: use Button for semantic actions; use ClickableSurface to make an existing layout clickable.
  • Popover vs DropdownMenu: Popover is just an anchored content surface; DropdownMenu adds menu-item navigation and keyboard handling.

The component list (one entry per headless/*.rs)

The list below mirrors the actual files under crates/yororen-ui-core/src/headless/ exactly (with the three internal-helper files text_input_core.rs, text_input_element.rs, text_area_element.rs excluded — they have no top-level factory functions and are not user-facing components).

Foundation / primitives

Action surfaces

Inputs

List / data

  • Disclosure
  • ListItem
  • Listbox — headless factory listbox(id, cx) lives in headless/listbox.rs; (no dedicated page yet).
  • Menu — headless factory menu(cx) lives in headless/menu.rs; (no dedicated page yet).
  • Tree
  • TreeItem
  • Table — headless factory table(cx) lives in headless/table.rs; (no dedicated page yet).
  • VirtualList — headless factories virtual_list, uniform_virtual_list, plus controllers VirtualListController and UniformVirtualListController, live in headless/virtual_list.rs. Documented under Widget-VirtualList (it is also classified as a widget because it owns a state entity).

Overlays / surfaces

Progress / status

  • Progress — headless factory progress(value, cx) lives in headless/progress.rs. The wiki pages ProgressBar and ProgressCircle cover its visual forms (the renderer maps the same headless props to either shape).
  • Skeleton

Toast / NotificationHost — these do not exist as public headless APIs in v0.3 — they are planned. Do NOT import yororen_ui::widget::TitleBar from anywhere; the workspace has no yororen_ui::widget module. There is also no headless/toast.rs module in v0.3. The visual notification_host() function exists at yororen-ui-default-renderer/src/notification_host.rs:18 but is not a public API — the file is not declared pub mod in the default-renderer's lib.rs (see crates/yororen-ui-default-renderer/src/lib.rs:27-29, which exposes only animation, renderers, themes), and it imports use crate::component::{Icon, IconName, label, toast}; — a crate::component module that does not exist in v0.3. The gallery confirms the file is dead code in crates/yororen-ui-demos/gallery_demo/src/notifications_host.rs:9-16: "The file is dead code and is not part of the public API." Neither yororen_ui::notification::notification_host (no such path) nor yororen_ui::renderer::notification_host (the alias is reachable via pub use yororen_ui_default_renderer as renderer; in crates/yororen-ui/src/lib.rs:27, but the source file is not a pub mod of that crate) compiles in v0.3. The headless state machine IS public: yororen_ui::notification::Notification, yororen_ui::notification::NotificationCenter, yororen_ui::notification::NotificationId, yororen_ui::notification::DismissStrategy, yororen_ui::notification::ToastKind — all reachable at yororen_ui::notification::* (the meta-crate re-exports the core notification module via pub use yororen_ui_core::{..., notification, ...} in crates/yororen-ui/src/lib.rs:26). The visual host itself must be implemented in your app — see Widgets for the v0.3 pattern and Guide-Notification for the full recipe.

The legacy wiki pages Component-Toast and Component-Helpers document v0.2 APIs and are not updated for v0.3; treat them as historical until a v0.3 port lands.

One-time startup calls

Some composites need a one-time registration at app startup. The current call is:

yororen_ui::headless::text_input::init(cx);

It binds the 14-action keymap against the "UITextInput" key context for the seven text inputs. It is idempotent (a OnceLock inside the crate) — calling it more than once is safe. The renderer wires the actions; this call only registers the keymap. The default-renderer's install call still does everything else you need (theme + the 54 default renderer impls + notification host auto-bind).

Note on "38": the default-renderer and brutalism-renderer crate-level docs and the brutalism register_brutal_renderers comment both self-describe as "38" — that number is a stale comment from the v0.2 design phase. The actual source-of-truth count is 54 markers, one per headless component, listed in crates/yororen-ui-core/src/renderer/markers.rs (see Design-Three-Layer-Architecture).

Marker types

cx.renderer_arc::<markers::Xxx, dyn XxxRenderer>() is the lookup key for the per-component renderer. markers is re-exported from yororen-ui-core::renderer::markers at yororen_ui::headless::markers. Each component has its own unit struct marker; the variant_showcase demo reads the markers directly to exercise the registry.

What is not in yororen_ui::headless

  • Widgets (TitleBar, NotificationHost, …) — see Widgets.
  • NotificationCenter — the data + state machine lives in yororen_ui::notification::center (re-exported from yororen-ui-core::notification via crates/yororen-ui/src/lib.rs:26). Reachable as yororen_ui::notification::Notification, yororen_ui::notification::NotificationCenter, yororen_ui::notification::NotificationId, yororen_ui::notification::DismissStrategy, yororen_ui::notification::ToastKind. The visual notification_host() builder does not have a public path in v0.3 — the function exists in yororen-ui-default-renderer/src/notification_host.rs:18 but the file is not pub mod'd in crates/yororen-ui-default-renderer/src/lib.rs and the file's use crate::component::{...} references a non-existent module. Apps must implement their own host (see the gallery's crates/yororen-ui-demos/gallery_demo/src/notifications_host.rs).
  • Theme / i18n / rtl / a11y / animation / assets — sibling top-level modules in yororen_ui. They are not components; they cross-cut every component.
  • The yororen_ui::component module — gone in v0.3. Migrate yororen_ui::component::Xyororen_ui::headless::X (or the preferred yororen_ui::headless::X::X).

Clone this wiki locally