import { type ReactNode, type ElementType, type ComponentPropsWithoutRef } from 'react';
export type SubNavigationRenderLabelFunction = (label: string) => ReactNode;
export type SubNavigationProps = VerticalSubNavigationProps | HorizontalSubNavigationProps;
type VerticalSubNavigationProps = BaseSubNavigationProps & {
/**
* The list of navigation items.
*
* - When `orientation` is `"vertical"`, each item **can** have children.
*/
navigationItems: NavigationItem[];
/**
* The orientation for laying out navigation items.
*
* @default 'vertical'
*/
orientation?: 'vertical';
};
type HorizontalSubNavigationProps = BaseSubNavigationProps & {
/**
* The list of navigation items.
*
* - When `orientation` is `"horizontal"`, each item **cannot** have children.
*/
navigationItems: ChildlessNavigationItem[];
/**
* The orientation for laying out navigation items.
*
* @default 'vertical'
*/
orientation?: 'horizontal';
};
/**
* Common properties for both vertical and horizontal SubNavigation.
*/
type BaseSubNavigationProps = {
/**
* The component to use as the link element instead of the general anchor element ``.
* The custom component must extend the HTMLAnchorElement interface.
*
* If this property is not set, the navigation link is rendered as an general anchor element ``.
*
* This property depends on the `isExternal` property of each navigation item.
*
* - If the `isExternal` property is set to true, the navigation link is rendered as an general anchor element `` with `target="_blank"`.
* - If the `isExternal` property is set to false, the navigation link is rendered as the custom component.
*
* Use this property if you want to use a custom component as the navigation link.
* e.g. next/link
*/
customLinkComponent?: ElementType;
/**
* Custom render function for each navigation item's label.
* Receives the item's raw `label` string and returns a ReactNode rendered inside
* the default `` wrapper.
* When omitted, the label string is rendered directly (default behavior).
*
* Use this to truncate long labels or otherwise customize how labels are displayed
* without losing the built-in semantic markup.
*
* To show a tooltip on both hover and focus, wrap the entire link with a `Tooltip`
* via `customLinkComponent` instead — placing a `Tooltip` inside `renderNavigationLabel`
* only works for hover because the tooltip trigger ends up inside the focusable ``,
* and focus events do not propagate inward to child elements.
*
* @param label - The label string of the navigation item.
*
* @returns ReactNode - Custom content rendered inside the label wrapper.
*
* @example
* ```tsx
* // Truncate labels that exceed 2 lines
* (
*
* {label}
*
* )}
* />
* ```
*/
renderNavigationLabel?: SubNavigationRenderLabelFunction;
/**
* Content displayed above the navigation list, rendered inside a padded wrapper.
* Use this to add a feature shortcut, promotional content, or other header-level
* UI at the top of the navigation.
*
* @example
* ```tsx
*
* Upgrade plan
*
* }
* />
* ```
*/
headerSlot?: ReactNode;
/**
* For overriding styles if you need.
*/
className?: string;
};
/**
* The union that discriminates whether each navigation item has children.
*/
type NavigationItem = ChildlessNavigationItem | ParentNavigationItem;
/**
* The navigation item that has no children.
*/
type ChildlessNavigationItem = BaseNavigationItem & {
/**
* No nested navigation items.
*/
children?: undefined;
/**
* The path or URL to the linked page.
*/
href: string;
/**
* If provided, the item is rendered as a button instead of a link.
* The handler is called with the item's `href` value as an argument.
*
* Use this for state-based navigation patterns where you want to update
* application state on click without performing browser navigation.
*/
onClick?: (href: string) => void;
};
/**
* The navigation item that has nested children.
*/
type ParentNavigationItem = BaseNavigationItem & {
/**
* The nested navigation items.
*/
children: NavigationItem[];
/**
* The path or URL to the linked page.
* When this property is set, the parent navigation item would be a link
* and only the disclosure icon is a button to expand children.
*/
href?: string;
};
/**
* Common properties for all navigation items.
*/
type BaseNavigationItem = {
/**
* The text label briefly describing the linked page.
*/
label: string;
/**
* Whether the navigation item is the current page.
*
* If this property is set to true, the navigation item is highlighted as the current page.
* When the navigation item is the nested navigation item, the parent navigation is opened by default.
*/
isCurrent?: boolean;
/**
* Whether the linked page is external.
*
* If this property is set to true, `target='_blank' is set to the link`.
*/
isExternal?: boolean;
/**
* The icon that is displayed on the left side of the text label.
*/
labelIcon?: ReactNode;
/**
* For a status icon or badge that is displayed on the right side of the text label.
* If `locked` prop is true, any indicators in this slot will be ignored.
*/
statusSlot?: ReactNode;
/**
* Display a lock icon on the right side to indicate the navigation item is locked by permission.
* This option does not actually disable the link.
*/
locked?: boolean;
/**
* The properties for the lock icon.
*
* @property aria-label - The alternative text for the lock icon. It's set "ロックされています" by default.
*/
lockIconProps?: Pick, 'aria-label'>;
};
export {};