Skip to content

Commit

Permalink
Merge pull request #942 from tszhong0411/pack-9-add-breadcrumb
Browse files Browse the repository at this point in the history
Add breadcrumb
  • Loading branch information
tszhong0411 authored Jan 9, 2025
2 parents 12baec6 + 1dc6492 commit 1d1844f
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/beige-peaches-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tszhong0411/eslint-config': patch
---

Turn off `jsx-a11y/no-aria-hidden-on-focusable`
5 changes: 5 additions & 0 deletions .changeset/wild-eagles-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tszhong0411/ui': patch
---

Add breadcrumb component
5 changes: 5 additions & 0 deletions apps/docs/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ const config: NextConfig = {
source: '/',
destination: '/introduction',
permanent: true
},
{
source: '/ui/components',
destination: '/ui/components/accordion',
permanent: true
}
]
}
Expand Down
37 changes: 37 additions & 0 deletions apps/docs/src/app/ui/components/breadcrumb.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
---

<ComponentPreview name='breadcrumb/breadcrumb' />

## Usage

```tsx
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator
} from '@tszhong0411/ui'
```

```tsx
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href='/'>Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href='/components'>Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
```
49 changes: 49 additions & 0 deletions apps/docs/src/components/demos/breadcrumb/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from '@tszhong0411/ui'

const BreadcrumbDemo = () => {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href='/'>Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger className='flex items-center gap-1'>
<BreadcrumbEllipsis className='size-4' />
<span className='sr-only'>Toggle menu</span>
</DropdownMenuTrigger>
<DropdownMenuContent align='start'>
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href='/ui/components'>Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}

export default BreadcrumbDemo
4 changes: 4 additions & 0 deletions apps/docs/src/config/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export const SIDEBAR_LINKS: SidebarLinks = [
href: '/ui/components/blur-image',
text: 'Blur Image'
},
{
href: '/ui/components/breadcrumb',
text: 'Breadcrumb'
},
{
href: '/ui/components/button',
text: 'Button'
Expand Down
3 changes: 1 addition & 2 deletions packages/eslint-config/src/configs/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ export const react = (options?: Options): Linter.Config[] => {
}
],
'jsx-a11y/lang': 'error',
'jsx-a11y/no-aria-hidden-on-focusable': 'error',
'jsx-a11y/prefer-tag-over-role': 'error'
'jsx-a11y/no-aria-hidden-on-focusable': 'error'
},
settings: {
'jsx-a11y': {
Expand Down
90 changes: 90 additions & 0 deletions packages/ui/src/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Slot } from '@radix-ui/react-slot'
import { cn } from '@tszhong0411/utils'
import { ChevronRightIcon, MoreHorizontalIcon } from 'lucide-react'

type BreadcrumbProps = {
separator?: React.ReactNode
} & React.ComponentProps<'nav'>

export const Breadcrumb = (props: BreadcrumbProps) => <nav aria-label='breadcrumb' {...props} />

type BreadcrumbListProps = React.ComponentProps<'ol'>

export const BreadcrumbList = (props: BreadcrumbListProps) => {
const { className, ...rest } = props

return (
<ol
className={cn(
'text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5',
className
)}
{...rest}
/>
)
}

type BreadcrumbItemProps = React.ComponentProps<'li'>

export const BreadcrumbItem = (props: BreadcrumbItemProps) => {
const { className, ...rest } = props

return <li className={cn('inline-flex items-center gap-1.5', className)} {...rest} />
}

type BreadcrumbLinkProps = {
asChild?: boolean
} & React.ComponentProps<'a'>

export const BreadcrumbLink = (props: BreadcrumbLinkProps) => {
const { asChild, className, ...rest } = props
const Comp = asChild ? Slot : 'a'

return <Comp className={cn('hover:text-foreground transition-colors', className)} {...rest} />
}

type BreadcrumbPageProps = React.ComponentProps<'span'>

export const BreadcrumbPage = (props: BreadcrumbPageProps) => {
const { className, ...rest } = props

return (
<span
role='link'
aria-disabled='true'
aria-current='page'
className={cn('text-foreground font-normal', className)}
{...rest}
/>
)
}

type BreadcrumbSeparatorProps = React.ComponentProps<'li'>

export const BreadcrumbSeparator = (props: BreadcrumbSeparatorProps) => {
const { children, className, ...rest } = props

return (
<li role='presentation' aria-hidden='true' className={cn(className)} {...rest}>
{children ?? <ChevronRightIcon className='size-3.5' />}
</li>
)
}

type BreadcrumbEllipsisProps = React.ComponentProps<'span'>

export const BreadcrumbEllipsis = (props: BreadcrumbEllipsisProps) => {
const { className, ...rest } = props

return (
<span
role='presentation'
aria-hidden='true'
className={cn('flex size-9 items-center justify-center', className)}
{...rest}
>
<MoreHorizontalIcon className='size-4' />
<span className='sr-only'>More</span>
</span>
)
}
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './avatar'
export * from './badge'
export * from './blur-fade'
export * from './blur-image'
export * from './breadcrumb'
export * from './button'
export * from './callout'
export * from './card'
Expand Down

0 comments on commit 1d1844f

Please sign in to comment.