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;