Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Inputs

Checkbox

Inputs

Checkbox React component for Tailwind CSS v4

CalendarColor Picker
Live props
Field
label
description
error
required
invalid
disabled
readOnly
State
defaultChecked
Appearance
size
tone
color
radius
variant
Layout
labelPosition
Behavior
name
Code
import { Checkbox } from "@/components/ui/checkbox"

<Checkbox />
  1. Home
  2. Components
  3. Inputs
  4. Checkbox
Free

Checkbox React component for Tailwind CSS v4

v1.0.1·Updated in 1.9.0

A React checkbox that is on, off or mixed, with a check that draws itself, full-row labels, cards, and groups with select all.

Click the box, its label or its description and the check draws itself on a quick spring; uncheck it and the stroke pulls back faster. While you press, the box dips a little, and with a mouse its border darkens on hover. Tab reaches every box and Space toggles it (Enter does not, as the ARIA pattern says); an indeterminate box turns checked on the next press. A link inside the label opens without toggling. Press Place order with the terms unchecked and the error slides in under the row; checking the box clears it. Cards take a ring in the tone when checked and dip slightly while pressed. In a group, Select all checks every enabled option and shows a dash while only some are checked (it turns checked once every enabled option is); with a maximum, the remaining options disable once you reach it. On a phone every row is at least 44px tall and the whole row is the target, and with reduced motion the check appears without drawing and nothing dips.

Checkbox is a free React component in the React input components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add checkbox, together with Field, useControllableState, Motion presets, Tones and UIProvider and the npm packages @radix-ui/react-checkbox and motion.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add checkbox

Usage

Import Checkbox from @/components/ui/checkbox.

import { useState } from "react"
import { Checkbox, CheckboxGroup } from "@/components/ui/checkbox"

const AMENITIES = [
  { value: "parking", label: "Parking" },
  { value: "balcony", label: "Balcony" },
  { value: "elevator", label: "Elevator" },
  { value: "laundry", label: "In-unit laundry" },
]

export function OrderConsent({ showError }: { showError: boolean }) {
  const [accepted, setAccepted] = useState(false)
  const [amenities, setAmenities] = useState<string[]>(["parking"])
  return (
    <form className="flex flex-col gap-4">
      <Checkbox
        name="terms"
        required
        checked={accepted}
        onCheckedChange={(checked) => setAccepted(checked === true)}
        label="I agree to the Terms and conditions"
        error={showError && !accepted ? "You need to accept the terms." : undefined}
      />
      <CheckboxGroup
        label="Amenities"
        name="amenities"
        columns={2}
        options={AMENITIES}
        value={amenities}
        onValueChange={setAmenities}
      />
    </form>
  )
}

