Skip to content

Breadcrumbs

The trail of pages to the one shown, HeroUI's on Kobalte's.

Solidtype_heroui.Breadcrumbs is Kobalte’s Breadcrumbs.Root, a <nav> named “Breadcrumbs” for a reader, around HeroUI’s list, each item an <li> holding Kobalte’s link and HeroUI’s chevron, with the classes HeroUI’s own breadcrumbsVariants gives. The last item is the page itself: its link is aria-current="page" and disabled, and no separator follows it.

breadcrumbs_usage.mlx
module Breadcrumbs = Solidtype_heroui.Breadcrumbs
let make () =
<Breadcrumbs>
<Breadcrumbs.Item href="#">"Home"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Products"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Electronics"</Breadcrumbs.Item>
<Breadcrumbs.Item>"Laptop"</Breadcrumbs.Item>
</Breadcrumbs>
<Breadcrumbs>
<Breadcrumbs.Item href="#">"Home"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Category"</Breadcrumbs.Item>
<Breadcrumbs.Item>"Current Page"</Breadcrumbs.Item>
</Breadcrumbs>
breadcrumbs_level2.mlx
module Breadcrumbs = Solidtype_heroui.Breadcrumbs
let make () =
<Breadcrumbs>
<Breadcrumbs.Item href="#">"Home"</Breadcrumbs.Item>
<Breadcrumbs.Item>"Current Page"</Breadcrumbs.Item>
</Breadcrumbs>
breadcrumbs_level3.mlx
module Breadcrumbs = Solidtype_heroui.Breadcrumbs
let make () =
<Breadcrumbs>
<Breadcrumbs.Item href="#">"Home"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Category"</Breadcrumbs.Item>
<Breadcrumbs.Item>"Current Page"</Breadcrumbs.Item>
</Breadcrumbs>
breadcrumbs_disabled.mlx
module Breadcrumbs = Solidtype_heroui.Breadcrumbs
let make () =
<Breadcrumbs is_disabled=true>
<Breadcrumbs.Item href="#">"Home"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Products"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Electronics"</Breadcrumbs.Item>
<Breadcrumbs.Item>"Laptop"</Breadcrumbs.Item>
</Breadcrumbs>

HeroUI gives the separator element its own class; a Solid component cannot add a class to an element already made, so the port draws the separator inside a <span> that takes HeroUI’s class, a 12-pixel square hidden from a reader. An icon fills it with size-full.

breadcrumbs_custom_separator.mlx
module Breadcrumbs = Solidtype_heroui.Breadcrumbs
let make () =
<Breadcrumbs
separator=(<svg
class_="size-full"
view_box="0 0 256 512"
xmlns="http://www.w3.org/2000/svg">
<path
d="M249.3 235.8c10.2 12.6 9.5 31.1-2.2 42.8l-128 128c-9.2 \
9.2-22.9 11.9-34.9 6.9S64.5 396.9 64.5 384l0-256c0-12.9 \
7.8-24.6 19.8-29.6s25.7-2.2 34.9 6.9l128 128 2.2 2.4z"
/>
</svg>)>
<Breadcrumbs.Item href="#">"Home"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Products"</Breadcrumbs.Item>
<Breadcrumbs.Item href="#">"Electronics"</Breadcrumbs.Item>
<Breadcrumbs.Item>"Laptop"</Breadcrumbs.Item>
</Breadcrumbs>

HeroUI’s Render Function example gives the trail and its items render, React’s way to swap the element it renders, which a Solid component has no need of.

class_ is added after HeroUI’s classes: the trail’s on its list, an item’s on its <li>.

breadcrumbs_tailwind.mlx
module Breadcrumbs = Solidtype_heroui.Breadcrumbs
let make () =
<Breadcrumbs class_="rounded-lg bg-default-soft px-3 py-2">
<Breadcrumbs.Item class_="text-muted hover:text-accent" href="#">
"Home"
</Breadcrumbs.Item>
<Breadcrumbs.Item class_="text-muted hover:text-accent" href="#">
"Products"
</Breadcrumbs.Item>
<Breadcrumbs.Item class_="font-medium text-foreground">
"Laptop"
</Breadcrumbs.Item>
</Breadcrumbs>

HeroUI’s classes are global, so a stylesheet restyles every one, as with HeroUI in React:

@layer components {
.breadcrumbs {
@apply gap-4 text-lg;
}
.breadcrumbs__link {
@apply font-semibold;
}
.breadcrumbs__separator {
@apply text-blue-500;
}
}
  • .breadcrumbs, .breadcrumbs__item, .breadcrumbs__link, .breadcrumbs__separator
  • Current: [data-current="true"] on the link and its item
  • Hover: :hover or [data-hovered="true"] on a link
  • Focus: [data-focus-visible="true"] on a link
  • Disabled: [aria-disabled="true"] on a link

React Aria knows the last item as it renders, from its collection. Solid makes an item before those after it, so each item joins its trail as it is made, and the trail draws them once all have, in the order they joined: the page is the last on the server too, so a prerendered page marks it. An item added later, by a For, is drawn after those already there, and becomes the page if it is last. Since the trail draws each item, a context given between the trail and an item does not reach the item’s children.

A disabled link, and the page itself, is Kobalte’s <a> with its href taken off, where React Aria’s keeps the href and refuses the click, and the page is a <span role="link">; both are aria-disabled="true". The trail is named on Kobalte’s <nav>, as the pattern for breadcrumbs asks, where React Aria names its <ol>. An item without an id tells on_action nothing.

Each prop beside the name HeroUI’s React component gives it.

React solidtype Type Default Description
separator separator element HeroUI’s chevron Drawn between items
isDisabled is_disabled bool false Whether every link is disabled
onAction on_action string -> unit Told the id of an item whose link is pressed
className class_ string Added after HeroUI’s classes
children children elements The items
React solidtype Type Default Description
id id string What on_action is told
href href string Where it leads; left out for the page itself
isDisabled is_disabled bool false Whether its link is disabled
className class_ string Added after HeroUI’s classes
children children elements Its text

Original HeroUI documentation: Breadcrumbs.

The same HeroUI Breadcrumbs twice, under the same props: in solidtype on the left, in React on the right. Below them, every attribute of the first link of each: a marked row is one they disagree on, and a dimmed row is a framework’s own, which no style reads.

on_action: nothing yet

solidtype — OCaml, on Solid and Kobalte
React — TypeScript, on React Aria
attributesolidtypeReact