Unstyled radio option (reka-ui RadioGroupItem) for custom segmented buttons or cards inside RadioButtonGroup.
import RadioGroupItemPrimitive from "@wikicasa-dev/components/UIKit/Radio/v2/RadioGroupItemPrimitive";
An option with no visuals of its own: an unstyled <button role="radio"> whose content is your slot. Use it inside RadioButtonGroup when options should look like segmented tabs, pills or selectable cards (e.g. "Vendita | Affitto | Asta" tabs, condition buttons in a filter modal). For the classic circle-and-label look use RadioButtonItem.
The default slot receives { checked, required, disabled }. select is emitted when the option is chosen.
Usage
<script setup lang="ts">
import { ref } from "vue";
import RadioButtonGroup from "@wikicasa-dev/components/UIKit/Radio/v2/RadioButtonGroup";
import RadioGroupItemPrimitive from "@wikicasa-dev/components/UIKit/Radio/v2/RadioGroupItemPrimitive";
const contract = ref("vendita");
const options = [
{ value: "vendita", label: "Vendita" },
{ value: "affitto", label: "Affitto" },
{ value: "asta", label: "Asta" },
];
</script>
<template>
<RadioButtonGroup v-model="contract" aria-label="Tipo di contratto" orientation="horizontal" class="segmented">
<RadioGroupItemPrimitive v-for="o in options" :key="o.value" :value="o.value" :data-cy="`contract-${o.value}`" class="segment">
{{ o.label }}
</RadioGroupItemPrimitive>
</RadioButtonGroup>
</template>
<style scoped>
.segmented { display: grid; grid-template-columns: repeat(3, 1fr); }
.segment { padding: 6px 20px; border: 0; border-bottom: 2px solid transparent; background: transparent; }
.segment[data-state="checked"] { border-bottom-color: rgb(var(--uikit-color-w-primary)); font-weight: 600; }
.segment:focus-visible { outline: 2px solid rgb(var(--uikit-color-w-primary)); }
</style>
Do / Don't
- Do always place it inside
RadioButtonGroup(the library has no separate radio root primitive) and give it a uniquevalue. - Do put readable text in the slot; icon-only options need an
aria-label. - Do style checked and disabled looks with
[data-state="checked"]and[data-disabled], and keep a visible:focus-visiblestyle. - Don't use it when the classic radio look is fine; use
RadioButtonItem.
Styling hooks
None: it is an unstyled <button>; class goes on it. Use data-state / data-disabled selectors and the design tokens.
API
Generated from the component's types. Do not edit by hand.
Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
dataCy |
string |
|||
disabled |
boolean |
When true, prevents the user from interacting with the radio item. |
||
asChild |
boolean |
Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | ||
as |
AsTag | Component |
The element or component this component should render as. Can be overwritten by asChild. |
||
required |
boolean |
When true, indicates that the user must set the value before the owning form can be submitted. |
||
value |
AcceptableValue |
The value given as data when submitted with a name. |
||
id |
string |
|||
name |
string |
The name of the field. Submitted with its owning form as part of a name/value pair. |
Events
| Name | Payload |
|---|---|
select |
[SelectEvent$2] |
v-model
None.
Slots
| Name | Slot props |
|---|---|
default |
{ checked: boolean; required: boolean; disabled: boolean; } |
Exposed (template ref)
None.