Props

  • labeldefault ""
    ReactNode

    Text beside the box. The whole row is one <label>, so clicking the text, the description or the empty space toggles the box. A link inside it opens without toggling.

  • descriptiondefault ""
    ReactNode

    A second line under the label, in the muted caption style. It is kept out of the box's name and linked with aria-describedby, so screen readers read it after the label.

  • errordefault ""
    ReactNode

    A message under the row, lined up with the label, that slides in and marks the box invalid (red border, aria-invalid). "", false and null are no error. A box without a label only turns red; wrap it in a Field to show the text.

  • requireddefault false
    boolean

    Shows the red mark after the label, sets aria-required, and inside a native form blocks submission while unchecked (through Radix's hidden input).

  • invaliddefault false
    boolean

    The red border and aria-invalid without a message, for forms that show errors elsewhere. Inherits from a parent Field.

  • disableddefault false
    boolean

    Dims the row to 50% and blocks it. A disabled Field or FieldGroup around it disables it too.

  • readOnlydefault false
    boolean

    Shows the value but ignores clicks and Space, with no hover or press feedback; the box keeps focus and sets aria-readonly.

  • defaultCheckeddefault false
    boolean | "indeterminate"

    The starting state while uncontrolled: true, false or "indeterminate" (a dash, aria-checked="mixed").

  • checked
    boolean | "indeterminate"

    The state while controlled. Pair it with onCheckedChange.

  • onCheckedChange
    (checked: boolean | "indeterminate") => void

    Called with the next state. Clicking an indeterminate box makes it true, like Radix.

  • sizedefault "md"
    "sm" | "md" | "lg"

    Box 16 / 18 / 20px with a 12 / 14 / 16px check and a 13 / 14 / 15px label. The box centers on the label's first line at every size.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The checked fill (and the card ring and icon tile). neutral is black in light mode and white in dark mode; keep brand for the one place it means something.

  • colordefault ""
    string

    Any CSS color. Replaces the tone; the check turns black or white by the color's lightness. Leave empty to use the tone.

  • radiusdefault "md"
    "none" | "sm" | "md" | "lg" | "full"

    Box corners, scaled with the size: md is 4 / 5 / 6px, full makes a round checkbox.

  • variantdefault "default"
    "default" | "card"

    card turns the row into a soft-filled tile with the box at the top end, an optional icon tile, and a ring in the tone when checked. For rich choices like paid extras.

  • labelPositiondefault "end"
    "end" | "start"

    start puts the label first and the box at the end of a full-width row, like a settings list. Cards ignore it.

  • icon
    ReactNode

    Cards: the leading icon in a 40px tile that takes the tone when checked. Rows: a thumbnail or avatar between the box and the text (the row then centers).

  • namedefault ""
    string

    Form field name. Inside a <form> Radix renders a hidden input that submits value while checked and returns to its first state when the form resets. The playground sits in a real form.

  • valuedefault "on"
    string

    What the form submits while the box is checked.

  • id
    string

    The box's id. Defaults to useId(); inside a Field the Field's id wins, so its label toggles the box.

  • classNames
    Partial<Record<"field" | "box" | "indicator" | "content" | "label" | "description" | "error" | "icon", string>>

    Extra classes for the parts: field is the label row (or the card), box the button, indicator the check svg. Padding for list rows goes on field so the padding stays clickable.

  • className
    string

    Classes for the outermost element: the wrapper around the row and its message, or the box itself when there is no label. ref and every other prop (aria-*, data-*, onBlur, form) go to the box, a <button role="checkbox">, so form libraries can focus it.

Parts

  • CheckboxGroup

    component

    A list of options with one label (role="group"). options: { value, label, description?, icon?, disabled? }[]; value / defaultValue / onValueChange (string[], kept in the options' order); label, description, error, required, invalid, disabled, readOnly; orientation ("vertical" | "horizontal", rows wrap); columns (1 | 2 | 3 | 4, one on phones); variant, size, tone, color, radius, labelPosition for every box; selectAll and selectAllLabel ("Select all"); max (0 = no limit) with maxLabel (n => `Choose up to ${n}`); name (every checked box submits its value, FormData.getAll(name)); fieldProps; classNames (group, all, option, box, indicator, icon, content, optionLabel, optionDescription plus the Field parts). Props: CheckboxGroupProps.

  • CheckboxIndicator

    component

    The box alone, aria-hidden, with the same look and animation but no behavior: checked, size, tone, color, radius, invalid, disabled. For listbox rows (role="option" must not hold a real checkbox) and table cells that own the state. Props: CheckboxIndicatorProps.

  • CheckboxOption

    type

    One option of CheckboxGroup: { value, label, description?, icon?, disabled? }.

Examples

Group in two columns

CheckboxGroup with a label and a name: every checked box submits its value, shown below as form data.

Cards with prices

variant="card" with icon tiles in the brand tone. The ring and the tile take the tone; the total follows in dollars.

Select all

selectAll adds a row that shows a dash while some are checked. Rows with a thumbnail center; delete the selection to see the list update.

Maximum choices

max={3}: once three are checked the rest disable, and maxLabel explains why.

Sizes, tones and radius

16, 18 and 20px boxes, every tone, a custom color, round and square corners, and the aria-hidden CheckboxIndicator for listbox rows.

Settings list

labelPosition="start" rows inside a list group: the whole row is the target, padding goes on classNames.field.

Disabled, read-only and invalid

Dimmed, locked and red states; the last one shows its error until you check it.

Dependencies

@radix-ui/react-checkboxmotionfielduse-controllable-statemotiontonesui-config

Files

  • components/ui/checkbox.tsx

FAQ

Is the React Checkbox component free?

Yes. The source is free and needs no account: copy it from the Code tab or install it with the CLI.

How do I install Checkbox?

Run npx wingo-ui@latest add checkbox. It also adds the Wingo UI items it builds on (Field, useControllableState, Motion presets, Tones and UIProvider) and the npm packages @radix-ui/react-checkbox and motion. With shadcn, run npx shadcn@latest add https://wingo-ui.com/r/checkbox.json.

How does Checkbox behave on phones?

On a phone every row is at least 44px tall and the whole row is the target, and with reduced motion the check appears without drawing and nothing dips.

See also

FieldRadio GroupSwitchToggleCardToneslib

Used in

Login PageFile managerCheckout stepsCSV ViewerData TableFilter panelListboxSchema BuilderFile ListTree ViewEditable GridList

and 8 more.

More React input components

ComboboxCountry SelectCron PickerCurrency InputDate PickerDate Time Picker
All 40 React input components

Articles using this component

  • React Multi Select: Search, Chips, Select All and Mobile

    Component guides · Oct 16, 2026 · 10 min read

  • Minimum Touch Target Size: WCAG, iOS, Android and Tailwind

    Mobile UI in React · Oct 9, 2026 · 11 min read

  • React Form Components: Accessible Fields, Zod and Mobile

    Component guides · Oct 9, 2026 · 26 min read

PreviousCalendarNext Color Picker

Checkout

Step 3 of 3

Linus city bike

Delivery in 1-2 days

$1,269.99