GitHub

Command Palette

Search for a command to run...

RadioCard

(A) One-liner

RadioCard is a selectable card component providing "radio selection UI + card layout" in one. Used standalone, selection toggle (like checkbox) is possible, and when used inside RadioCardGroup, it operates with single selection (radio semantics).


(B) Installation (Track A / Track B)

Common prerequisite: unistyles side-effect import in app entry file is required.

  • Track A: import '@fleet-ui/local/core/unistyles';
  • Track B: import '@fleet-ui/core/unistyles';

Track A (CLI / local install)

Track A: add RadioCard
pnpm dlx @fleet-ui/cli add RadioCard
Track A: import
import { RadioCard, RadioCardGroup } from '@fleet-ui/local/components';

Track B (NPM package)

Track B: import
import { RadioCard, RadioCardGroup } from '@fleet-ui/components';

(D) Core Features & Usage

RadioCardGroup (single select)
import { RadioCard, RadioCardGroup } from '@fleet-ui/components';
 
export function Example() {
  return (
    <RadioCardGroup
      name="Shipping Method"
      defaultValue="standard"
      onValueChange={(v) => console.log(v)}
      gap="md"
    >
      <RadioCard
        value="standard"
        title="Standard Delivery"
        description="3-5 days"
      />
      <RadioCard
        value="express"
        title="Express Delivery"
        description="Next day arrival"
        selectedVariant="filled"
        selectedColorScheme="primary"
      />
    </RadioCardGroup>
  );
}

Inside group:

  • Pressing same card again doesn't deselect (radio).
  • Selection is managed by value string and passed via RadioCardGroup.onValueChange(value).

D-2. Standalone Usage: Selection Toggle (Caution)

Using RadioCard standalone enables toggle behavior with selected/defaultSelected/onSelect internally. This behavior is closer to "selection card (checkbox-like)" than "radio," so if you want single selection with multiple cards side by side, be sure to use RadioCardGroup.

D-3. Layout Slots

Content composition is separated into these slots:

  • header: Card top header area
  • footer: Card bottom footer area
  • media: Icon/image to left of title
  • left/right: Body (content) left/right slots

D-4. Style Override on Selection

  • selectedColorScheme: Change color scheme only when selected
  • selectedVariant: Change card variant only when selected

(E) Internal State / Shared Value / Animation

E-1. State Model (Priority)

RadioCard selection state is determined by this priority:

  1. Group: If RadioCardGroup context exists, uses groupContext.isSelected(value) (single selection)
  2. Controlled: If selected prop exists, uses that value
  3. Uncontrolled: Starts internal state with defaultSelected and toggles on tap

RadioCardGroup supports both controlled/uncontrolled.

  • controlled: Control with value
  • uncontrolled: defaultValue + internal internalValue

E-2. Animation

  • press-in/out: Scale/opacity spring (0.98/0.81/1)
  • Color transition: Gets background/border/title/description from variant-based colors and transitions with spring

(F) Accessibility

Group:

  • RadioCardGroup uses accessibilityRole="radiogroup".
  • Provides group label with name or accessibilityLabel.

Card:

  • RadioCard is accessibilityRole="radio"
  • accessibilityState={{ checked, disabled }}
  • Default label is accessibilityLabel || title

Internal indicator (Radio component) is treated as visual auxiliary element and hidden with accessible={false} to prevent duplicate reading.


(G) Props Table

Reference: Public types from packages/components/src/RadioCard/RadioCard.types.ts.

RadioCard — RadioCardProps

PropTypeRequiredDefaultDescriptionNotes
titlestringYes-Card titleAlso used as accessibility default label
descriptionstringNo-Description text
headerReactNodeNo-Top header slot
footerReactNodeNo-Bottom footer slot
mediaReactNodeNo-Media to left of title
leftReactNodeNo-Body left slot
rightReactNodeNo-Body right slot
valuestringYes-Group selection identifierRequired in group
selectedbooleanNo-Selection state (controlled, standalone)Ignored inside group
defaultSelectedbooleanNofalseInitial selection (uncontrolled, standalone)Ignored inside group
onSelect(selected: boolean) => voidNo-Selection toggle callback (standalone)Ignored inside group
colorSchemeItemColorSchemeNo'neutral'Card color scheme
variantItemVariantNo'outlined'Card variant
sizeItemSizeNo'md'Card size
roundedItemRoundedNo'md'Rounded
shadowItemShadowNo'none'Shadow
indicatorPosition'start' | 'end'No'end'Radio position
indicatorVariantRadioVariantNo'filled'Radio variant
selectedColorSchemeItemColorSchemeNo-Selection color scheme override
selectedVariantItemVariantNo-Selection variant override
disabledbooleanNofalseDisabledOR'd with group disabled
styleStyleProp<ViewStyle>No-Style override
accessibilityLabelstringNo-Accessibility labelDefault: title
testIDstringNo-Test identifier

RadioCardGroup — RadioCardGroupProps

PropTypeRequiredDefaultDescription
valuestringNo-Selection value (controlled)
defaultValuestringNo-Initial selection value (uncontrolled)
onValueChange(value: string) => voidNo-Selection change callback
namestringNo-Group name (a11y)
disabledbooleanNofalseGroup disabled
childrenReactNodeNo-RadioCard children
styleViewProps['style']No-Container style
gap'none' | 'sm' | 'md' | 'lg'No'md'Card gap