|
| 1 | +import React, { ComponentProps, ElementRef, forwardRef } from 'react' |
| 2 | +import { CSSProps, styled, VariantProps } from '../../stitches.config' |
| 3 | +import { Link, LinkProps } from '../Link' |
| 4 | + |
| 5 | +const BREADCRUMB_TAG = 'nav' |
| 6 | +const BREADCRUMB_LIST_TAG = 'ol' |
| 7 | +const CRUMB_TAG = 'li' |
| 8 | + |
| 9 | +/** |
| 10 | + * StyledBreadcrumbs base component |
| 11 | + */ |
| 12 | +const StyledBreadcrumbs = styled(BREADCRUMB_TAG, {}) |
| 13 | +const BreadcrumbList = styled(BREADCRUMB_LIST_TAG, { |
| 14 | + padding: 0, |
| 15 | + margin: 0, |
| 16 | + listStyleType: 'none', |
| 17 | +}) |
| 18 | + |
| 19 | +const StyledCrumb = styled(CRUMB_TAG, { |
| 20 | + display: 'inline', |
| 21 | + $$spacing: '$space$3', |
| 22 | + |
| 23 | + '&:not(:first-of-type)': { |
| 24 | + marginLeft: '$$spacing', |
| 25 | + |
| 26 | + '&::before': { |
| 27 | + content: '', |
| 28 | + opacity: 0.25, |
| 29 | + marginRight: '$$spacing', |
| 30 | + display: 'inline-block', |
| 31 | + transform: 'rotate(15deg)', |
| 32 | + borderRight: '1px solid', |
| 33 | + height: '0.8em', |
| 34 | + }, |
| 35 | + }, |
| 36 | +}) |
| 37 | + |
| 38 | +type BreadcrumbsVariants = VariantProps<typeof StyledBreadcrumbs> |
| 39 | +type BreadcrumbsProps = BreadcrumbsVariants & |
| 40 | + CSSProps & |
| 41 | + ComponentProps<typeof BREADCRUMB_TAG> |
| 42 | + |
| 43 | +export const Breadcrumbs = forwardRef< |
| 44 | + ElementRef<typeof StyledBreadcrumbs>, |
| 45 | + BreadcrumbsProps |
| 46 | +>(({ children, ...props }, forwardedRef) => { |
| 47 | + return ( |
| 48 | + <StyledBreadcrumbs aria-label="Breadcrumb" {...props} ref={forwardedRef}> |
| 49 | + <BreadcrumbList>{children}</BreadcrumbList> |
| 50 | + </StyledBreadcrumbs> |
| 51 | + ) |
| 52 | +}) |
| 53 | +Breadcrumbs.toString = () => `.${StyledBreadcrumbs.className}` |
| 54 | + |
| 55 | +export type CrumbProps = LinkProps & { |
| 56 | + isCurrentPage?: boolean |
| 57 | +} |
| 58 | + |
| 59 | +export const Crumb = ({ |
| 60 | + isCurrentPage = false, |
| 61 | + children, |
| 62 | + ...props |
| 63 | +}: CrumbProps) => { |
| 64 | + return ( |
| 65 | + <StyledCrumb> |
| 66 | + <Link |
| 67 | + variant={isCurrentPage ? 'clear' : 'hovered'} |
| 68 | + aria-current={isCurrentPage ? 'page' : undefined} |
| 69 | + {...props} |
| 70 | + > |
| 71 | + {children} |
| 72 | + </Link> |
| 73 | + </StyledCrumb> |
| 74 | + ) |
| 75 | +} |
0 commit comments