Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Other Components

Beyond standard HTML elements and input widgets, vgui provides several specialized components that are accessible as lowercase tags in view!.

<progress> — Progress Bar

Renders a horizontal progress bar. The fill width is determined by value / max:

#![allow(unused)]
fn main() {
view! {
    <progress value={0.5f64} max={1.0f64} />
}
}

Attributes

AttributeTypeDefaultDescription
valuef640.0Current progress value.
maxf641.0Maximum value.

The bar is rendered as a gpui::Div with a filled portion proportional to value / max. Standard styling attributes (class, style) can be applied to customize appearance.

<meter> — Meter Gauge

Renders a horizontal gauge. Fill width is value between min and max. When low, high, and optimum are all omitted the fill is the same blue as <progress>. Otherwise values inside [low.unwrap_or(min), high.unwrap_or(max)] are green and values outside that range are red.

#![allow(unused)]
fn main() {
view! {
    <meter value={0.3f64} min={0f64} max={1f64} low={0.2f64} high={0.8f64} optimum={0.5f64} />
}
}

Attributes

AttributeTypeDefaultDescription
valuef640.0Current value.
minf640.0Minimum of the range.
maxf641.0Maximum of the range.
lowOption<f64>noneLower bound of the “good” range.
highOption<f64>noneUpper bound of the “good” range.
optimumOption<f64>nonePresence (with low/high) selects green/red coloring.

<details> — Collapsible Container

Renders a collapsible container with a summary header and hidden content. The open attribute controls content visibility; the summary is always visible.

#![allow(unused)]
fn main() {
view! {
    <details open={open.get()}>
        <summary on:click={click(move |cx| set_open.update(cx, |v| *v = !*v))}>
            {"Click to toggle"}
        </summary>
        <div>{"Hidden content"}</div>
    </details>
}
}

Attributes

AttributeTypeDefaultDescription
openboolfalseWhether content is visible.

Children

<details> children are split: the first child (typically <summary>) is the always-visible header, and the remaining children form the collapsible content. <summary> is rendered as a gpui::div() with cursor_pointer().

Note: In vgui v1, open is a prop, not internal state — you must manage it with a signal and toggle it in the <summary> click handler, as shown above.

<dialog> — Modal Dialog

Renders a modal dialog that floats above all non-deferred content via a portal (deferred paint layer) at z-index priority 100. When open is false, renders a hidden element with no layout impact.

#![allow(unused)]
fn main() {
view! {
    <button on:click={click(move |cx| set_show.set(cx, true))}>
        {"Open Dialog"}
    </button>
    <dialog open={show_dialog.get()} on:close={move |cx| set_show.set(cx, false)}>
        <div class="bg-white p-4 rounded text-black">
            <p>{"Dialog content — click outside or press Escape to close."}</p>
            <button on:click={click(move |cx| set_show.set(cx, false))}>
                {"Close"}
            </button>
        </div>
    </dialog>
}
}

Attributes

AttributeTypeDefaultDescription
openboolfalseWhether the dialog is visible.
on:closeFn(&mut App)no-opCalled when the dialog is dismissed.

Dismissal

The dialog can be dismissed three ways:

  • Click-outside: Clicking the backdrop (outside the content) fires on:close. The backdrop occludes mouse events, so elements behind the dialog never receive them.
  • Escape key: Pressing Escape fires on:close — but only when focus is within the dialog. This is a gpui constraint: key events dispatch only along the focus path (root → focused node). Clicking into the dialog moves focus there, so Escape works in the natural case. If focus remains on background content, Escape will not fire.
  • Explicit close: Call your on:close handler from a button inside the dialog (as shown above).

The on:close closure takes Fn(&mut App) directly — no click() wrapper needed, unlike on:click. This is because on:close is a vgui abstraction, not a gpui event.

Focus Management

The dialog implements two accessibility features:

  • Focus trap: Tab and Shift+Tab cycle within the dialog content. Focus cannot escape to background elements.
  • Focus restore: When the dialog opens, the previously focused element is saved. When the dialog closes (via Escape, click-outside, or on:close), focus is restored to that element.

Focus moves to the dialog content when it opens. The trap and restore are automatic — no extra attributes or callbacks are needed.

Portal rendering

The dialog paints on a deferred layer (priority 100), so it floats above all non-deferred content regardless of sibling paint order. It stays centered even while the page scrolls — the portal layer is independent of scroll content.

<portal> — Portal Floating Layer

Renders content on a floating layer drawn after all non-deferred ancestors. This is the base portal primitive — dialog and floating wrap it with higher-level behavior.

#![allow(unused)]
fn main() {
view! {
    <portal priority={200}>
        <div class="bg-white p-2 rounded">
            {"Rendered on top of everything"}
        </div>
    </portal>
}
}

Attributes

AttributeTypeDefaultDescription
priorityusize0Stacking order; higher values paint on top of lower ones.

Use <portal> when you need custom stacking control — for example, rendering a dialog above another dialog (priority 100) by wrapping content at priority 200.

<floating> — Positioned Floating Element

Renders content at a window-coordinate point with automatic overflow avoidance. If the content would extend past the window edge, it snaps inside with an 8px margin. Paints on a deferred layer at priority 50 (below dialog’s 100).

#![allow(unused)]
fn main() {
view! {
    <floating position={gpui::point(gpui::px(100.), gpui::px(200.))}>
        <div class="bg-white p-2 rounded"
             on:mouse_down_out={move |_, _, cx| /* dismiss */}>
            {"Floating tooltip or popover"}
        </div>
    </floating>
}
}

Attributes

AttributeTypeDefaultDescription
positionPoint<Pixels>Window-coordinate position (required).

<floating> has no built-in dismissal. Add on:mouse_down_out to the content for click-outside behavior, as shown above.