@aegov/design-system-react
Version: 
A design system for the Government of the United Arab Emirates. Extending the original design system released as @aegov/design-system, this is the package specefically created for the ReactJs enviornment.
97 lines (91 loc) • 3.31 kB
JSX
import React from 'react';
import { Root, Thumb } from '@radix-ui/react-switch';
import { twMerge } from 'tailwind-merge';
import { z } from 'zod';
import { Moon, Sun } from '@phosphor-icons/react';
const ToggleSchema = z.object({
  checked: z.boolean().optional(),
  onCheckedChange: z.function().optional(),
  disabled: z.boolean().optional(),
  variant: z.enum(['default', 'success', 'mode', 'secondary']).optional(),
  label: z.string().optional(),
  className: z.string().optional(),
  checkedIcon: z.any().optional(),
  uncheckedIcon: z.any().optional(),
});
const Toggle = React.forwardRef((props, ref) => {
  const {
    checked,
    onCheckedChange,
    disabled,
    variant = 'default',
    label,
    className,
    checkedIcon,
    uncheckedIcon,
    ...rest
  } = ToggleSchema.parse(props);
  const variants = {
    default: {
      root: 'bg-aeblack-100 data-[state=checked]:bg-primary-300',
      thumb: 'bg-whitely-50 border border-aeblack-100 data-[state=checked]:border-primary-600',
    },
    success: {
      root: 'bg-aeblack-100 data-[state=checked]:bg-aegreen-300',
      thumb: 'bg-whitely-50 border border-aeblack-100 data-[state=checked]:border-aegreen-600',
    },
    secondary: {
      root: 'bg-aeblack-100 data-[state=checked]:bg-secondary-800',
      thumb: 'bg-whitely-50 border border-aeblack-100 data-[state=checked]:border-secondary-600',
    },
    mode: {
      root: 'bg-whitely-50 border border-aeblack-100 data-[state=checked]:bg-aeblack-950',
      thumb: 'bg-transparent border-transparent flex items-center justify-center',
    },
  };
  return (
    <label className={twMerge('relative inline-flex cursor-pointer items-center', className)}>
      <Root
        ref={ref}
        checked={checked}
        onCheckedChange={onCheckedChange}
        disabled={disabled}
        className={twMerge(
          'relative flex items-center h-4 w-10 cursor-pointer rounded-full outline-none transition-colors',
          'focus-visible:outline focus-visible:outline-offset-[3px] focus-visible:outline-primary-500',
          'disabled:cursor-not-allowed disabled:opacity-30',
          variant === 'mode' && 'h-6 w-12',
          variants[variant].root
        )}
        {...rest}
      >
        <Thumb
          className={twMerge(
            'absolute block h-5 w-5 rounded-full shadow transition-transform duration-300',
            'translate-x-0 data-[state=checked]:translate-x-6 rtl:data-[state=checked]:-translate-x-6',
            'top-1/2 -translate-y-1/2',
            variant === 'mode' && 'h-4 w-4 translate-x-1 rtl:-translate-x-1 data-[state=checked]:translate-x-7 rtl:data-[state=checked]:-translate-x-7',
            variants[variant].thumb
          )}
        >
          {checkedIcon || uncheckedIcon ? (
            checked ? checkedIcon : uncheckedIcon
          ) : variant === 'mode' ? (
            <>
              {checked ? (
                <Moon weight="fill" className="h-4 w-4 text-whitely-50" />
              ) : (
                <Sun weight="fill" className="h-4 w-4 text-aeblack-950" />
              )}
            </>
          ) : null}
        </Thumb>
      </Root>
      {label && (
        <span className="ms-3 text-sm">{label}</span>
      )}
    </label>
  );
});
Toggle.displayName = 'Toggle';
export default Toggle;