Checkbox
nexvyn/checkboxFreeComponent
A checkbox with drawn check animation, indeterminate state, and hidden native input for forms.
Live preview
live · rendered by the registry
Rendered by nexvyn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.nexvyn.dev/r/checkbox.jsonSource
1'use client'23import {4 cloneElement,5 forwardRef,6 isValidElement,7 useCallback,8 useId,9 useState,10 type ReactNode,11} from 'react'12import { motion, useReducedMotion } from 'motion/react'13import { cn } from '@/lib/utils'14import { springs } from '@/lib/motion-tokens'1516export type CheckedState = boolean | 'indeterminate'1718export interface CheckboxProps {19 id?: string20 checked?: CheckedState21 defaultChecked?: boolean22 onCheckedChange?: (checked: CheckedState) => void23 name?: string24 disabled?: boolean25 required?: boolean26 'aria-invalid'?: boolean | 'true' | 'false' | 'grammar' | 'spelling'27 'aria-label'?: string28 'aria-labelledby'?: string29 'aria-describedby'?: string30 className?: string31 value?: string32}3334export interface CheckboxFieldProps {35 label: string36 description?: string37 strikeThrough?: boolean38 className?: string39 children: ReactNode40}4142function useControlledChecked(43 controlledValue: CheckedState | undefined,44 defaultValue: boolean | undefined,45 onChange: ((checked: CheckedState) => void) | undefined,46): [CheckedState, (next: CheckedState) => void] {47 const [internal, setInternal] = useState<CheckedState>(defaultValue ?? false)48 const isControlled = controlledValue !== undefined49 const value = isControlled ? controlledValue : internal5051 const setValue = useCallback(52 (next: CheckedState) => {53 if (!isControlled) setInternal(next)54 onChange?.(next)55 },56 [isControlled, onChange],57 )5859 return [value, setValue]60}6162const CHECK_PATH = 'M3.5 8.5L7 12L12.5 5.5'63const DASH_PATH = 'M4 8L12 8'6465function CheckGlyph({ state, animate }: { state: CheckedState; animate: boolean }) {66 const reduceMotion = useReducedMotion()67 const isChecked = state === true68 const isIndeterminate = state === 'indeterminate'69 const shouldShow = isChecked || isIndeterminate7071 if (!shouldShow) return null7273 const path = isIndeterminate ? DASH_PATH : CHECK_PATH74 const shouldAnimate = animate && !reduceMotion7576 return (77 <svg viewBox="0 0 16 16" fill="none" className="absolute inset-0 size-full" aria-hidden="true">78 <motion.path79 d={path}80 stroke="currentColor"81 strokeWidth={2}82 strokeLinecap="round"83 strokeLinejoin="round"84 initial={shouldAnimate ? { pathLength: 0, opacity: 0 } : { pathLength: 1, opacity: 1 }}85 animate={{ pathLength: 1, opacity: 1 }}86 exit={shouldAnimate ? { pathLength: 0, opacity: 0 } : undefined}87// … truncated
What it pulls in
npm packages
Files it writes
More from nexvyn
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | nexvyn | Components | Free | 1 dep | |
| Action Buttonaction-button | nexvyn | Components | Free | 3 deps · 4 files | |
| Adaptive Actionsadaptive-actions | nexvyn | Components | Free | 1 dep | |
| AI Inputai-input | nexvyn | Components | Free | 1 dep · 2 files | |
| Badgebadge | nexvyn | Components | Free | 2 deps · 2 files | |
| Bars Themebars-theme | nexvyn | Components | Free | 1 dep · 3 files | |
| Bounce Sidebarbounce-sidebar | nexvyn | Components | Free | 1 dep · 2 files | |
| Breadcrumbsbreadcrumbs | nexvyn | Components | Free | 1 dep · 2 files |
