Skip to content

feat: add Breadcrumbs, Separator and Avatar - #101

Merged
Agustin-Delgado merged 4 commits into
mainfrom
feat/breadcrumbs-separator-avatar
Sep 20, 2026
Merged

Agustin-Delgado merged 4 commits into
mainfrom
feat/breadcrumbs-separator-avatar

Conversation

@Agustin-Delgado

@Agustin-Delgado Agustin-Delgado commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Three primitives that complete the catalog, each with the accessibility of a native element, and the patterns on top of them that a real page needs.

Breadcrumbs — Root, List, Item, Link, Ellipsis, Separator.

  • Root is a <nav> landmark named "Breadcrumb" in the locale of LocaleProvider (six languages), or with your aria-label.
  • List is an <ol> with role="list" in writing: some browsers drop a list from the accessibility tree when its list-style is none, which every trail sets.
  • Link is an <a> with an href, and a <span> without one or with disabled: not a link, and not a tab stop, with no tabindex to manage. current gives aria-current="page".
  • Separator is aria-hidden, in the item after the link, thus the list holds pages only and the count a screen reader says is the count of pages. A slash without children.
  • maxItems folds the middle of a long trail. Ellipsis is a button named "Show N more pages" that stands for the folded pages; a press unfolds the trail and moves the focus to the first page that comes into view, because the button is gone. bind:expanded reads and folds it back.

Separator — one part. role="separator", aria-orientation="vertical" only for a vertical line (a separator is horizontal unless it says otherwise), and role="none" with decorative for a line the content already makes.

  • With a value it is a window splitter: a tab stop with aria-valuenow, aria-valuemin, aria-valuemax and aria-controls. The arrows of its axis move it by step, or largeStep with Shift; Home and End send it to the ends; Enter folds the pane to min and unfolds it to where it was; the pointer drags it along its parent, as a share of the parent's size. The horizontal arrows flip on a right-to-left page. data-dragging and data-focus-visible for the styles.

Avatar — Root, Image, Fallback, Group, Count.

  • Image loads the image off the screen and renders the <img> once it is there: a broken image icon never shows. A cached image is loaded at once, with no loading frame. A new src starts a new load. loading="lazy" starts the load when the avatar comes into view.
  • Fallback shows at once for a failure or a missing src, and after delay milliseconds while the image loads. It holds back on the server too. It takes the name of the image: a role="img" named with the alt, thus a failed image is not a nameless avatar and a screen reader does not hear the letters of the initials. An empty alt hides it.
  • Root has data-status and onStatusChange for loading, loaded and error.
  • Group is a role="group" named with aria-label, with a max: the avatars past it render nothing, thus they load no image. Count shows +N, and the screen reader hears "N more" in the locale.

Docs pages for the three, with demos, and changesets.

Verification

  • 41 browser tests and 5 SSR tests: the roles and the orientation of the separator; the splitter with the arrows of each axis, Shift, Home, End, Enter, the range, the flip in RTL, a drag along the parent, and the disabled state; the tab order and the locale of the breadcrumbs, the span for a disabled link, the fold with maxItems, the ellipsis and the focus after the press; the load, the failure, the missing source, the delay with fake timers, the change of source, the status callback, the name of the fallback, the lazy load on scroll, and the group with its count in two languages.
  • Full browser suite: 1856 tests green. Lint, STE check and both typechecks green.
  • The docs pages were checked live: the trail renders with role="list" and no markers, Tab skips the disabled link and lands on the current one with a ring, the fold shows "Home / … / Accessibility / Breadcrumbs" and Enter on the ellipsis unfolds it with the focus on "Docs"; the avatars show the image, the initials for a bad source and for no source, the group shows three of five with "+2" named "2 more"; the splitter follows a drag of a fifth of the row from 35 to 51, ArrowLeft and Home move it from the keyboard with the ring on.

@vercel

vercel Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
human-kit-ui-docs Ready Ready Preview Sep 20, 2026 2:50pm UTC

Breadcrumbs is a nav landmark named Breadcrumb in six languages, with an ordered list that keeps its role in writing, aria-current on the current page, aria-hidden separators in the items, and a span for a link without an address or with disabled.

Separator is a role=separator line, vertical on request, or role=none when decorative.

Avatar loads the image off the screen and renders the img once it is there, shows the fallback at once for a failure or a missing source, and holds it back for a delay while the image loads.
A failed image left a nameless avatar: the screen reader heard the letters of the initials. The fallback is a role=img named with the alt now, and hidden for an empty alt. The docs note that the image loads on mount, thus loading=lazy has no effect, and the breadcrumbs chevron turns for a right-to-left page.
Avatar: loading=lazy starts the load when the avatar comes into view; Avatar.Group is a named role=group with a max, and Avatar.Count says how many are past it, as +N on the screen and N more for the screen reader.

Breadcrumbs: maxItems folds the middle of a long trail behind Breadcrumbs.Ellipsis, a button named Show N more pages; a press unfolds the trail and moves the focus to the first page that comes into view.

Separator: with a value it is a window splitter, a tab stop with aria-valuenow that the arrow keys, Home, End, Enter and a pointer drag along the parent move, with the horizontal arrows flipped on a right-to-left page.
The prerender follows every link it finds. The demos linked to pages that do not exist, and the build of the docs failed with a 404 on /docs.
@Agustin-Delgado
Agustin-Delgado force-pushed the feat/breadcrumbs-separator-avatar branch from e7c1e28 to 5d76f71 Compare September 20, 2026 14:47
@Agustin-Delgado
Agustin-Delgado merged commit d9ab263 into main Sep 20, 2026
8 checks passed
@Agustin-Delgado
Agustin-Delgado deleted the feat/breadcrumbs-separator-avatar branch September 20, 2026 14:51

This branch was successfully deployed

1 active deployment
Preview — 5d76f71e Deployed Sep 20, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant