@primer/react
Version:
An implementation of GitHub's Primer Design System using React
199 lines (196 loc) • 6.83 kB
JavaScript
import { clsx } from 'clsx';
import React, { useEffect, forwardRef } from 'react';
import { XIcon, AlertIcon, InfoIcon, CheckCircleIcon, StopIcon } from '@primer/octicons-react';
import { IconButton } from '../Button/IconButton.js';
import { ButtonComponent } from '../Button/Button.js';
import { useMergedRefs } from '../hooks/useMergedRefs.js';
import { useId } from '../hooks/useId.js';
import classes from './Banner.module.css.js';
import { jsx, jsxs } from 'react/jsx-runtime';
import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden.js';
const BannerContext = /*#__PURE__*/React.createContext(undefined);
const iconForVariant = {
critical: /*#__PURE__*/jsx(StopIcon, {}),
info: /*#__PURE__*/jsx(InfoIcon, {}),
success: /*#__PURE__*/jsx(CheckCircleIcon, {}),
upsell: /*#__PURE__*/jsx(InfoIcon, {}),
warning: /*#__PURE__*/jsx(AlertIcon, {})
};
const Banner = /*#__PURE__*/React.forwardRef(function Banner({
'aria-label': label,
'aria-labelledby': labelledBy,
children,
className,
description,
hideTitle,
icon,
leadingVisual,
onDismiss,
primaryAction,
secondaryAction,
title,
variant = 'info',
actionsLayout = 'default',
flush = false,
...rest
}, forwardRef) {
const dismissible = !!onDismiss;
const hasActions = primaryAction || secondaryAction;
const bannerRef = React.useRef(null);
const ref = useMergedRefs(forwardRef, bannerRef);
const supportsCustomIcon = variant === 'info' || variant === 'upsell';
const titleId = useId();
const visual = leadingVisual !== null && leadingVisual !== void 0 ? leadingVisual : icon;
if (process.env.NODE_ENV !== "production") {
// This hook is called consistently depending on the environment
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (title) {
return;
}
const {
current: banner
} = bannerRef;
if (!banner) {
return;
}
const hasTitle = banner.querySelector('[data-banner-title]');
if (!hasTitle) {
throw new Error('Expected a title to be provided to the <Banner> component with the `title` prop or through `<Banner.Title>` but no title was found');
}
}, [title]);
}
return /*#__PURE__*/jsx(BannerContext.Provider, {
value: {
titleId
},
children: /*#__PURE__*/jsxs("section", {
"data-component": "Banner",
...rest,
"aria-labelledby": labelledBy !== null && labelledBy !== void 0 ? labelledBy : label ? undefined : titleId,
"aria-label": labelledBy ? undefined : label,
className: clsx(className, classes.Banner),
"data-dismissible": onDismiss ? '' : undefined,
"data-has-actions": hasActions ? '' : undefined,
"data-title-hidden": hideTitle ? '' : undefined,
"data-variant": variant,
"data-actions-layout": actionsLayout,
tabIndex: -1,
ref: ref,
"data-layout": rest.layout || 'default',
"data-flush": flush ? '' : undefined,
children: [/*#__PURE__*/jsx("div", {
"data-component": "Banner.Icon",
className: classes.BannerIcon,
children: visual && supportsCustomIcon ? visual : iconForVariant[variant]
}), /*#__PURE__*/jsxs("div", {
className: classes.BannerContainer,
children: [/*#__PURE__*/jsxs("div", {
"data-component": "Banner.Content",
className: classes.BannerContent,
children: [title ? hideTitle ? /*#__PURE__*/jsx(VisuallyHidden, {
children: /*#__PURE__*/jsx(BannerTitle, {
children: title
})
}) : /*#__PURE__*/jsx(BannerTitle, {
children: title
}) : null, description ? /*#__PURE__*/jsx(BannerDescription, {
children: description
}) : null, children]
}), hasActions ? /*#__PURE__*/jsx(BannerActions, {
primaryAction: primaryAction,
secondaryAction: secondaryAction
}) : null]
}), dismissible ? /*#__PURE__*/jsx(IconButton, {
"aria-label": "Dismiss banner",
onClick: onDismiss,
className: classes.BannerDismiss,
icon: XIcon,
variant: "invisible"
}) : null]
})
});
});
function BannerTitle(props) {
const {
as: Heading = 'h2',
className,
children,
id,
...rest
} = props;
const context = React.useContext(BannerContext);
const titleId = id !== null && id !== void 0 ? id : context === null || context === void 0 ? void 0 : context.titleId;
return /*#__PURE__*/jsx(Heading, {
...rest,
id: titleId,
className: clsx(className, classes.BannerTitle),
"data-component": "Banner.Title",
"data-banner-title": "",
children: children
});
}
BannerTitle.displayName = "BannerTitle";
function BannerDescription({
children,
className,
...rest
}) {
return /*#__PURE__*/jsx("div", {
...rest,
className: clsx('BannerDescription', className),
"data-component": "Banner.Description",
children: children
});
}
BannerDescription.displayName = "BannerDescription";
function BannerActions({
primaryAction,
secondaryAction
}) {
return /*#__PURE__*/jsxs("div", {
className: classes.BannerActions,
"data-component": "Banner.Actions",
children: [/*#__PURE__*/jsxs("div", {
className: classes.BannerActionsContainer,
"data-primary-action": "trailing",
children: [secondaryAction !== null && secondaryAction !== void 0 ? secondaryAction : null, primaryAction !== null && primaryAction !== void 0 ? primaryAction : null]
}), /*#__PURE__*/jsxs("div", {
className: classes.BannerActionsContainer,
"data-primary-action": "leading",
children: [primaryAction !== null && primaryAction !== void 0 ? primaryAction : null, secondaryAction !== null && secondaryAction !== void 0 ? secondaryAction : null]
})]
});
}
BannerActions.displayName = "BannerActions";
const BannerPrimaryAction = /*#__PURE__*/forwardRef(({
children,
className,
...rest
}, forwardedRef) => {
return /*#__PURE__*/jsx(ButtonComponent, {
"data-component": "Banner.PrimaryAction",
ref: forwardedRef,
className: clsx('BannerPrimaryAction', className),
variant: "default",
...rest,
children: children
});
});
BannerPrimaryAction.displayName = 'BannerPrimaryAction';
const BannerSecondaryAction = /*#__PURE__*/forwardRef(({
children,
className,
...rest
}, forwardedRef) => {
return /*#__PURE__*/jsx(ButtonComponent, {
"data-component": "Banner.SecondaryAction",
ref: forwardedRef,
className: clsx('BannerPrimaryAction', className),
variant: "invisible",
...rest,
children: children
});
});
BannerSecondaryAction.displayName = 'BannerSecondaryAction';
export { Banner, BannerActions, BannerDescription, BannerPrimaryAction, BannerSecondaryAction, BannerTitle };