@primer/react
Version:
An implementation of GitHub's Primer Design System using React
154 lines (151 loc) • 6.03 kB
JavaScript
import { clsx } from 'clsx';
import React, { useEffect, forwardRef } from 'react';
import { XIcon, StopIcon, InfoIcon, CheckCircleIcon, AlertIcon } from '@primer/octicons-react';
import { IconButton } from '../Button/IconButton.js';
import '../Button/ButtonBase.js';
import '../utils/defaultSxProp.js';
import { ButtonComponent } from '../Button/Button.js';
import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden.js';
import { useMergedRefs } from '../internal/hooks/useMergedRefs.js';
import classes from './Banner.module.css.js';
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const iconForVariant = {
critical: /*#__PURE__*/React.createElement(StopIcon, null),
info: /*#__PURE__*/React.createElement(InfoIcon, null),
success: /*#__PURE__*/React.createElement(CheckCircleIcon, null),
upsell: /*#__PURE__*/React.createElement(InfoIcon, null),
warning: /*#__PURE__*/React.createElement(AlertIcon, null)
};
const labels = {
critical: 'Critical',
info: 'Information',
success: 'Success',
upsell: 'Recommendation',
warning: 'Warning'
};
const Banner = /*#__PURE__*/React.forwardRef(function Banner({
'aria-label': label,
children,
className,
description,
hideTitle,
icon,
onDismiss,
primaryAction,
secondaryAction,
title,
variant = 'info',
...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';
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__*/React.createElement("section", _extends({}, rest, {
"aria-label": label !== null && label !== undefined ? label : labels[variant],
className: clsx(className, classes.Banner),
"data-dismissible": onDismiss ? '' : undefined,
"data-title-hidden": hideTitle ? '' : undefined,
"data-variant": variant,
tabIndex: -1,
ref: ref
}), /*#__PURE__*/React.createElement("div", {
className: classes.BannerIcon
}, icon && supportsCustomIcon ? icon : iconForVariant[variant]), /*#__PURE__*/React.createElement("div", {
className: classes.BannerContainer
}, /*#__PURE__*/React.createElement("div", {
className: classes.BannerContent
}, title ? hideTitle ? /*#__PURE__*/React.createElement(VisuallyHidden, null, /*#__PURE__*/React.createElement(BannerTitle, null, title)) : /*#__PURE__*/React.createElement(BannerTitle, null, title) : null, description ? /*#__PURE__*/React.createElement(BannerDescription, null, description) : null, children), hasActions ? /*#__PURE__*/React.createElement(BannerActions, {
primaryAction: primaryAction,
secondaryAction: secondaryAction
}) : null), dismissible ? /*#__PURE__*/React.createElement(IconButton, {
"aria-label": "Dismiss banner",
onClick: onDismiss,
className: classes.BannerDismiss,
icon: XIcon,
variant: "invisible"
}) : null);
});
function BannerTitle(props) {
const {
as: Heading = 'h2',
className,
children,
...rest
} = props;
return /*#__PURE__*/React.createElement(Heading, _extends({}, rest, {
className: clsx(className, classes.BannerTitle),
"data-banner-title": ""
}), children);
}
BannerTitle.displayName = "BannerTitle";
function BannerDescription({
children,
className,
...rest
}) {
return /*#__PURE__*/React.createElement("div", _extends({}, rest, {
className: clsx('BannerDescription', className)
}), children);
}
BannerDescription.displayName = "BannerDescription";
function BannerActions({
primaryAction,
secondaryAction
}) {
return /*#__PURE__*/React.createElement("div", {
className: classes.BannerActions
}, /*#__PURE__*/React.createElement("div", {
className: classes.BannerActionsContainer,
"data-primary-action": "trailing"
}, secondaryAction !== null && secondaryAction !== undefined ? secondaryAction : null, primaryAction !== null && primaryAction !== undefined ? primaryAction : null), /*#__PURE__*/React.createElement("div", {
className: classes.BannerActionsContainer,
"data-primary-action": "leading"
}, primaryAction !== null && primaryAction !== undefined ? primaryAction : null, secondaryAction !== null && secondaryAction !== undefined ? secondaryAction : null));
}
BannerActions.displayName = "BannerActions";
const BannerPrimaryAction = /*#__PURE__*/forwardRef(({
children,
className,
...rest
}, forwardedRef) => {
return /*#__PURE__*/React.createElement(ButtonComponent, _extends({
ref: forwardedRef,
className: clsx('BannerPrimaryAction', className),
variant: "default"
}, rest), children);
});
BannerPrimaryAction.displayName = 'BannerPrimaryAction';
const BannerSecondaryAction = /*#__PURE__*/forwardRef(({
children,
className,
...rest
}, forwardedRef) => {
return /*#__PURE__*/React.createElement(ButtonComponent, _extends({
ref: forwardedRef,
className: clsx('BannerPrimaryAction', className),
variant: "link"
}, rest), children);
});
BannerSecondaryAction.displayName = 'BannerSecondaryAction';
export { Banner, BannerActions, BannerDescription, BannerPrimaryAction, BannerSecondaryAction, BannerTitle };