Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Navigation

Breadcrumbs

Show the path to the current resource.

Rust
use herogpui::components::breadcrumbs::{Breadcrumbs, Crumb};

Breadcrumbs on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Breadcrumbs, Crumb};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

let last_nav = self.demo_text_value("bc-nav");
let crumbs = || {
    vec![
        Crumb::new("Home").href("#"),
        Crumb::new("Components").href("#"),
        Crumb::new("Breadcrumbs"),
    ]
};

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        // `cx.listener` takes one event argument, and
        // `on_navigate` receives the index and the crumb
        // alongside the click, so the view state is reached
        // through the entity directly.
        Breadcrumbs::new(crumbs())
            .id("breadcrumbs")
            .full_width(true)
            .text_size(px(16.))
            .on_navigate({
                let view = cx.entity().downgrade();
                move |idx: &usize,
                      crumb: &Crumb,
                      _,
                      _,
                      cx: &mut gpui::App| {
                    let _ = view.update(cx, |this, cx| {
                        this.set_demo_text_value(
                            "bc-nav",
                            format!("{idx}: {}", crumb.label),
                        );
                        cx.notify();
                    });
                }
            })
            .into_any_element(),
        para(
            &format!(
                "The current page is \"Breadcrumbs\" -- inert, no tab stop. \
                                     Last navigation: {}",
                if last_nav.is_empty() {
                    "none yet".to_owned()
                } else {
                    last_nav
                }
            ),
            cx,
        ),
    ])

Also calls para (included when you copy).

Navigation Levels

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Breadcrumbs, Crumb};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Breadcrumbs::new(vec![Crumb::new("Home").href("#")])
            .id("breadcrumbs-level-1")
            .into_any_element(),
        Breadcrumbs::new(vec![
            Crumb::new("Home").href("#"),
            Crumb::new("Library"),
        ])
        .id("breadcrumbs-level-2")
        .into_any_element(),
        Breadcrumbs::new(vec![
            Crumb::new("Home").href("#"),
            Crumb::new("Library").href("#"),
            Crumb::new("Data"),
        ])
        .id("breadcrumbs-level-3")
        .into_any_element(),
    ])

Disabled State

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Breadcrumbs, Crumb};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Breadcrumbs::new(vec![
        Crumb::new("Home").href("#"),
        Crumb::new("Archive").href("#"),
        Crumb::new("2025"),
    ])
    .id("breadcrumbs-disabled")
    .is_disabled(true)
    .into_any_element()])

Custom Separator

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Breadcrumbs, Crumb};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let crumbs = || {
    vec![
        Crumb::new("Home").href("#"),
        Crumb::new("Components").href("#"),
        Crumb::new("Breadcrumbs"),
    ]
};

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Breadcrumbs::new(crumbs())
        .id("breadcrumbs-sep-custom")
        .separator_render(|_| {
            gpui::div()
                .text_size(px(12.))
                .child("→".to_owned())
                .into_any_element()
        })
        .into_any_element()])

Separators

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{BreadcrumbSeparator, Breadcrumbs, Crumb};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let crumbs = || {
    vec![
        Crumb::new("Home").href("#"),
        Crumb::new("Components").href("#"),
        Crumb::new("Breadcrumbs"),
    ]
};

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Breadcrumbs::new(crumbs())
            .id("breadcrumbs-sep-slash")
            .separator(BreadcrumbSeparator::Slash)
            .into_any_element(),
        Breadcrumbs::new(crumbs())
            .id("breadcrumbs-sep-chevron")
            .separator(BreadcrumbSeparator::Chevron)
            .into_any_element(),
        Breadcrumbs::new(crumbs())
            .id("breadcrumbs-sep-dash")
            .separator(BreadcrumbSeparator::Dash)
            .into_any_element(),
    ])

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

para
fn para(text: &str, cx: &App) -> gpui::AnyElement {
    let colors = cx.colors();
    gpui::div()
        .text_size(px(14.5))
        .line_height(px(24.))
        .text_color(colors.foreground)
        .max_w(px(720.))
        .child(text.to_owned())
        .into_any_element()
}

Anatomy

Rust types

Breadcrumbs

Breadcrumbs is assembled from these builders. The API reference lists each one.

API reference

Against HeroUI v3.2.6: 9 entries ported, 2 partial, 4 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Breadcrumbs builders
BuilderValuesDefaultDescription
separator_render(closure) + separator(BreadcrumbSeparator)AnyElementchevron-right iconCustom separator between breadcrumb items; separator_render is its Rust port — a closure rebuilt for every non-last crumb and painted inside the 12px separator slot — while separator(BreadcrumbSeparator) covers the built-in presets. The closure overrides the preset.
is_disabled(bool)true | falsefalseWhether all breadcrumb links are disabled; disabled crumbs leave the tab order and fade, but the current page keeps opacity-100 as v3's [data-current] rule does.
new(items)PartialAnyElement—The breadcrumb items; takes a Vec<Crumb> instead of composed Breadcrumbs.Item elements.
href(href)string—The URL to link to (omit for the current page); a href crumb opens it through the OS URL handler, with or without an on_navigate callback.
new(label)PartialAnyElement | render closure—Item content or render function; takes a label string per Crumb, so composed children are not supported.
Not ported4 HeroUI entries not ported
Breadcrumbs builders not ported
HeroUI v3Why it is not ported
Breadcrumbs.className
Breadcrumbs.renderOverrides the default element with a custom render function; there is no element to override.
Breadcrumbs.Item.classNameFor the item.
Breadcrumbs.Item.renderOverrides the default element with a custom render function; there is no element to override.

Parts

Breadcrumbs parts
PartDescription
BreadcrumbsRoot container: one flex line, items centre, no wrap.
BreadcrumbsPer-crumb wrapper that hugs its content and holds the link and the trailing separator; draws it from a Crumb, so it is not a composed element.

States

Breadcrumbs states
StateBuilderDescription
Currentis_last -> colors.linkThe last crumb is the current page: it renders in the link token, exposes AccessKit aria-current=page, is not a tab stop, answers no press even with an href, and never takes the disabled fade.
Hoverhover(|s| s.underline()) when navigableLink crumbs underline on hover; the colour stays muted.
Focustab_stop_handle per link crumbEvery link crumb is a tab stop ( link semantics) and draws the focus-visible status ring when keyboard-focused; mouse focus leaves the ring off. Enter and Space activate the focused crumb through gpui's focused-click, so no second key handler is bound. The current page and disabled crumbs are not tab stops at all.
Disabledis_disabled -> disabled_opacity when !is_lastIsDisabled disables every link: none takes a press, none stays a tab stop, and all of them fade — except the current page, which [data-current] holds at opacity-100.