diff --git a/docs/components/breadcrumb.md b/docs/components/breadcrumb.md
index f447213..1183868 100644
--- a/docs/components/breadcrumb.md
+++ b/docs/components/breadcrumb.md
@@ -16,9 +16,23 @@
}
`" />
+## 可访问性
+
+组件使用带有 `Breadcrumb` 名称的导航 landmark 和有序列表。最后一项默认表示当前页并设置 `aria-current="page"`,分隔符会从辅助技术中隐藏。
+
## API
-| 属性 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| items | 面包屑项 | `BreadcrumbItem[]` | - |
-| separator | 分隔符 | `string` | `'/'` |
+| 属性 | 说明 | 类型 | 默认值 |
+| --------- | -------- | ------------------ | ------ |
+| items | 面包屑项 | `BreadcrumbItem[]` | - |
+| separator | 分隔符 | `ReactNode` | `'/'` |
+
+## BreadcrumbItem
+
+| 属性 | 说明 | 类型 | 默认值 |
+| ------- | ------------ | ------------ | ----------------- |
+| key | 唯一标识 | `string` | - |
+| label | 面包屑内容 | `ReactNode` | - |
+| href | 链接地址 | `string` | - |
+| onClick | 点击回调 | `() => void` | - |
+| current | 标记为当前页 | `boolean` | 最后一项为 `true` |
diff --git a/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.test.tsx b/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.test.tsx
new file mode 100644
index 0000000..9a5d07a
--- /dev/null
+++ b/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.test.tsx
@@ -0,0 +1,70 @@
+import { render, screen } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { describe, expect, it, vi } from 'vitest'
+
+import { Breadcrumb } from './Breadcrumb'
+
+const items = [
+ { key: 'home', label: 'Home', href: '/' },
+ { key: 'library', label: 'Library', href: '/library' },
+ { key: 'current', label: 'Current page' },
+]
+
+describe('Breadcrumb', () => {
+ it('renders a labelled navigation landmark with ordered items', () => {
+ render()
+
+ expect(screen.getByRole('navigation', { name: 'Breadcrumb' })).toBeInTheDocument()
+ expect(screen.getByRole('list')).toBeInTheDocument()
+ expect(screen.getAllByRole('listitem')).toHaveLength(3)
+ })
+
+ it('marks the last item as the current page by default', () => {
+ render()
+
+ expect(screen.getByText('Current page')).toHaveAttribute('aria-current', 'page')
+ expect(screen.getByText('Current page').tagName).toBe('SPAN')
+ })
+
+ it('allows an explicit current item', () => {
+ render(
+ ,
+ )
+
+ expect(screen.getByRole('link', { name: 'Reports' })).toHaveAttribute('aria-current', 'page')
+ expect(screen.getByRole('link', { name: 'Detail' })).not.toHaveAttribute('aria-current')
+ })
+
+ it('hides separators from the accessibility tree', () => {
+ render()
+
+ const separators = screen.getAllByText('>')
+
+ expect(separators).toHaveLength(2)
+ expect(separators[0]).toHaveAttribute('aria-hidden', 'true')
+ })
+
+ it('keeps clickable non-link items interactive', async () => {
+ const user = userEvent.setup()
+ const onClick = vi.fn()
+
+ render(
+ ,
+ )
+
+ await user.click(screen.getByRole('button', { name: 'Open menu' }))
+
+ expect(onClick).toHaveBeenCalledTimes(1)
+ })
+})
diff --git a/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.tsx b/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.tsx
index 8ba78e4..4b925ef 100644
--- a/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.tsx
+++ b/packages/ui/src/components/navigation/Breadcrumb/Breadcrumb.tsx
@@ -6,6 +6,7 @@ export interface BreadcrumbItem {
label: ReactNode
href?: string
onClick?: () => void
+ current?: boolean
}
export interface BreadcrumbProps extends HTMLAttributes {
@@ -17,23 +18,48 @@ export const Breadcrumb = forwardRef(function Brea
{ className, items, separator = '/', ...props },
ref,
) {
+ const hasExplicitCurrent = items.some((item) => item.current)
+
return (
)