EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
Card·component·@astryxdesign/core

Selectable Card

A card that toggles between selected and unselected states with an accent border. For navigation use ClickableCard.

Open in Playground @astryxdesign/core/SelectableCard

Showcases and examples

3 documented examples

Selectable Card

A plan picker with single-select radio behavior. Cards show an accent border when selected.

Preview loads on approachPreview loads on approach
Exact source · selectable-card-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {useState} from 'react';
import {SelectableCard} from '@astryxdesign/core/SelectableCard';
import {Stack} from '@astryxdesign/core/Layout';
import {Text, Heading} from '@astryxdesign/core/Text';

const plans = [
  {id: 'basic', name: 'Basic', price: '$9/mo', desc: 'For individuals'},
  {id: 'pro', name: 'Pro', price: '$29/mo', desc: 'For small teams'},
  {
    id: 'enterprise',
    name: 'Enterprise',
    price: '$99/mo',
    desc: 'For organizations',
  },
];

export default function SelectableCardShowcase() {
  const [selected, setSelected] = useState<string | null>('pro');

  return (
    <Stack direction="horizontal" gap={3}>
      {plans.map(plan => (
        <SelectableCard
          key={plan.id}
          label={plan.name}
          isSelected={selected === plan.id}
          onChange={() => setSelected(plan.id)}
          width={180}>
          <Stack direction="vertical" gap={1}>
            <Heading level={4}>{plan.name}</Heading>
            <Text type="large" weight="bold">
              {plan.price}
            </Text>
            <Text type="supporting" color="secondary">
              {plan.desc}
            </Text>
          </Stack>
        </SelectableCard>
      ))}
    </Stack>
  );
}

Usage

A card that toggles between selected and unselected states with an accent border. For navigation use ClickableCard.

  • Use for plan pickers, filter chips, or option grids.
  • For single-select track one ID; for multi-select use a Set.
  • When focused, toggle selection with Space or Enter.
  • Use for navigation; use ClickableCard for that.

Typed props

PropType and behavior
labelstring · required
Accessibility label.
isSelectedboolean · required
Controlled selection state.
onChange(isSelected: boolean) => void · required
Called when toggled.
isDisabledboolean · default false
Disables the card.
childrenReactNode
Card content.
padding0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 · default 4
Inner padding.
variant'default' | 'transparent' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow' · default 'default'
Background color variant.
elevation'none' | 'low' | 'med' | 'high' · default 'none'
Resting shadow depth. The selection ring composes on top, so a selected card keeps its shadow.
widthSizeValue
Card width.
heightSizeValue
Card height.
maxWidthSizeValue
Maximum card width.
xstyleStyleXStyles
StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value, not an inline style object like style={{}}.

Anatomy

Container · required

Interactive div with accent border on selection.

Content · required

Children rendered inside the card.

Theming

Container theming is enabled.

Targets

astryx-selectable-card

Visual props: selected, variant

Variables

--selectable-card-ring-color

Colour of the selection ring drawn for a variant a theme added. The built-in variants each ring in their own border token and ignore this; a theme that adds a variant sets it in the same rule as that variant's backgroundColor, because no token the component could pick is guaranteed to contrast with a fill it cannot know.

Default: var(--color-accent)