import { HStack, RadioCard } from "@chakra-ui/react"
const Demo = () => {
return (
<RadioCard.Root defaultValue="next">
<RadioCard.Label>Select framework</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ value: "next", title: "Next.js" },
{ value: "vite", title: "Vite" },
{ value: "astro", title: "Astro" },
]
Usage
import { RadioCard } from "@chakra-ui/react"
<RadioCard.Root>
<RadioCard.Label />
<RadioCard.Item>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemContent>
<RadioCard.ItemText />
<RadioCard.ItemDescription />
</RadioCard.ItemContent>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
</RadioCard.Root>
Examples
Description
Here's an example of how to add some further description to the radio card.
import { HStack, RadioCard } from "@chakra-ui/react"
const Demo = () => {
return (
<RadioCard.Root defaultValue="next">
<RadioCard.Label>Select framework</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemContent>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemDescription>
{item.description}
</RadioCard.ItemDescription>
</RadioCard.ItemContent>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ value: "next", title: "Next.js", description: "Best for apps" },
{ value: "vite", title: "Vite", description: "Best for SPAs" },
{ value: "astro", title: "Astro", description: "Best for static sites" },
]
Sizes
Pass the size
prop to the RadioCard.Root
component to change the size of the
radio card.
import { For, HStack, RadioCard, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="8">
<For each={["sm", "md", "lg"]}>
{(size) => (
<RadioCard.Root key={size} size={size} defaultValue="next">
<RadioCard.Label>size = ({size})</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)}
</For>
</Stack>
)
}
const items = [
{ value: "next", title: "Next.js" },
{ value: "vite", title: "Vite" },
]
Colors
Pass the colorPalette
prop to the RadioCard.Root
component to change the
color of the radio card.
import { For, HStack, RadioCard, Stack } from "@chakra-ui/react"
import { colorPalettes } from "compositions/lib/color-palettes"
const Demo = () => {
return (
<Stack gap="8">
<For each={colorPalettes}>
{(colorPalette) => (
<RadioCard.Root
key={colorPalette}
colorPalette={colorPalette}
defaultValue="next"
>
<RadioCard.Label>Select Framework</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)}
</For>
</Stack>
)
}
const items = [
{ value: "next", title: "Next.js" },
{ value: "vite", title: "Vite" },
]
Variants
Pass the variant
prop to the RadioCard.Root
component to change the visual
style of the radio card.
import { For, HStack, RadioCard, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="8">
<For each={["surface", "subtle", "outline", "solid"]}>
{(variant) => (
<RadioCard.Root
colorPalette="teal"
key={variant}
variant={variant}
defaultValue="next"
>
<RadioCard.Label>variant = ({variant})</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)}
</For>
</Stack>
)
}
const items = [
{ value: "next", title: "Next.js" },
{ value: "vite", title: "Vite" },
]
Icon
Render a custom icon inside the radio card by placing it within
RadioCard.ItemContent
.
import { HStack, Icon, RadioCard } from "@chakra-ui/react"
import { LuArrowRight, LuCircleOff, LuLock } from "react-icons/lu"
const Demo = () => {
return (
<RadioCard.Root defaultValue="next">
<RadioCard.Label>Select permission</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemContent>
<Icon size="xl" color="fg.muted" mb="2">
{item.icon}
</Icon>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemDescription>
{item.description}
</RadioCard.ItemDescription>
</RadioCard.ItemContent>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{
icon: <LuArrowRight />,
value: "allow",
title: "Allow",
description: "This user can access the system",
},
{
icon: <LuCircleOff />,
value: "deny",
title: "Deny",
description: "This user will be denied access to the system",
},
{
icon: <LuLock />,
value: "lock",
title: "Lock",
description: "This user will be locked out of the system",
},
]
Controlled
Pass the value
and onValueChange
props to the RadioCard.Root component to
control the selected radio card.
"use client"
import { HStack, RadioCard } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [value, setValue] = useState<string | null>("next")
return (
<RadioCard.Root value={value} onValueChange={(e) => setValue(e.value)}>
<RadioCard.Label>Select framework</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ value: "next", title: "Next.js" },
{ value: "vite", title: "Vite" },
{ value: "astro", title: "Astro" },
]
No Indicator
Here's an example of how to use the radio card without an indicator.
import { HStack, Icon, RadioCard } from "@chakra-ui/react"
import { RiAppleFill, RiBankCardFill, RiPaypalFill } from "react-icons/ri"
const Demo = () => {
return (
<RadioCard.Root
orientation="horizontal"
align="center"
justify="center"
maxW="lg"
defaultValue="paypal"
>
<RadioCard.Label>Payment method</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<Icon fontSize="2xl" color="fg.subtle">
{item.icon}
</Icon>
<RadioCard.ItemText ms="-4">{item.title}</RadioCard.ItemText>
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ value: "paypal", title: "Paypal", icon: <RiPaypalFill /> },
{ value: "apple-pay", title: "Apple Pay", icon: <RiAppleFill /> },
{ value: "card", title: "Card", icon: <RiBankCardFill /> },
]
No Indicator (Vertical)
Here's an example of a radio card with no indicator and content aligned vertically.
import { HStack, Icon, RadioCard } from "@chakra-ui/react"
import { RiAppleFill, RiBankCardFill, RiPaypalFill } from "react-icons/ri"
const Demo = () => {
return (
<RadioCard.Root
orientation="vertical"
align="center"
maxW="400px"
defaultValue="paypal"
>
<RadioCard.Label>Payment method</RadioCard.Label>
<HStack>
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<Icon fontSize="2xl" color="fg.muted">
{item.icon}
</Icon>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ value: "paypal", title: "Paypal", icon: <RiPaypalFill /> },
{ value: "apple-pay", title: "Apple Pay", icon: <RiAppleFill /> },
{ value: "card", title: "Card", icon: <RiBankCardFill /> },
]
Centered
Here's an example of a radio card with centered text.
import { HStack, Icon, RadioCard } from "@chakra-ui/react"
import { LuClock, LuDollarSign, LuTrendingUp } from "react-icons/lu"
const Demo = () => {
return (
<RadioCard.Root orientation="vertical" align="center" defaultValue="next">
<RadioCard.Label>Select contract type</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<Icon fontSize="2xl" color="fg.muted" mb="2">
{item.icon}
</Icon>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ icon: <LuDollarSign />, value: "fixed", title: "Fixed Rate" },
{ icon: <LuTrendingUp />, value: "milestone", title: "Milestone" },
{ icon: <LuClock />, value: "hourly", title: "Hourly" },
]
Composition
Here's an example of composing the RadioCard with the Group
component.
import { Group, RadioCard } from "@chakra-ui/react"
const Demo = () => {
return (
<RadioCard.Root defaultValue="next" gap="4" maxW="sm">
<RadioCard.Label>How well do you know React?</RadioCard.Label>
<Group attached orientation="vertical">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value} width="full">
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemIndicator />
<RadioCard.ItemContent>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemDescription>
{item.description}
</RadioCard.ItemDescription>
</RadioCard.ItemContent>
</RadioCard.ItemControl>
</RadioCard.Item>
))}
</Group>
</RadioCard.Root>
)
}
const items = [
{
value: "advanced",
title: "Advanced",
description: "I love complex things",
},
{
value: "professional",
title: "Professional",
description: "I can hack simple things",
},
{
value: "beginner",
title: "Beginner",
description: "I don't write code",
},
]
Addon
Use the RadioCard.ItemAddon
component to add metadata to the radio card.
import { HStack, RadioCard } from "@chakra-ui/react"
const Demo = () => {
return (
<RadioCard.Root defaultValue="next">
<RadioCard.Label>Select framework</RadioCard.Label>
<HStack align="stretch">
{items.map((item) => (
<RadioCard.Item key={item.value} value={item.value}>
<RadioCard.ItemHiddenInput />
<RadioCard.ItemControl>
<RadioCard.ItemContent>
<RadioCard.ItemText>{item.title}</RadioCard.ItemText>
<RadioCard.ItemDescription>
{item.description}
</RadioCard.ItemDescription>
</RadioCard.ItemContent>
<RadioCard.ItemIndicator />
</RadioCard.ItemControl>
<RadioCard.ItemAddon>Some addon text</RadioCard.ItemAddon>
</RadioCard.Item>
))}
</HStack>
</RadioCard.Root>
)
}
const items = [
{ value: "next", title: "Next.js", description: "Best for apps" },
{ value: "vite", title: "Vite", description: "Best for SPAs" },
{ value: "astro", title: "Astro", description: "Best for static sites" },
]
Closed Component
Here's how to setup the Radio card for a closed component composition.
import { RadioCard } from "@chakra-ui/react"
import * as React from "react"
interface RadioCardItemProps extends RadioCard.ItemProps {
icon?: React.ReactElement
label?: React.ReactNode
description?: React.ReactNode
addon?: React.ReactNode
indicator?: React.ReactNode | null
indicatorPlacement?: "start" | "end" | "inside"
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
}
export const RadioCardItem = React.forwardRef<
HTMLInputElement,
RadioCardItemProps
>(function RadioCardItem(props, ref) {
const {
inputProps,
label,
description,
addon,
icon,
indicator = <RadioCard.ItemIndicator />,
indicatorPlacement = "end",
...rest
} = props
const hasContent = label || description || icon
const ContentWrapper = indicator ? RadioCard.ItemContent : React.Fragment
return (
<RadioCard.Item {...rest}>
<RadioCard.ItemHiddenInput ref={ref} {...inputProps} />
<RadioCard.ItemControl>
{indicatorPlacement === "start" && indicator}
{hasContent && (
<ContentWrapper>
{icon}
{label && <RadioCard.ItemText>{label}</RadioCard.ItemText>}
{description && (
<RadioCard.ItemDescription>
{description}
</RadioCard.ItemDescription>
)}
{indicatorPlacement === "inside" && indicator}
</ContentWrapper>
)}
{indicatorPlacement === "end" && indicator}
</RadioCard.ItemControl>
{addon && <RadioCard.ItemAddon>{addon}</RadioCard.ItemAddon>}
</RadioCard.Item>
)
})
export const RadioCardRoot = RadioCard.Root
export const RadioCardLabel = RadioCard.Label
export const RadioCardItemIndicator = RadioCard.ItemIndicator
If you want to automatically add the closed component to your project, run the command:
npx @chakra-ui/cli snippet add radio-card
Here's how to use the it
<RadioCardRoot>
<RadioCardLabel />
<RadioCardItem />
</RadioCardRoot>
Props
Root
Prop | Default | Type |
---|---|---|
orientation | 'horizontal' | 'vertical' | 'horizontal' The orientation of the component |
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' The color palette of the component |
size | 'md' | 'sm' | 'md' | 'lg' The size of the component |
variant | 'outline' | 'surface' | 'subtle' | 'outline' | 'solid' The variant of the component |
align | 'start' | 'start' | 'end' | 'center' The align of the component |
as | React.ElementType The underlying element to render. | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | boolean Whether to remove the component's style. | |
defaultValue | string The initial value of the checked radio when rendered. Use when you don't need to control the value of the radio group. | |
disabled | boolean If `true`, the radio group will be disabled | |
form | string The associate form of the underlying input. | |
id | string The unique identifier of the machine. | |
ids | Partial<{
root: string
label: string
indicator: string
item: (value: string) => string
itemLabel: (value: string) => string
itemControl: (value: string) => string
itemHiddenInput: (value: string) => string
}> The ids of the elements in the radio. Useful for composition. | |
name | string The name of the input fields in the radio (Useful for form submission). | |
onValueChange | (details: ValueChangeDetails) => void Function called once a radio is checked | |
readOnly | boolean Whether the checkbox is read-only | |
value | string The controlled value of the radio group | |
justify | 'start' | 'end' | 'center' The justify of the component |
Explorer
Explore the Radio Card
component parts interactively. Click on parts in the
sidebar to highlight them in the preview.
Component Anatomy
Hover to highlight, click to select parts
root
label
item
itemText
itemControl
indicator
itemAddon
itemIndicator
itemContent
itemDescription
radio-card.recipe.ts