@shopify/polaris
Version:
Shopify’s product component library
122 lines (121 loc) • 5.23 kB
JavaScript
import React from 'react';
import { CancelSmallMinor, CircleTickMajorTwotone, FlagMajorTwotone, CircleAlertMajorTwotone, CircleDisabledMajorTwotone, CircleInformationMajorTwotone, } from '@shopify/polaris-icons';
import { BannerContext } from '../../utilities/banner-context';
import { classNames, variationName } from '../../utilities/css';
import { Button, buttonFrom } from '../Button';
import { Heading } from '../Heading';
import { ButtonGroup } from '../ButtonGroup';
import { UnstyledLink } from '../UnstyledLink';
import { Icon } from '../Icon';
import { WithinContentContext } from '../../utilities/within-content-context';
import styles from './Banner.scss';
export class Banner extends React.PureComponent {
constructor() {
super(...arguments);
this.wrapper = React.createRef();
}
focus() {
this.wrapper.current && this.wrapper.current.focus();
}
render() {
return (<BannerContext.Provider value>
<WithinContentContext.Consumer>
{(withinContentContainer) => {
const { icon, action, secondaryAction, title, children, status, onDismiss, stopAnnouncements, } = this.props;
let color;
let defaultIcon;
let ariaRoleType = 'status';
switch (status) {
case 'success':
color = 'greenDark';
defaultIcon = CircleTickMajorTwotone;
break;
case 'info':
color = 'tealDark';
defaultIcon = CircleInformationMajorTwotone;
break;
case 'warning':
color = 'yellowDark';
defaultIcon = CircleAlertMajorTwotone;
ariaRoleType = 'alert';
break;
case 'critical':
color = 'redDark';
defaultIcon = CircleDisabledMajorTwotone;
ariaRoleType = 'alert';
break;
default:
color = 'inkLighter';
defaultIcon = FlagMajorTwotone;
}
const className = classNames(styles.Banner, status && styles[variationName('status', status)], onDismiss && styles.hasDismiss, withinContentContainer
? styles.withinContentContainer
: styles.withinPage);
const id = uniqueID();
const iconName = icon || defaultIcon;
let headingMarkup = null;
let headingID;
if (title) {
headingID = `${id}Heading`;
headingMarkup = (<div className={styles.Heading} id={headingID}>
<Heading element="p">{title}</Heading>
</div>);
}
const buttonSizeValue = withinContentContainer ? 'slim' : undefined;
const secondaryActionMarkup = secondaryAction
? secondaryActionFrom(secondaryAction)
: null;
const actionMarkup = action ? (<div className={styles.Actions}>
<ButtonGroup>
<div className={styles.PrimaryAction}>
{buttonFrom(action, { outline: true, size: buttonSizeValue })}
</div>
{secondaryActionMarkup}
</ButtonGroup>
</div>) : null;
let contentMarkup = null;
let contentID;
if (children || actionMarkup) {
contentID = `${id}Content`;
contentMarkup = (<div className={styles.Content} id={contentID}>
{children}
{actionMarkup}
</div>);
}
const dismissButton = onDismiss ? (<div className={styles.Dismiss}>
<Button plain icon={CancelSmallMinor} onClick={onDismiss} accessibilityLabel="Dismiss notification"/>
</div>) : null;
return (<div className={className}
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
tabIndex={0} ref={this.wrapper} role={ariaRoleType} aria-live={stopAnnouncements ? 'off' : 'polite'} onMouseUp={handleMouseUp} aria-labelledby={headingID} aria-describedby={contentID}>
{dismissButton}
<div className={styles.Ribbon}>
<Icon source={iconName} color={color} backdrop/>
</div>
<div>
{headingMarkup}
{contentMarkup}
</div>
</div>);
}}
</WithinContentContext.Consumer>
</BannerContext.Provider>);
}
}
let index = 1;
function uniqueID() {
return `Banner${index++}`;
}
function handleMouseUp({ currentTarget }) {
currentTarget.blur();
}
function secondaryActionFrom(action) {
if (action.url) {
return (<UnstyledLink className={styles.SecondaryAction} url={action.url} external={action.external}>
<span className={styles.Text}>{action.content}</span>
</UnstyledLink>);
}
return (<button className={styles.SecondaryAction} onClick={action.onAction}>
<span className={styles.Text}>{action.content}</span>
</button>);
}