|
- import * as React from 'react';
- import clsx from 'clsx';
- import plugin from 'tailwindcss/plugin';
- import { useFallbackId } from '@modal-sh/react-utils';
-
- /**
- * Derived HTML element of the {@link RadioTickBox} component.
- */
- export type RadioTickBoxDerivedElement = HTMLInputElement;
-
- /**
- * Props of the {@link RadioTickBox} component.
- */
- export interface RadioTickBoxProps extends Omit<React.InputHTMLAttributes<RadioTickBoxDerivedElement>, 'type' | 'size'> {
- /**
- * Should the component occupy the whole width of its parent?
- */
- block?: boolean;
- /**
- * Complementary content of the component.
- */
- subtext?: React.ReactNode;
- }
-
- export const radioTickBoxPlugin = plugin(({ addComponents }) => {
- addComponents({
- '.radio-tick-box': {
- '& + label + label > :first-child > :first-child': {
- 'display': 'none',
- },
- '&:checked + label + label > :first-child > :first-child': {
- 'display': 'block',
- },
- },
- });
- });
-
- /**
- * Component for selecting a single value from an array of choices grouped by name.
- *
- * This component is displayed as a tick box, i.e. a typical radio button.
- */
- export const RadioTickBox = React.forwardRef<RadioTickBoxDerivedElement, RadioTickBoxProps>((
- {
- children,
- block = false as const,
- id: idProp,
- className,
- subtext,
- style,
- ...etcProps
- },
- forwardedRef,
- ) => {
- const id = useFallbackId(idProp);
-
- return (
- <div
- className={clsx(
- 'gap-x-4 flex-wrap',
- block && 'flex',
- !block && 'inline-flex align-center',
- className,
- )}
- style={style}
- data-testid="base"
- >
- <input
- {...etcProps}
- ref={forwardedRef}
- type="radio"
- id={id}
- className="sr-only peer/radio radio-tick-box"
- />
- <label
- htmlFor={id}
- className="peer/children order-2 cursor-pointer peer-disabled/radio:cursor-not-allowed"
- >
- <span
- data-testid="children"
- >
- {children}
- </span>
- </label>
- <label
- htmlFor={id}
- className={clsx(
- 'order-1 block rounded-full ring-secondary/50 overflow-hidden gap-4 leading-none select-none cursor-pointer',
- 'peer-focus/radio:outline-0 peer-focus/radio:ring-4 peer-focus/radio:ring-secondary/50',
- 'active:ring-tertiary/50 active:ring-4',
- 'peer-active/children:ring-tertiary/50 peer-active/children:ring-4 peer-active/children:text-tertiary',
- 'peer-disabled/radio:opacity-50 peer-disabled/radio:cursor-not-allowed peer-disabled/radio:ring-0',
- 'text-primary peer-disabled/radio:text-primary peer-focus/radio:text-secondary peer-checked/radio:text-tertiary active:text-tertiary',
- )}
- >
- <span
- className={clsx(
- 'w-6 h-6 block rounded-full border-2 p-0.5 box-border border-current',
- )}
- >
- <span
- className={clsx(
- 'w-full h-full rounded-full bg-current text-current',
- )}
- />
- </span>
- </label>
- {subtext && (
- <div
- className="block w-full text-xs pl-10 order-3"
- data-testid="subtext"
- >
- {subtext}
- </div>
- )}
- </div>
- );
- });
-
- RadioTickBox.displayName = 'RadioTickBox' as const;
-
- RadioTickBox.defaultProps = {
- block: false as const,
- subtext: undefined,
- };
|