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);
`;