Radio Group
Allows single selection from multiple options.
import { RadioGroup } from '~/components/ui/radio-group'
export const Demo = (props: RadioGroup.RootProps) => {
const options = [
{ id: 'react', label: 'React' },
{ id: 'solid', label: 'Solid' },
{ id: 'svelte', label: 'Svelte' },
{ id: 'vue', label: 'Vue' },
]
return (
<RadioGroup.Root defaultValue="react" {...props}>
{options.map((option) => (
<RadioGroup.Item key={option.id} value={option.id} disabled={option.id === 'svelte'}>
<RadioGroup.ItemControl />
<RadioGroup.ItemText>{option.label}</RadioGroup.ItemText>
<RadioGroup.ItemHiddenInput />
</RadioGroup.Item>
))}
</RadioGroup.Root>
)
}
import { For } from 'solid-js'
import { RadioGroup } from '~/components/ui/radio-group'
export const Demo = (props: RadioGroup.RootProps) => {
const options = [
{ id: 'react', label: 'React' },
{ id: 'solid', label: 'Solid' },
{ id: 'svelte', label: 'Svelte' },
{ id: 'vue', label: 'Vue' },
]
return (
<RadioGroup.Root defaultValue="react" {...props}>
<For each={options}>
{(option) => (
<RadioGroup.Item value={option.id} disabled={option.id === 'svelte'}>
<RadioGroup.ItemControl />
<RadioGroup.ItemText>{option.label}</RadioGroup.ItemText>
<RadioGroup.ItemHiddenInput />
</RadioGroup.Item>
)}
</For>
</RadioGroup.Root>
)
}
Usage
import { RadioGroup } from '~/components/ui/radio-group'
Installation
npx @park-ui/cli components add radio-group
1
Add Styled Primitive
Copy the code snippet below into ~/components/ui/styled/radio-group.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { RadioGroup } from '@ark-ui/react/radio-group'
import { type RadioGroupVariantProps, radioGroup } from 'styled-system/recipes'
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(radioGroup)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
HTMLDivElement,
Assign<Assign<HTMLStyledProps<'div'>, RadioGroup.RootProviderBaseProps>, RadioGroupVariantProps>
>(RadioGroup.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
HTMLDivElement,
Assign<Assign<HTMLStyledProps<'div'>, RadioGroup.RootBaseProps>, RadioGroupVariantProps>
>(RadioGroup.Root, 'root')
export const Indicator = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, RadioGroup.IndicatorBaseProps>
>(RadioGroup.Indicator, 'indicator')
export const ItemControl = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, RadioGroup.ItemControlBaseProps>
>(RadioGroup.ItemControl, 'itemControl')
export const Item = withContext<
HTMLLabelElement,
Assign<HTMLStyledProps<'label'>, RadioGroup.ItemBaseProps>
>(RadioGroup.Item, 'item')
export const ItemText = withContext<
HTMLSpanElement,
Assign<HTMLStyledProps<'span'>, RadioGroup.ItemTextBaseProps>
>(RadioGroup.ItemText, 'itemText')
export const Label = withContext<
HTMLLabelElement,
Assign<HTMLStyledProps<'label'>, RadioGroup.LabelBaseProps>
>(RadioGroup.Label, 'label')
export {
RadioGroupContext as Context,
RadioGroupItemHiddenInput as ItemHiddenInput,
} from '@ark-ui/react/radio-group'
import { type Assign, RadioGroup } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { type RadioGroupVariantProps, radioGroup } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(radioGroup)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
Assign<Assign<HTMLStyledProps<'div'>, RadioGroup.RootProviderBaseProps>, RadioGroupVariantProps>
>(RadioGroup.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
Assign<Assign<HTMLStyledProps<'div'>, RadioGroup.RootBaseProps>, RadioGroupVariantProps>
>(RadioGroup.Root, 'root')
export const Indicator = withContext<Assign<HTMLStyledProps<'div'>, RadioGroup.IndicatorBaseProps>>(
RadioGroup.Indicator,
'indicator',
)
export const ItemControl = withContext<
Assign<HTMLStyledProps<'div'>, RadioGroup.ItemControlBaseProps>
>(RadioGroup.ItemControl, 'itemControl')
export const Item = withContext<Assign<HTMLStyledProps<'label'>, RadioGroup.ItemBaseProps>>(
RadioGroup.Item,
'item',
)
export const ItemText = withContext<Assign<HTMLStyledProps<'span'>, RadioGroup.ItemTextBaseProps>>(
RadioGroup.ItemText,
'itemText',
)
export const Label = withContext<Assign<HTMLStyledProps<'label'>, RadioGroup.LabelBaseProps>>(
RadioGroup.Label,
'label',
)
export {
RadioGroupContext as Context,
RadioGroupItemHiddenInput as ItemHiddenInput,
} from '@ark-ui/solid'
No snippet found
2
Add Re-Export
To improve the developer experience, re-export the styled primitives in~/components/ui/radio-group.tsx
.
export * as RadioGroup from './styled/radio-group'
export * as RadioGroup from './styled/radio-group'
3
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { radioGroupAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const radioGroup = defineSlotRecipe({
className: 'radioGroup',
slots: radioGroupAnatomy.keys(),
base: {
root: {
display: 'flex',
flexDirection: {
_vertical: 'column',
_horizontal: 'row',
},
},
itemControl: {
background: 'transparent',
borderColor: 'border.default',
borderRadius: 'full',
borderWidth: '1px',
transitionDuration: 'normal',
transitionProperty: 'background',
transitionTimingFunction: 'default',
_hover: {
background: 'bg.subtle',
},
_checked: {
background: 'colorPalette.default',
borderColor: 'colorPalette.default',
outlineColor: 'bg.default',
outlineStyle: 'solid',
_hover: {
background: 'colorPalette.default',
},
},
_disabled: {
borderColor: 'border.disabled',
color: 'fg.disabled',
_hover: {
bg: 'initial',
color: 'fg.disabled',
},
},
},
item: {
alignItems: 'center',
cursor: 'pointer',
display: 'flex',
_disabled: {
cursor: 'not-allowed',
},
},
itemText: {
color: 'fg.default',
fontWeight: 'medium',
_disabled: {
color: 'fg.disabled',
},
},
},
defaultVariants: {
size: 'md',
},
variants: {
size: {
sm: {
root: {
gap: {
_vertical: '3',
_horizontal: '4',
},
},
item: {
gap: '2',
},
itemControl: {
width: '4',
height: '4',
_checked: {
outlineWidth: '3px',
outlineOffset: '-4px',
},
},
itemText: {
textStyle: 'sm',
},
},
md: {
root: {
gap: {
_vertical: '4',
_horizontal: '6',
},
},
item: {
gap: '3',
},
itemControl: {
width: '5',
height: '5',
_checked: {
outlineWidth: '4px',
outlineOffset: '-5px',
},
},
itemText: {
textStyle: 'md',
},
},
lg: {
root: {
gap: {
_vertical: '5',
_horizontal: '8',
},
},
item: {
gap: '4',
},
itemControl: {
width: '6',
height: '6',
_checked: {
outlineWidth: '5px',
outlineOffset: '-6px',
},
},
itemText: {
textStyle: 'lg',
},
},
},
},
})