# All files / src/Breadcrumbs Breadcrumbs.tsx

100% Statements 37/37
100% Branches 25/25
100% Functions 6/6
100% Lines 32/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    12313x
    13x
    13x
    13x

    13x

    13x

    13x

    13x

    43x

    43x
    43x
    43x

    43x
    130x

    130x
    130x

    130x

    130x

    43x

    13x

    131x
    131x
    137x

    130x
    40x

    90x

    131x

    131x
    131x

    13x

    13x

    13x

     import { ChevronRight } from '@procore/core-icons'
    import React, { ForwardedRef } from 'react'
    import { useI18nContext } from '../_hooks/I18n'
    import { addSubcomponents } from '../_utils/addSubcomponents'
    import { DivAttributes, LiAttributes, NavAttributes } from '../_utils/types'
    import {
      StyledContainer,
      StyledCrumb,
      StyledList,
      StyledSeparator,
    } from './Breadcrumbs.styles'
    import {
      BreadcrumbCrumbProps,
      BreadcrumbProps,
      BreadcrumbVariants,
    } from './Breadcrumbs.types'

    const separator = (
      <StyledSeparator aria-hidden={true}>
        <ChevronRight />
      </StyledSeparator>
    )

    /**

     We use breadcrumbs to provide navigational information to the user on every
     tool’s child page in Procore.

     @since 10.19.0

     @see [Storybook](https://procore.github.io/core/core-react/latest/?path=/story/demos-breadcrumbs--demo)

     @see [Design Guidelines](https://design.procore.com/breadcrumb)

     */
    const Breadcrumbs_ = React.forwardRef<
      HTMLElement,
      NavAttributes & BreadcrumbProps
    >(function Breadcrumbs(
      { children, variant = BreadcrumbVariants.LEGACY, ...props },
      ref
    ) {
      const i18n = useI18nContext()
      const childrenArray = React.Children.toArray(children)
      const isLegacy = variant === BreadcrumbVariants.LEGACY

      const navigationList = childrenArray
        .filter((child) => child)
        .map((child, i) => {
          const isLast = i === childrenArray.length - 1
          const aria = {
            'aria-current': (child as React.ReactElement).props.active || undefined,
          }
          const cloneProps = isLegacy
            ? aria
            : {
                ...aria,
                isLast,
                variant,
              }

          return (
            <React.Fragment key={`separator-${i}`}>
              {React.cloneElement(child as React.ReactElement, cloneProps)}
              {isLegacy && !isLast ? separator : <></>}
            </React.Fragment>
          )
        })
      return (
        <StyledContainer
          aria-label={i18n.t('core.breadcrumbs.label')}
          {...props}
          ref={ref}
        >
          {!isLegacy ? <StyledList>{navigationList}</StyledList> : navigationList}
        </StyledContainer>
      )
    })

    type NavCrumbProps = LiAttributes & BreadcrumbCrumbProps
    type LegacyCrumbProps = DivAttributes & BreadcrumbCrumbProps

    export const Crumb = React.forwardRef<
      HTMLLIElement | HTMLDivElement,
      NavCrumbProps | LegacyCrumbProps
    >(function Crumb({ variant = BreadcrumbVariants.LEGACY, ...props }, ref) {
      const childrenWithAriaAttrs = React.Children.toArray(props.children)
        .filter((child) => child)
        .map((child) => {
          if (React.isValidElement<{ 'aria-current'?: boolean }>(child)) {
            return React.cloneElement(child, {
              'aria-current': props.active || undefined,
            })
          } else {
            return child
          }
        })
      const isLegacy = variant === BreadcrumbVariants.LEGACY
      const showSeparator =
        !isLegacy && props.hasOwnProperty('isLast') && !props.isLast
      return (
        <StyledCrumb
          as={isLegacy ? 'div' : 'li'}
          {...(props as NavCrumbProps)}
          ref={ref as ForwardedRef<HTMLLIElement>}
        >
          {childrenWithAriaAttrs}
          {showSeparator ? separator : <></>}
        </StyledCrumb>
      )
    })

    Breadcrumbs_.displayName = 'Breadcrumbs'

    Crumb.displayName = 'Breadcrumbs.Crumb'

    export const Breadcrumbs = addSubcomponents(
      {
        Crumb,
      },
      Breadcrumbs_
    )