Skip to content

feat: add Breadcrumb component#21

Merged
Igor Salviatto (igorsalbr) merged 5 commits intomainfrom
feat/breadcrumb-component
Mar 30, 2026
Merged

feat: add Breadcrumb component#21
Igor Salviatto (igorsalbr) merged 5 commits intomainfrom
feat/breadcrumb-component

Conversation

@igorsalbr
Copy link
Copy Markdown
Contributor

@igorsalbr Igor Salviatto (igorsalbr) commented Mar 30, 2026

Summary

  • New Breadcrumb component accepting a variable-length items array with label, optional href or onClick
  • Framework-agnostic: supports custom link rendering via renderLink prop (e.g. Next.js Link)
  • Semantic HTML (nav > ol > li), aria-current="page" on last item, ChevronRightIcon separators
  • 12 unit tests covering: single/multiple items, links, buttons, renderLink, accessibility, className, many items
Screenshot 2026-03-30 at 17 17 42

Test plan

  • All 12 Breadcrumb tests passing
  • Full suite (1844 tests) passing — no regressions
  • Biome lint/format clean

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a Breadcrumb navigation component with single/multi-item support, semantic HTML (nav/ol/li), separators, accessible attributes (aria-label, aria-current), prop forwarding, custom root class, and pluggable link rendering.
  • Tests

    • New test suite covering rendering, interaction, accessibility, and large-list behavior.
  • Documentation

    • Added Storybook examples demonstrating various breadcrumb configurations.
  • Style

    • Minor SVG attribute tweak for consistent icon rendering.

Accepts a variable-length array of items with label, optional href
or onClick. Supports custom link rendering via renderLink prop for
framework-specific routing (e.g. Next.js Link). Uses semantic HTML
with nav > ol > li, aria-current="page" on the last item, and
ChevronRightIcon separators.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

I pity the fool who misses this: adds a client-side React Breadcrumb component, tests, Storybook stories, and barrel exports — renders nav[aria-label="Breadcrumb"] with ol/li, items as links/buttons/spans, separators, renderLink, className, and nav prop forwarding.

Changes

Cohort / File(s) Summary
Breadcrumb Component
src/components/ui/Breadcrumb/Breadcrumb.tsx
New Breadcrumb component and exported types (BreadcrumbItem, BreadcrumbProps). Renders <nav aria-label="Breadcrumb"><ol><li>; non-last items render <a>/custom renderLink or <button>, final item renders <span aria-current="page">. Separators (ChevronRightIcon), cn and data-slot markers used.
Tests
src/components/ui/Breadcrumb/Breadcrumb.test.tsx
New test suite validating single vs multiple items, aria-current semantics, separator aria-hidden and counts, link/button/span rendering rules, renderLink behavior, click handler invocation, semantic structure (nav/ol/li), className and prop forwarding.
Stories
src/components/ui/Breadcrumb/Breadcrumb.stories.tsx
Added Storybook stories: Default, TwoItems, WithOnClick, SingleItem, and ManyItems demonstrating various item configurations (href, onClick, many items).
Barrel Exports
src/components/ui/Breadcrumb/index.ts, src/components/ui/index.ts
Added re-exports for Breadcrumb and types BreadcrumbItem, BreadcrumbProps to public UI barrel files.
Icon tweak & exports
src/components/icons/SignContractIcon.tsx, src/components/icons/index.ts
Moved fill="currentColor" onto a <g> in SignContractIcon; reordered SignContractIcon export in icons barrel (no API or behavior change).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I pity the fool who loses the way,
Breadcrumbs gleam with chevrons in play,
Nav, ol, li — tidy and true,
Links and buttons guide you through,
Follow the trail — you’ll find your view.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add Breadcrumb component' clearly and concisely describes the main change—introducing a new Breadcrumb UI component to the codebase.
Description check ✅ Passed The PR description covers the main change (Breadcrumb component) and includes test results, but omits the Storybook section from the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/breadcrumb-component

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/components/ui/Breadcrumb/Breadcrumb.test.tsx (1)

93-128: Props and many items tested right - but Mr. T notices somethin' missing!

These tests are good, fool! But Mr. T doesn't see a test for an empty items array. Might wanna add one to make sure the component handles that edge case gracefully.

