// Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { CSSProperties, KeyboardEventHandler, MouseEventHandler, ReactNode, } from 'react'; import React from 'react'; import classNames from 'classnames'; import type { Theme } from '../util/theme'; import { assertDev } from '../util/assert'; import { themeClassName } from '../util/theme'; export enum ButtonSize { Large, Medium, Small, } export enum ButtonVariant { Calling = 'Calling', Destructive = 'Destructive', Details = 'Details', Primary = 'Primary', Secondary = 'Secondary', SecondaryAffirmative = 'SecondaryAffirmative', SecondaryDestructive = 'SecondaryDestructive', SystemMessage = 'SystemMessage', } export enum ButtonIconType { audio = 'audio', message = 'message', muted = 'muted', search = 'search', unmuted = 'unmuted', video = 'video', } type PropsType = { className?: string; disabled?: boolean; icon?: ButtonIconType; size?: ButtonSize; style?: CSSProperties; tabIndex?: number; theme?: Theme; variant?: ButtonVariant; 'aria-disabled'?: boolean; } & ( | { onClick: MouseEventHandler; // TODO: DESKTOP-4121 onKeyDown?: KeyboardEventHandler; } | { type: 'submit'; form?: string; } ) & ( | { 'aria-label': string; children: ReactNode; } | { 'aria-label'?: string; children: ReactNode; } | { 'aria-label': string; children?: ReactNode; } ); const SIZE_CLASS_NAMES = new Map([ [ButtonSize.Large, 'module-Button--large'], [ButtonSize.Medium, 'module-Button--medium'], [ButtonSize.Small, 'module-Button--small'], ]); const VARIANT_CLASS_NAMES = new Map([ [ButtonVariant.Primary, 'module-Button--primary'], [ButtonVariant.Secondary, 'module-Button--secondary'], [ ButtonVariant.SecondaryAffirmative, 'module-Button--secondary module-Button--secondary--affirmative', ], [ ButtonVariant.SecondaryDestructive, 'module-Button--secondary module-Button--secondary--destructive', ], [ButtonVariant.Destructive, 'module-Button--destructive'], [ButtonVariant.Calling, 'module-Button--calling'], [ButtonVariant.SystemMessage, 'module-Button--system-message'], [ButtonVariant.Details, 'module-Button--details'], ]); export const Button = React.forwardRef( function ButtonInner(props, ref) { const { children, className, disabled = false, icon, style, tabIndex, theme, variant = ButtonVariant.Primary, size = variant === ButtonVariant.Details ? ButtonSize.Small : ButtonSize.Medium, } = props; const ariaLabel = props['aria-label']; const ariaDisabled = props['aria-disabled']; let onClick: undefined | MouseEventHandler; let type: 'button' | 'submit'; let form; if ('onClick' in props) { ({ onClick } = props); type = 'button'; } else { onClick = undefined; ({ type } = props); ({ form } = props); } const sizeClassName = SIZE_CLASS_NAMES.get(size); assertDev(sizeClassName, ' ); if (theme) { return
{buttonElement}
; } return buttonElement; } );