Breadcrumbs
Show the path to the current resource.
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.
Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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).
An element expression with window: &mut Window and cx: &mut App in scope.
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()])An element expression with window: &mut Window and cx: &mut App in scope.
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()])An element expression with window: &mut Window and cx: &mut App in scope.
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.
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 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
| Builder | Values | Default | Description |
|---|---|---|---|
separator_render( | AnyElement | chevron-right icon | Custom 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( | true | | false | Whether 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(Partial | AnyElement | — | The breadcrumb items; takes a Vec<Crumb> instead of composed Breadcrumbs.Item elements. |
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(Partial | AnyElement | | — | Item content or render function; takes a label string per Crumb, so composed children are not supported. |
Not ported4 HeroUI entries not ported
| HeroUI v3 | Why it is not ported |
|---|---|
Breadcrumbs.className | |
Breadcrumbs.render | Overrides the default element with a custom render function; there is no element to override. |
Breadcrumbs.Item.className | For the item. |
Breadcrumbs.Item.render | Overrides the default element with a custom render function; there is no element to override. |
Parts
| Part | Description |
|---|---|
Breadcrumbs | Root container: one flex line, items centre, no wrap. |
Breadcrumbs | Per-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
| State | Builder | Description |
|---|---|---|
Current | is_last -> colors.link | The 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. |
Hover | hover(|s| s.underline()) when navigable | Link crumbs underline on hover; the colour stays muted. |
Focus | tab_stop_handle per link crumb | Every 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. |
Disabled | is_disabled -> disabled_opacity when !is_last | IsDisabled 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. |