import React from 'react'; import styled, { css } from 'styled-components'; import type { JSX } from 'react'; import type { BreadcrumbItem } from '@redocly/config'; import { useThemeHooks } from '@redocly/theme/core/hooks'; import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown'; import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu'; import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem'; import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip'; import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon'; import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants'; import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon'; type BreadcrumbDropdownProps = { children?: React.ReactNode; label: string; items: (BreadcrumbItem & { isActive?: boolean })[]; onItemClick?: (item: BreadcrumbItem, index: number) => void; className?: string; }; export function BreadcrumbDropdown({ children, label, items, onItemClick, className, }: BreadcrumbDropdownProps): JSX.Element | null { const { useTelemetry, useTranslate } = useThemeHooks(); const telemetry = useTelemetry(); const { translate } = useTranslate(); if (!items || items.length === 0) { return null; } const isTruncated = label.length > BREADCRUMB_MAX_LENGTH; const triggerContent = isTruncated ? ( {children} ) : ( children ); const trigger = {triggerContent}; return ( {items.map((item, index) => { const isActive = Boolean(item?.isActive); const hasLink = Boolean(item.link); const translatedLabel = translate(item.labelTranslationKey, item.label); return ( { onItemClick?.(item, index); telemetry.sendBreadcrumbClickedMessage([ { object: 'breadcrumb', link: item.link, position: index + 1, totalBreadcrumbs: items.length, }, ]); }} $hasLink={hasLink} to={item.link} dataAttributes={!hasLink ? { 'aria-disabled': 'true' } : {}} > {translatedLabel} {isActive && ( )} ); })} ); } const BreadcrumbDropdownWrapper = styled.div` display: inline-flex; align-items: center; `; const StyledDropdownTrigger = styled.button` display: flex; align-items: center; gap: var(--breadcrumbs-gap); border: none; background: none; border-radius: var(--breadcrumbs-border-radius); color: var(--breadcrumbs-text-color); cursor: pointer; font-size: var(--breadcrumbs-font-size); &:hover { background-color: var(--breadcrumbs-background-color-hover); } &:focus { box-shadow: var(--breadcrumbs-box-shadow-focus); outline: none; } `; const StyledDropdownMenuItem = styled(DropdownMenuItem)<{ $hasLink: boolean }>` cursor: ${(props) => (props.$hasLink ? 'pointer' : 'default')}; ${(props) => !props.$hasLink && css` &:focus, &:focus-visible { outline: none; box-shadow: none; } &:hover { background-color: transparent; color: inherit; } `} `; const TriggerContentWrapper = styled.span` display: flex; align-items: center; gap: var(--breadcrumbs-gap); `; const DropdownContent = styled.div<{ $isActive: boolean }>` display: flex; align-items: center; gap: var(--breadcrumbs-gap); padding: var(--breadcrumb-padding); color: ${(props) => (props.$isActive ? 'var(--breadcrumbs-text-color-active)' : 'inherit')}; font-weight: ${(props) => props.$isActive ? 'var(--breadcrumbs-font-weight-active)' : 'inherit'}; `; const DropdownLabel = styled.span` color: inherit; `; const ActiveIcon = styled.span` position: absolute; left: var(--breadcrumb-dropdown-active-icon-position); display: inline-flex; align-items: center; color: inherit; width: var(--breadcrumbs-icon-size); height: var(--breadcrumbs-icon-size); `;