Selectable Card
A card-shaped button with controlled selected state, keyboard focus and pressed semantics.
Purpose
Use Selectable Card for a single card-shaped choice when the whole surface should act as one button and expose its selected state.
Card choices
Installation
With the Siteplane registry alias configured, add the component and import the installed source from your app.
CLI
pnpm dlx shadcn@4.16.1 add @siteplane/selectable-cardImport
import { SelectableCard } from "@/components/ui/selectable-card";Need the machine-readable source metadata? View registry JSON.
Usage
Selectable Card turns the whole surface into a selectable control while keeping button semantics.
"use client";
import { useState } from "react";
import { SelectableCard } from "@/components/ui/selectable-card";
export function Example() {
const [selected, setSelected] = useState("team");
return (
<>
<SelectableCard onClick={() => setSelected("team")} selected={selected === "team"}>Team workspace</SelectableCard>
<SelectableCard onClick={() => setSelected("personal")} selected={selected === "personal"}>Personal workspace</SelectableCard>
</>
);
}Examples
Selection always stays in the calling flow: control selected via state and onClick.
States
Plan choice
Compact choice
Density stays a className decision on the same primitive.
API Reference
The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.
SelectableCardrenders a button by default, accepts Base UI'srenderprop and exposes a controlledselectedboolean.- The component mirrors
selectedtodata-selectedandaria-pressed; update the value from the consumer's click handler. - Native button props such as
disabled,type, accessible naming and keyboard activation remain available.
Motion
Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.
- Selection, hover and focus use color, border and ring transitions without moving the card.
- Reduced motion requires no additional override because the component has no scale or translation animation.
Accessibility
- Keep the card as one semantic button with a clear accessible name.
- Do not nest buttons, links or other interactive controls inside a clickable Selectable Card.
aria-presseddescribes the selected state; do not replace it with color-only styling.
Implementation Guidance
- Use Radio Group for a mutually exclusive list with native radio semantics and Checkbox for independent multiple selection.
- Keep state controlled by the caller and preserve the button contract.
- Do not hand-build a clickable card with a non-focusable container.