import { clsx } from 'clsx'; import { AriaLabelProperty, CommonProps, Heading, LinkProps, Typography } from '../common'; import Link from '../link'; import Title from '../title'; import React, { useEffect, useRef, FunctionComponent, ReactNode } from 'react'; type ActionProps = AriaLabelProperty & { text: string; onClick?: (event: React.MouseEvent) => void; disabled?: boolean; }; type ButtonActionProps = ActionProps; type LinkActionProps = ActionProps & LinkProps; export interface HeaderProps extends CommonProps { /** * Optional prop to define the action for the header. If the `href` property * is provided, a `Link` will be rendered instead of a `Button`. */ action?: ButtonActionProps | LinkActionProps; /** * Option prop to specify DOM render element of the title * * - When `as="legend"`, the `Header` will render as a `` element. * **Note:** `` elements must be the first child of a `
` to comply with HTML semantics. * If this condition is not met, a warning will be logged to the console. * * - Other valid values include standard heading tags (`h1` to `h6`) or `header`. * @default 'h5' */ as?: Heading | 'legend' | 'header'; /** Required prop to set the title of the Header. */ title: ReactNode; /** * Optional prop to specify the level of the Header * @default 'group' */ level?: 'section' | 'group'; className?: string; testId?: string; } /** * Renders a header action which can be either a button or a link. * * @param {Object} props - The properties object. * @param {ButtonActionProps | LinkActionProps} props.action - The action object which can be either a button or a link. * @returns {JSX.Element} The rendered header action component. */ const HeaderAction = React.forwardRef< HTMLButtonElement | HTMLAnchorElement, { action: ButtonActionProps | LinkActionProps } >(({ action }, ref) => { return ( {action.text} ); }); HeaderAction.displayName = 'HeaderAction'; /** * @param {ButtonActionProps | LinkActionProps} [action] - Optional prop to specify the action button or link. * @param {Heading | 'legend'} [as='h5'] - Optional prop to override the heading element rendered for the title. * @param {string} title - Required prop to set the title of the section header. * @param {'group' | 'section'} [level='group'] - Optional prop to specify the level of the section header. * @param {string} [className] * @param {string} [testId] * * @see {@link Header } for further information. * @see {@link https://storybook.wise.design/?path=/docs/typography-header--docs|Storybook Wise Design} */ const Header: FunctionComponent = React.forwardRef( ( { as = 'h5', action, className, testId, title, level = 'group', ...props }, ref: React.Ref, ) => { const internalRef = useRef(null); const levelTypography = level === 'group' ? Typography.TITLE_GROUP : Typography.TITLE_SUBSECTION; const headerClasses = clsx('np-header', className, { 'np-header--group': level === 'group', }); const commonProps = { className: headerClasses, 'data-testid': testId, }; useEffect(() => { if (as === 'legend' && internalRef.current) { const { parentElement } = internalRef.current; if (!parentElement || parentElement.tagName.toLowerCase() !== 'fieldset') { console.warn( 'Legends should be the first child in a fieldset, and this is not possible when including an action', ); } } }, [as]); if (!action) { return ( {title} ); } return (
}> {title}
); }, ); Header.displayName = 'Header'; export default Header;