Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsForm Blocks

Radio

A form control that lets users select exactly one option from a group. Five sizes, five intents, label/description/error patterns, RadioGroup compound component, and RadioCard full-surface variant.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { Radio, RadioGroup } from "@tessinaui/ui";
{/* Uncontrolled group */}
<RadioGroup defaultValue="email" label="Contact method">
  <Radio value="email" label="Email" />
  <Radio value="sms"   label="SMS"   />
  <Radio value="phone" label="Phone" />
</RadioGroup>

{/* Controlled group */}
<RadioGroup value={method} onValueChange={setMethod} label="Contact method">
  <Radio value="email" label="Email" />
  <Radio value="sms"   label="SMS"   />
</RadioGroup>

{/* With error */}
<RadioGroup required errorMessage="Please select an option.">
  <Radio value="a" label="Option A" intent="error" />
  <Radio value="b" label="Option B" intent="error" />
</RadioGroup>

Showcase

API Reference

Radio props

PropTypeDefaultDescription
valuestring""Value submitted with the form (required for group behavior)
variant"filled" | "outline""filled"Unchecked style: filled has bg-secondary, outline is transparent
size"xs" | "sm" | "md" | "lg" | "xl""md"Visual size of the radio indicator
intent"none" | "error" | "warning" | "success" | "info""none"Semantic color for ring and dot
disabledbooleanfalsePrevents interaction
readOnlybooleanfalsePrevents interaction, accessible
requiredbooleanfalseHTML required + asterisk on label
labelstring—Text label rendered beside the radio
descriptionstring—Helper text below the label
errorMessagestring—Error text (overrides description, adds AlertCircle)
labelPosition"left" | "right""right"Which side the label appears on
dir"ltr" | "rtl"—Text direction for the wrapper
namestring—Input name for form submission
classNamestring—Extra classes on the wrapper <div>

All other native attributes are forwarded to the underlying <span> (Base UI).

RadioGroup props

PropTypeDefaultDescription
valuestring—Controlled selected value
defaultValuestring—Uncontrolled initial value
onValueChange(value: string) => void—Change handler
disabledbooleanfalseDisables all radios in the group
orientation"vertical" | "horizontal""vertical"Stack direction
variant"filled" | "outline""filled"Propagated to child Radios
sizeRadioSize"md"Propagated to child Radios
intentRadioIntent"none"Propagated to child Radios
labelstring—Group legend
descriptionstring—Helper text below legend
errorMessagestring—Error text for the group
requiredbooleanfalseAsterisk on group legend
dir"ltr" | "rtl"—Text direction for the group wrapper

RadioCard props

PropTypeDefaultDescription
valuestring""Value submitted with the form
titlestring—Card title (required)
descriptionstring—Optional description below the title
iconReactNode—Leading icon rendered left of the text
sizeRadioSize"md"Size of the radio indicator
intentRadioIntent"none"Semantic color
disabledbooleanfalsePrevents interaction
dir"ltr" | "rtl"—Text direction

RadioCardGroup props

PropTypeDefaultDescription
valuestring—Controlled selected value
defaultValuestring—Uncontrolled initial value
onValueChange(value: string) => void—Change handler
columns1 | 2 | 3 | 42Number of card columns
sizeRadioSize"md"Propagated to child RadioCards
intentRadioIntent"none"Propagated to child RadioCards
disabledbooleanfalseDisables all cards
labelstring—Group legend
descriptionstring—Helper text
errorMessagestring—Error text for the group

States

StateVisual
UnselectedEmpty ring with border
SelectedRing + filled inner dot
Disabled unselectedMuted empty ring
Disabled selectedMuted ring + muted dot
FocusRing outline (2px)
Hover (unselected)Darker border
Hover (selected)Slightly darker border

Sizes

SizeRingDot
xs14×14 px6×6 px
sm16×16 px8×8 px
md20×20 px10×10 px
lg24×24 px12×12 px
xl28×28 px14×14 px

Intents

IntentUnselected borderSelected ring/dot
noneborder-borderborder-primary / bg-primary
errorborder-errorborder-error / bg-error
warningborder-warningborder-warning / bg-warning
successborder-successborder-success / bg-success
infoborder-infoborder-info / bg-info

Accessibility

  • Hidden <input type="radio"> rendered by Base UI — native form semantics
  • Arrow keys navigate within a RadioGroup (standard radio group behavior)
  • aria-invalid set on group when errorMessage is present
  • aria-describedby links error messages to their respective controls
  • Required: aria-required + native required attribute on hidden input
  • Focus ring visible at all sizes — complies with WCAG 2.1 AA (3:1 contrast)
  • Group rendered as <fieldset> + <legend> for screen reader context

Checkbox

A form control that lets users select one or more options. Supports checked, unchecked, and indeterminate states. Five sizes, five intents, label/description/error patterns, and a CheckboxGroup compound component with select-all support.

Switch

A toggle control that allows users to turn a setting on or off

On this page

PlaygroundInstallationUsageShowcaseAPI ReferenceRadio propsRadioGroup propsRadioCard propsRadioCardGroup propsStatesSizesIntentsAccessibility