Rewrote all the docs - more noob friendly now.

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-05 23:55:26 +05:00
parent e483bf73e7
commit f6ae86617c
35 changed files with 2159 additions and 2341 deletions
+64 -70
View File
@@ -1,66 +1,56 @@
# Breadcrumb
A navigation trail showing the user's location in the app hierarchy. Items are separated by chevron icons. The last item is always rendered as plain text (current page); earlier items are links.
A "you are here" trail — a row of links showing how the user got to the current page. Like breadcrumbs leading back through a forest.
---
## HTML structure
```
nav[aria-label=Breadcrumb]
ol.flex.flex-wrap.items-center.gap-1.5.text-sm.text-muted-foreground
li.inline-flex.items-center.gap-1.5 ← one per item
a | span ← a = link, span = non-linked or current
span[role=presentation, aria-hidden] ← chevron separator (omitted after last item)
svg (3.5×3.5, chevron-right)
```
---
## CSS mechanics
| Class | Effect |
|---|---|
| `text-muted-foreground` | Dimmed color for all non-current items |
| `font-normal text-foreground` | Full-opacity color applied to the last (current) item |
| `hover:text-foreground transition-colors` | Link hover state |
| `flex-wrap` | Items wrap on narrow screens |
---
## Constructor signature
```csharp
public Breadcrumb(IEnumerable<(string Label, string Href)> items)
```
| Parameter | Description |
|---|---|
| `items` | Ordered list of `(Label, Href)` tuples. The last item is always the current page. |
Rules:
- The **last** item is always non-linked and rendered in full `text-foreground` color, regardless of its `Href` value.
- Any **non-last** item with an empty `Href` is rendered as a plain `<span>` rather than a link.
---
## Usage examples
### Simple three-level breadcrumb
## Quick example
```csharp
new Breadcrumb(new[]
{
("Home", "/"),
("Settings", "/settings"),
("Profile", ""), // current page — href is ignored for the last item
("Profile", ""), // current page
})
```
### Dynamic breadcrumb from a data path
The last item is always the current page. Its link is ignored — the component automatically renders it as plain text with full colour instead of a dimmed link.
---
## All the options
```csharp
public Breadcrumb(IEnumerable<(string Label, string Href)> items)
```
| Parameter | What it does |
|---|---|
| `items` | An ordered list of `(Label, Href)` pairs from root to current page. |
Two rules:
- The **last item** is always rendered as plain text (current page). Its `Href` is ignored.
- Any **non-last item** with an empty `Href` renders as a plain `<span>` — useful for non-navigable category labels.
---
## Real-world examples
### Three-level app navigation
```csharp
new Breadcrumb(new[]
{
("Home", "/"),
("Reports", "/reports"),
("Monthly", ""), // current — href not needed
})
```
### Built dynamically from a category tree
```csharp
// Build items from a category tree
var crumbs = categoryPath
.Select((cat, i) => (cat.Name, i < categoryPath.Count - 1 ? cat.Url : ""))
.ToArray();
@@ -68,41 +58,45 @@ var crumbs = categoryPath
new Breadcrumb(crumbs)
```
### Embedded in a page
### Inside a page
```html
<!-- MyPage.htmx -->
<div class="mb-6">
$$Breadcrumb$$
</div>
<!-- ArticlePage.htmx -->
<div class="mb-6">$$Breadcrumb$$</div>
<h1 class="text-3xl font-bold">$$ArticleTitle$$</h1>
```
```csharp
// MyPage.htmx.cs
public IHtmxComponent Breadcrumb { get; }
public MyPage()
// ArticlePage.htmx.cs
public sealed class ArticlePage : ArticlePageBase
{
Breadcrumb = new Breadcrumb(new[]
{
("Home", "/"),
("Reports", "/reports"),
("Monthly", ""),
});
}
private readonly IHtmxComponent _breadcrumb;
private readonly byte[] _titleData;
protected override void RenderBreadcrumb(HtmxRenderContext ctx)
=> Breadcrumb.Render(ctx.Next());
public ArticlePage(string articleTitle, string categoryName, string categoryUrl)
{
_titleData = articleTitle.ToUtf8Bytes();
_breadcrumb = new Breadcrumb(new[]
{
("Home", "/"),
(categoryName, categoryUrl),
(articleTitle, ""),
});
}
protected override void RenderBreadcrumb(HtmxRenderContext ctx)
=> _breadcrumb.Render(ctx.Next());
protected override void RenderArticleTitle(HtmxRenderContext ctx)
=> ctx.Writer.WriteUtf8(_titleData);
}
```
---
## Tips and tricks
## How it works
- Always make the last item the current page — its href is ignored anyway, and it gets the visual "active" treatment automatically.
- If you have a non-navigable segment (e.g. a category separator with no URL), pass an empty `Href` for that item and it will render as a plain span.
- For very deep hierarchies, consider truncating the middle items and replacing them with a `…` span — build the items list conditionally before passing to the constructor.
- The chevron separator is `aria-hidden` so screen readers announce only the labels in sequence.
Each item renders as a `<li>` inside an `<ol>` inside a `<nav aria-label="Breadcrumb">`. All items except the last are rendered as `<a>` links; the last is a `<span>`. Between items the component inserts a small SVG chevron that is marked `aria-hidden` so screen readers skip it and only announce the text labels.
---