import * as React from 'react'; import { Button, tailwind } from '@tesseract-design/web-base'; import { useFallbackId } from '@modal-sh/react-utils'; const { tw } = tailwind; const ToggleButtonDerivedElementComponent = 'input' as const; /** * Derived HTML element of the {@link ToggleButton} component. */ export type ToggleButtonDerivedElement = HTMLElementTagNameMap[ typeof ToggleButtonDerivedElementComponent ]; /** * Props of the {@link ToggleButton} component. */ export interface ToggleButtonProps extends Omit, 'type' | 'size'> { /** * Should the component occupy the whole width of its parent? */ block?: boolean; /** * Should the component's content use minimal space? */ compact?: boolean; /** * Size of the component. */ size?: Button.Size; /** * Complementary content of the component. */ subtext?: React.ReactNode; /** * Short complementary content displayed at the edge of the component. */ badge?: React.ReactNode; /** * Variant of the component. */ variant?: Button.Variant; /** * Is the component in an indeterminate state? */ indeterminate?: boolean; } export const toggleButtonPlugin: tailwind.PluginCreator = ({ addComponents, }) => { addComponents({ '.toggle-button': { '& + label > :first-child > :first-child': { 'display': 'none', }, '&:checked + label > :first-child > :first-child': { 'display': 'block', }, '& + label > :first-child > :first-child + *': { 'display': 'none', }, '&:indeterminate + label > :first-child > :first-child + *': { 'display': 'block', }, }, }); }; /** * Component for toggling a Boolean value. */ export const ToggleButton = React.forwardRef(( { children, block = false, compact = false, size = 'medium' as const, id: idProp, className, subtext, badge, variant = 'bare' as const, indeterminate = false, style, ...etcProps }, forwardedRef, ) => { const defaultRef = React.useRef(null); const ref = forwardedRef ?? defaultRef; const id = useFallbackId(idProp); React.useEffect(() => { if (typeof ref === 'function') { const defaultElement = defaultRef.current as ToggleButtonDerivedElement; defaultElement.indeterminate = indeterminate; ref(defaultElement); return; } const element = ref.current as ToggleButtonDerivedElement; element.indeterminate = indeterminate; }, [indeterminate, defaultRef, ref]); return ( ); }); ToggleButton.displayName = 'ToggleButton'; ToggleButton.defaultProps = { block: false, compact: false, size: 'medium', subtext: undefined, badge: undefined, indeterminate: false, variant: 'bare', };