import * as React from 'react' import * as PropTypes from 'prop-types' import styled from 'styled-components' import { Size, SizeMap } from '../../services/utilities' import stringify from '../../services/stringify' export type Variant = 'outline' | 'primary' const MIN_HEIGHTS: SizeMap = { small: '2.5rem', medium: '3rem', large: '4rem', } const Base = styled('button')({ 'appearance': 'none', 'padding': '0 1rem', 'font': 'inherit', 'fontFamily': 'var(--font-family-base)', 'textTransform': 'uppercase', 'fontWeight': 'bolder', 'borderRadius': '0.25rem', 'placeContent': 'center', 'position': 'relative', 'cursor': 'pointer', 'border': 0, 'userSelect': 'none', 'textDecoration': 'none', 'transitionProperty': 'background-color, color', 'whiteSpace': 'nowrap', 'lineHeight': 1, ':focus': { '--color-accent': 'var(--color-active, Highlight)', 'outline': 0, }, ':disabled': { opacity: 0.5, cursor: 'not-allowed', }, '::-moz-focus-inner': { outline: 0, border: 0, }, }) Base.displayName = 'button' const Border = styled('span')({ 'borderColor': 'var(--color-accent, blue)', 'boxSizing': 'border-box', 'display': 'inline-block', 'borderWidth': '0.125rem', 'borderStyle': 'solid', 'position': 'absolute', 'top': 0, 'left': 0, 'width': '100%', 'height': '100%', 'borderRadius': 'inherit', 'pointerEvents': 'none', 'transitionProperty': 'border-color', '::before': { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', content: "''", borderRadius: '0.125rem', opacity: 0.5, pointerEvents: 'none', }, [`${Base}:focus &::before`]: { boxShadow: '0 0 0 0.375rem var(--color-accent, blue)', }, }) Border.displayName = 'span' const propTypes = { /** * Size of the component. */ size: PropTypes.oneOf(['small', 'medium', 'large']), /** * Variant of the component. */ variant: PropTypes.oneOf>(['outline', 'primary']), /** * Should the component take up the remaining space parallel to the content flow? */ block: PropTypes.bool, /** * Text to identify the action associated upon activation of the component. */ children: PropTypes.any, /** * Can the component be activated? */ disabled: PropTypes.bool, } type Props = PropTypes.InferProps const defaultVariantStyleSet: React.CSSProperties = { backgroundColor: 'transparent', color: 'var(--color-accent, blue)', } const variantStyleSets: Record = { outline: defaultVariantStyleSet, primary: { backgroundColor: 'var(--color-accent, blue)', color: 'var(--color-bg, white)', }, } const Button = React.forwardRef( ({ size = 'medium', variant = 'outline', block = false, disabled = false, children, ...etcProps }, ref) => { const { [variant as Variant]: theVariantStyleSet = defaultVariantStyleSet } = variantStyleSets return ( {stringify(children)} ) }, ) Button.propTypes = propTypes Button.displayName = 'Button' export default Button