Finalize checkbox presentation/behavior

This commit is contained in:
Sam Becker 2025-03-15 13:24:53 -05:00
parent a6228ce888
commit f9b6d7f485
2 changed files with 32 additions and 20 deletions

View File

@ -1,5 +1,5 @@
import clsx from 'clsx/lite';
import { InputHTMLAttributes, ReactNode, Ref } from 'react';
import { InputHTMLAttributes, ReactNode, RefObject } from 'react';
import { ImCheckmark } from 'react-icons/im';
const boxStyles = clsx(
@ -14,18 +14,21 @@ export default function Checkbox({
accessory,
type: _type,
...props
}: InputHTMLAttributes<HTMLInputElement> & {
ref?: Ref<HTMLInputElement>
}: Omit<InputHTMLAttributes<HTMLInputElement>, 'ref'> & {
ref?: RefObject<HTMLInputElement | null>
accessory?: ReactNode
}) {
return (
<span className={clsx(
'relative inline-flex items-center justify-center',
'size-5',
props.readOnly
? 'cursor-not-allowed'
: 'group-has-active:opacity-70',
)}>
<span
className={clsx(
'relative inline-flex items-center justify-center',
'size-5',
props.readOnly
? 'cursor-not-allowed'
: 'group-has-active:opacity-70',
)}
onClick={() => ref?.current?.click()}
>
{accessory
? accessory
: props.checked
@ -34,12 +37,15 @@ export default function Checkbox({
'border-transparent',
props.readOnly
? 'bg-gray-300 dark:bg-gray-700'
: 'bg-blue-600',
: 'bg-black',
)}>
<ImCheckmark className={clsx(
'text-white text-[11px]',
props.readOnly && 'dark:text-gray-400',
)} />
<ImCheckmark
size={12}
className={clsx(
'text-white',
props.readOnly && 'dark:text-gray-400',
)}
/>
</span>
: <span className={clsx(
boxStyles,
@ -50,7 +56,7 @@ export default function Checkbox({
ref={ref}
type="checkbox"
className={clsx(
'absolute inset-0 invisible',
'absolute inset-0 opacity-0! size-5',
className,
)}
{...props}

View File

@ -1,6 +1,6 @@
'use client';
import { Ref, InputHTMLAttributes } from 'react';
import { InputHTMLAttributes, useRef, RefObject } from 'react';
import { useFormStatus } from 'react-dom';
import Spinner from './Spinner';
import { clsx } from 'clsx/lite';
@ -31,7 +31,7 @@ export default function FieldSetWithStatus({
spellCheck,
capitalize,
type = 'text',
inputRef,
inputRef: inputRefProp,
accessory,
hideLabel,
}: {
@ -55,10 +55,14 @@ export default function FieldSetWithStatus({
spellCheck?: boolean
capitalize?: boolean
type?: FieldSetType
inputRef?: Ref<HTMLInputElement>
inputRef?: RefObject<HTMLInputElement | null>
accessory?: React.ReactNode
hideLabel?: boolean
}) {
const inputRefInternal = useRef<HTMLInputElement>(null);
const inputRef = inputRefProp ?? inputRefInternal;
const id = _id || parameterize(label);
const { pending } = useFormStatus();
@ -68,7 +72,9 @@ export default function FieldSetWithStatus({
name: id,
type,
value,
checked: type === 'checkbox' ? value === 'true' : undefined,
checked: type === 'checkbox'
? value === 'true' ? true : false
: undefined,
placeholder,
onChange: e => onChange?.(type === 'checkbox'
? e.target.value === 'true' ? 'false' : 'true'