Checkbox & Radio
Custom-styled checkbox and radio inputs with a checked-state icon, built without relying on default browser styling.
CheckboxRadio.jsx
'use client' import { useState } from 'react' import { Check } from 'lucide-react' export default function CheckboxRadio() { const [checked, setChecked] = useState({ a: true, b: false }) const [selected, setSelected] = useState('monthly') return ( <div className="p-4 flex flex-col gap-6"> {/* Checkboxes */} <div className="flex flex-col gap-3"> {[ { key: 'a', label: 'Email notifications' }, { key: 'b', label: 'Marketing updates' } ].map((item) => ( <label key={item.key} className="flex items-center gap-3 cursor-pointer select-none"> <div onClick={() => setChecked((c) => ({ ...c, [item.key]: !c[item.key] }))} className={`flex h-5 w-5 items-center justify-center rounded-[6px] border-2 transition-colors duration-200 ${checked[item.key] ? 'bg-[#1d1d1f] border-[#1d1d1f] dark:bg-white dark:border-white' : 'bg-transparent border-[#d0d0d0] dark:border-[#4c4c4c]'}`} > {checked[item.key] && <Check size={13} strokeWidth={3} className="text-white dark:text-[#1d1d1f]" />} </div> <span className="text-[14px] text-[#1d1d1f] dark:text-[#f5f5f7]">{item.label}</span> </label> ))} </div> {/* Radio buttons */} <div className="flex flex-col gap-3"> {[ { key: 'monthly', label: 'Billed monthly' }, { key: 'yearly', label: 'Billed yearly' } ].map((item) => ( <label key={item.key} className="flex items-center gap-3 cursor-pointer select-none"> <div onClick={() => setSelected(item.key)} className={`flex h-5 w-5 items-center justify-center rounded-full border-2 transition-colors duration-200 ${selected === item.key ? 'border-[#1d1d1f] dark:border-white' : 'border-[#d0d0d0] dark:border-[#4c4c4c]'}`} > {selected === item.key && <div className="h-[9px] w-[9px] rounded-full bg-[#1d1d1f] dark:bg-white" />} </div> <span className="text-[14px] text-[#1d1d1f] dark:text-[#f5f5f7]">{item.label}</span> </label> ))} </div> </div> ) }