@patreon/studio
Version:
Patreon Studio Design System
83 lines (80 loc) • 4.11 kB
JSX
'use client';
import cx from 'classnames';
import React, { useId } from 'react';
import { BodyText } from '~/components/BodyText';
import { Button } from '~/components/Button';
import { HeadingText } from '~/components/HeadingText';
import { IconClose } from '~/components/Icon';
import { LoadingSpinner } from '~/components/LoadingSpinner';
import { TextLink } from '~/components/TextLink';
import { tokens } from '~/tokens';
import { report } from '~/utilities/deprecation';
import styles from './Banner.module.css';
export function Banner({ action, secondaryAction, alignAction = 'right', children, header, inlineLink, 'data-tag': dataTag, id, inline, placement, onClose, variant = 'info', icon, loading = false, }) {
const contentId = useId();
const Icon = icon;
const isSingleLine = !header && !inlineLink;
const hasFloatingCloseButton = !isSingleLine && onClose && !action;
const hasInlineCloseButton = isSingleLine && !!onClose;
if (inline) {
report('`inline` property is deprecated, use the `placement` prop instead');
}
const role = variant === 'critical' || variant === 'warning' ? 'alert' : 'status';
const computedIcon = (Icon || loading) && (<div className={styles.accessoryWrapper}>
{Icon && !loading && (<div className={styles.iconWrapper}>
<Icon size={{
xs: '20px',
md: placement === 'inline-large' ? '24px' : '20px',
}} color="inherit"/>
</div>)}
{loading && <LoadingSpinner size="xs"/>}
</div>);
const closeButton = hasInlineCloseButton && (<div className={styles.closeButtonWrapper}>
<Button onClick={onClose} size="sm" aria-label="close" icon={IconClose} variant="tertiary" unfilled corners="pill"/>
</div>);
const rootClassName = cx(styles.root, {
[styles.placementGlobal]: placement === 'global',
[styles.placementInlineLarge]: placement === 'inline-large',
[styles.placementInlineSmall]: placement === 'inline-small',
[styles.variantInfo]: variant === 'info',
[styles.variantInverted]: variant === 'inverted',
[styles.variantCritical]: variant === 'critical',
[styles.variantSuccess]: variant === 'success',
[styles.variantWarning]: variant === 'warning',
[styles.isSingleLine]: isSingleLine,
[styles.alignActionRight]: alignAction === 'right',
[styles.alignActionBottom]: alignAction === 'bottom',
});
const textColor = variant === 'inverted' ? tokens.global.inverted.regular.default : tokens.global.content.regular.default;
return (<div className={rootClassName} aria-describedby={contentId} aria-live="polite" data-tag={dataTag} id={id} role={role}>
{hasFloatingCloseButton && (<div className={styles.floatingCloseButton}>
<Button onClick={onClose} size="sm" aria-label="close" icon={IconClose} variant="tertiary" unfilled corners="pill"/>
</div>)}
<div className={styles.contentWrapper}>
{computedIcon}
<div className={styles.content}>
<div className={styles.textWrapper}>
{header && (<HeadingText as="h3" size="md" color={textColor}>
{header}
</HeadingText>)}
<BodyText as="div" size="md" color={textColor} className={styles.childrenContent}>
{children}
</BodyText>
{inlineLink && (<TextLink size="md" {...inlineLink}>
{inlineLink.label}
</TextLink>)}
</div>
{(secondaryAction || action) && (<div className={styles.actionWrapper}>
{secondaryAction && (<Button data-tag="secondary-action" variant={variant === 'inverted' ? 'insetWhite' : 'tertiary'} size="md" {...secondaryAction}>
{secondaryAction.label}
</Button>)}
{action && (<Button data-tag="action" variant="insetWhite" size="md" {...action}>
{action.label}
</Button>)}
</div>)}
</div>
{closeButton}
</div>
</div>);
}
//# sourceMappingURL=index.jsx.map