🧪 Suggested test for empty items
it("renders nothing for empty items array", () => {
  render(<Breadcrumb items={[]} />);
  const list = document.querySelector('[data-slot="breadcrumb-list"]');
  expect(list?.querySelectorAll("li")).toHaveLength(0);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/Breadcrumb/Breadcrumb.test.tsx` around lines 93 - 128, Add
a new test in Breadcrumb.test.tsx that verifies Breadcrumb handles an empty
items array: render <Breadcrumb items={[]} />, select the element with
data-slot="breadcrumb-list" (or the list slot used by the component) and assert
it contains zero <li> children; name the test something like "renders nothing
for empty items array" and place it alongside the other it(...) blocks so the
Breadcrumb component's empty-array edge case is covered.
src/components/ui/Breadcrumb/Breadcrumb.tsx (1)

55-74: Listen here, fool! Mr. T sees an inconsistency!

When using the native <a> tag, you render item.label directly and apply data-slot="breadcrumb-link" to the anchor. But when using renderLink, you pass a <span> wrapper as children and the custom link element won't have the data-slot attribute.

This creates inconsistent markup between the two code paths, which could affect styling hooks and testing.

♻️ Proposed fix to align both code paths
             if (renderLink) {
-              return renderLink(item.href, linkContent);
+              return (
+                <span data-slot="breadcrumb-link">
+                  {renderLink(item.href, linkContent)}
+                </span>
+              );
             }

Or alternatively, pass the label directly to renderLink for consistency:

-            const linkContent = (
-              <span className="text-gray-500 hover:text-gray-700">
-                {item.label}
-              </span>
-            );
-
             if (renderLink) {
-              return renderLink(item.href, linkContent);
+              return renderLink(item.href, item.label);
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/Breadcrumb/Breadcrumb.tsx` around lines 55 - 74, The
breadcrumb renders inconsistent markup: the native <a> uses
data-slot="breadcrumb-link" and renders item.label directly, while the
renderLink path wraps the label in a <span> without the data-slot; update the
Breadcrumb component so both paths produce the same markup by either passing the
label (item.label) directly to renderLink or passing the same anchor-like
children with data-slot="breadcrumb-link" to renderLink; locate this logic in
the render block that checks if (!isLast && item.href) and adjust the call to
renderLink(item.href, ...) to include the data-slot attribute (or plain label)
so styling/testing hooks match the native <a> output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/ui/Breadcrumb/Breadcrumb.tsx`:
- Around line 88-93: The current JSX in Breadcrumb (the map rendering each
BreadcrumbItem using key={item.label}) can produce duplicate keys; update the
rendering in Breadcrumb.tsx to use a stable unique key instead — either use the
map index (e.g., key={index}) if items are static, or add and use an explicit id
property on the BreadcrumbItem type (e.g., item.id) and set key={item.id};
update the BreadcrumbItem type/interface if you choose id so callers supply it,
and replace key={item.label} in the component accordingly.

---

Nitpick comments:
In `@src/components/ui/Breadcrumb/Breadcrumb.test.tsx`:
- Around line 93-128: Add a new test in Breadcrumb.test.tsx that verifies
Breadcrumb handles an empty items array: render <Breadcrumb items={[]} />,
select the element with data-slot="breadcrumb-list" (or the list slot used by
the component) and assert it contains zero <li> children; name the test
something like "renders nothing for empty items array" and place it alongside
the other it(...) blocks so the Breadcrumb component's empty-array edge case is
covered.

In `@src/components/ui/Breadcrumb/Breadcrumb.tsx`:
- Around line 55-74: The breadcrumb renders inconsistent markup: the native <a>
uses data-slot="breadcrumb-link" and renders item.label directly, while the
renderLink path wraps the label in a <span> without the data-slot; update the
Breadcrumb component so both paths produce the same markup by either passing the
label (item.label) directly to renderLink or passing the same anchor-like
children with data-slot="breadcrumb-link" to renderLink; locate this logic in
the render block that checks if (!isLast && item.href) and adjust the call to
renderLink(item.href, ...) to include the data-slot attribute (or plain label)
so styling/testing hooks match the native <a> output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8cfa0f61-0c8a-4885-a49a-2877f15c82c7

📥 Commits

Reviewing files that changed from the base of the PR and between d36a9ca and 5f5f90f.

📒 Files selected for processing (4)
  • src/components/ui/Breadcrumb/Breadcrumb.test.tsx
  • src/components/ui/Breadcrumb/Breadcrumb.tsx
  • src/components/ui/Breadcrumb/index.ts
  • src/components/ui/index.ts

…sues

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sort JSX props in SignContractIcon and fix export order in icons/index.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@igorsalbr Igor Salviatto (igorsalbr) merged commit 9ea77c2 into main Mar 30, 2026
2 checks passed
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.

2 participants