UNPKG

@patreon/studio

Version:

Patreon Studio Design System

83 lines (80 loc) 4.11 kB
'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