GPUI Box GitHub

Components / navigation

Tabs builder

A row of tabs. The strip publishes one Role::Tab node per tab.

A builder is RenderOnce. Construct and mount it in one expression.

use gpui_kit::navigation::Tabs;

Reviewed in tabs document-tabs.

Also drawn by motion-state motion-primitives deferred-drop reading-direction, which arranges components rather than reviewing them.

Construct
new(ident: impl Into<Ident>) -> Self
Options

Chain onto the value.

capsules() -> Self
tab(tab: TabItem) -> Self
tabs(tabs: impl IntoIterator<Item = TabItem>) -> Self
selected(id: impl Into<SharedString>) -> Self
on_select(handler: impl Fn(SharedString, &mut Window, &mut App) + 'static) -> Self
on_close(handler: impl Fn(SharedString, &mut Window, &mut App) + 'static) -> Self
overflow_after(count: usize) -> Self
scrolling() -> Self
overflow_menu(menu: Entity<Menu>) -> Self
reorderable(reorderable: bool) -> Self
accepts(predicate: impl Fn(&DragItem, &DropPosition) -> bool + 'static) -> Self
deferred_acceptance(controller: dnd::DeferredDrop, revision: u64) -> Self
on_reorder(handler: impl Fn(&DropIntent, &mut Window, &mut App) + 'static) -> Self
Example · tabs
fn tabs(_window: &mut Window, cx: &mut App) -> AnyElement {
    let theme = cx.theme().clone();
    stack(&theme)
        .w(px(520.0))
        .child(caption(
            &theme,
            "In-content tabs: raised control, quiet track, tabular count",
        ))
        .child(
            Tabs::new("scene.tabs.workspace")
                .tabs([
                    TabItem::new("overview", "Overview").icon(Icon::Widget),
                    TabItem::new("runs", "Runs").badge("12"),
                    TabItem::new("logs", "Logs"),
                    TabItem::new("billing", "Billing").disabled(true),
                ])
                .selected("runs")
                .on_select(|_, _, _| {}),
        )
        .child(caption(
            &theme,
            "places, not documents: Regular Liquid capsules, \
             with a translucent selected fill on the material",
        ))
        .child(
            Tabs::new("scene.tabs.capsules")
                .capsules()
                .control_size(ControlSize::Sm)
                .tabs([
                    TabItem::new("code", "Portal")
                        .icon(Icon::Terminal)
                        .tint(theme.colors.accent),
                    TabItem::new("game", "Harbour")
                        .icon(Icon::Play)
                        .tint(theme.colors.warning),
                    TabItem::new("design", "notes")
                        .icon(Icon::Pen)
                        .tint(theme.colors.info),
                ])
                .selected("code")
                .on_select(|_, _, _| {}),
        )
        // The body belongs to the caller: tabs render the strip only.
        .child(crate::foundation::text(
            &theme,
            TypeScale::Body,
            "Runs are rendered by the caller, not by the strip.",
        ))
        .child(caption(
            &theme,
            "the other answer to a strip with no room: it scrolls, and the \
             edge with more behind it fades",
        ))
        // Deliberately narrower than its tabs, because a strip that fits shows
        // nothing about what a strip that does not fit does.
        .child(
            div().w(px(300.0)).child(
                Tabs::new("scene.tabs.spaces")
                    .tabs((1..=9).map(|n| {
                        TabItem::new(format!("space-{n}"), format!("Workspace {n}"))
                            .icon(Icon::Widget)
                    }))
                    .selected("space-5")
                    .scrolling()
                    .on_select(|_, _, _| {}),
            ),
        )
        .into_any_element()
}

Source: crates/gpui-kit/src/navigation/tabs.rs