Skip to content

Radio

A material design radio button.

Usage

Basic Radio
Option A
Option B
Option C (Left)
Selected: A
Radio Group
One
Two
Three
Group Value: One
Nested Layout
Category A
Option A1
Option A2
Category B
Option B1
Option B2
Nested Value: A1
v-for Loop (Items)
Item 1
Item 2
Item 3
Item 4
Loop Value: Item 2
v-for Loop (RadioGroups)
Question 1: Yes or No?
Yes
No
Answer: Yes
Question 2: Pick a Color
Red
Green
Blue
Answer: Red
Dynamic v-model
Option 1
Option 2
Option 3
Current Value: Option 1
Cross Nested (Radio inside Checkbox)
Include Extra Options
R1
R2
Basic Option
Checkbox: [ "Include Extra" ], Radio: R1
Hide Icon
Option X
Option Y
RadioListTile
Light ThemeUse light theme
Dark ThemeUse dark theme
System Theme
Custom Theme (No Icon)
Theme: Light
vue
<template>
  <Column :gap="20">
    <!-- Basic Radio with Labels -->
    <Text :style="headerStyle">Basic Radio</Text>
    <Row :gap="20" cross-axis-alignment="center">
      <Radio value="A" v-model:groupValue="radioVal">
        <Text>Option A</Text>
      </Radio>
      <Radio value="B" v-model:groupValue="radioVal" active-color="#4CAF50">
        <Text>Option B</Text>
      </Radio>
      <Radio value="C" v-model:groupValue="radioVal" label-position="left">
        <Text>Option C (Left)</Text>
      </Radio>
    </Row>
    <Text>Selected: {{ radioVal }}</Text>

    <Divider />

    <!-- Radio Group -->
    <Text :style="headerStyle">Radio Group</Text>
    <RadioGroup v-model:value="groupVal" active-color="#E91E63">
      <Row :gap="20">
        <Radio value="One">
          <Text>One</Text>
        </Radio>
        <Radio value="Two">
          <Text>Two</Text>
        </Radio>
        <Radio value="Three">
          <Text>Three</Text>
        </Radio>
      </Row>
    </RadioGroup>
    <Text>Group Value: {{ groupVal }}</Text>

    <Divider />

    <!-- Nested Radio Group -->
    <Text :style="headerStyle">Nested Layout</Text>
    <RadioGroup v-model:value="nestedVal">
      <Container color="#f5f5f5" :padding="EdgeInsets.all(10)">
        <Column :gap="10">
          <Text :style="{ fontWeight: FontWeight.bold }">Category A</Text>
          <Row :gap="20">
            <Radio value="A1"><Text>Option A1</Text></Radio>
            <Radio value="A2"><Text>Option A2</Text></Radio>
          </Row>
          <Text :style="{ fontWeight: FontWeight.bold }">Category B</Text>
          <Row :gap="20">
            <Radio value="B1"><Text>Option B1</Text></Radio>
            <Radio value="B2"><Text>Option B2</Text></Radio>
          </Row>
        </Column>
      </Container>
    </RadioGroup>
    <Text>Nested Value: {{ nestedVal }}</Text>

    <Divider />

    <!-- v-for Loop -->
    <Text :style="headerStyle">v-for Loop (Items)</Text>
    <RadioGroup v-model:value="loopVal">
      <Row :gap="10" wrap>
        <Radio v-for="item in items" :key="item" :value="item">
          <Text>{{ item }}</Text>
        </Radio>
      </Row>
    </RadioGroup>
    <Text>Loop Value: {{ loopVal }}</Text>

    <Divider />

    <!-- v-for Loop with RadioGroup -->
    <Text :style="headerStyle">v-for Loop (RadioGroups)</Text>
    <Column :gap="15">
      <RadioGroup
        v-for="(group, index) in questionGroups"
        :key="index"
        v-model:value="group.answer"
        active-color="#673AB7"
      >
        <Column :gap="5">
          <Text :style="{ fontWeight: FontWeight.bold }">{{ group.question }}</Text>
          <Row :gap="15">
            <Radio v-for="opt in group.options" :key="opt" :value="opt">
              <Text>{{ opt }}</Text>
            </Radio>
          </Row>
          <Text>Answer: {{ group.answer }}</Text>
        </Column>
      </RadioGroup>
    </Column>

    <Divider />

    <!-- Dynamic v-model -->
    <Text :style="headerStyle">Dynamic v-model</Text>
    <RadioGroup v-model:value="dynamicVal">
      <Column :gap="10">
        <Row :gap="20">
          <Radio value="Option 1"><Text>Option 1</Text></Radio>
          <Radio value="Option 2"><Text>Option 2</Text></Radio>
          <Radio value="Option 3"><Text>Option 3</Text></Radio>
        </Row>
        <Row :gap="10">
          <Button @click="dynamicVal = 'Option 1'"><Text>Select 1</Text></Button>
          <Button @click="dynamicVal = 'Option 2'"><Text>Select 2</Text></Button>
          <Button @click="dynamicVal = 'Option 3'"><Text>Select 3</Text></Button>
        </Row>
        <Text>Current Value: {{ dynamicVal }}</Text>
      </Column>
    </RadioGroup>

    <Divider />

    <!-- Cross-Nested Example -->
    <Text :style="headerStyle">Cross Nested (Radio inside Checkbox)</Text>
    <CheckboxGroup v-model:value="crossCheckVal">
      <Column :gap="15">
        <Checkbox value="Include Extra">
          <Row :gap="10" cross-axis-alignment="center">
            <Text>Include Extra Options</Text>
            <RadioGroup
              v-if="crossCheckVal.includes('Include Extra')"
              v-model:value="crossRadioVal"
            >
              <Row :gap="10">
                <Radio value="R1"><Text>R1</Text></Radio>
                <Radio value="R2"><Text>R2</Text></Radio>
              </Row>
            </RadioGroup>
          </Row>
        </Checkbox>
        <Checkbox value="Basic Option">
          <Text>Basic Option</Text>
        </Checkbox>
      </Column>
    </CheckboxGroup>
    <Text>Checkbox: {{ crossCheckVal }}, Radio: {{ crossRadioVal }}</Text>

    <Divider />

    <!-- Hide Icon Radio -->
    <Text :style="headerStyle">Hide Icon</Text>
    <Row :gap="20" cross-axis-alignment="center">
      <Radio value="X" v-model:groupValue="hiddenVal" hide-icon>
        <Text :style="hiddenVal === 'X' ? { color: '#007AFF', fontWeight: FontWeight.bold } : {}"
          >Option X</Text
        >
      </Radio>
      <Radio value="Y" v-model:groupValue="hiddenVal" hide-icon>
        <Text :style="hiddenVal === 'Y' ? { color: '#007AFF', fontWeight: FontWeight.bold } : {}"
          >Option Y</Text
        >
      </Radio>
    </Row>

    <Divider />

    <!-- RadioListTile -->
    <Text :style="headerStyle">RadioListTile</Text>
    <Container color="#f5f5f5">
      <Column>
        <RadioListTile
          value="Light"
          v-model:groupValue="themeVal"
          title="Light Theme"
          subtitle="Use light theme"
        />
        <RadioListTile
          value="Dark"
          v-model:groupValue="themeVal"
          title="Dark Theme"
          subtitle="Use dark theme"
          active-color="#212121"
        />
        <RadioListTile
          value="System"
          v-model:groupValue="themeVal"
          title="System Theme"
          control-affinity="trailing"
        />
        <RadioListTile
          value="Custom"
          v-model:groupValue="themeVal"
          title="Custom Theme (No Icon)"
          hide-icon
          :selected-color="themeVal === 'Custom' ? '#007AFF' : undefined"
        />
      </Column>
    </Container>
    <Text>Theme: {{ themeVal }}</Text>
  </Column>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import {
  Column,
  Row,
  Text,
  Radio,
  RadioGroup,
  RadioListTile,
  Divider,
  Container,
  TextStyle,
  FontWeight,
  EdgeInsets,
  Button,
  Checkbox,
  CheckboxGroup,
} from "fluekit";

const radioVal = ref("A");
const groupVal = ref("One");
const nestedVal = ref("A1");
const loopVal = ref("Item 2");
const themeVal = ref("Light");
const hiddenVal = ref("X");
const dynamicVal = ref("Option 1");
const items = ["Item 1", "Item 2", "Item 3", "Item 4"];
const crossCheckVal = ref(["Include Extra"]);
const crossRadioVal = ref("R1");

const questionGroups = reactive([
  { question: "Question 1: Yes or No?", options: ["Yes", "No"], answer: "Yes" },
  { question: "Question 2: Pick a Color", options: ["Red", "Green", "Blue"], answer: "Red" },
]);

const headerStyle = TextStyle({
  fontWeight: FontWeight.bold,
});
</script>

API

Props

NameTypeDefaultDescription
valueany-The value represented by this radio button.
groupValueany-The currently selected value for a group of radio buttons.
activeColorstring'#007AFF'The color to use when this radio button is selected.
fillColorstring-The background color of the radio button.
labelPosition'left' | 'right''right'The position of the label relative to the radio.
hideIconbooleanfalseWhether to hide the radio icon.

Slots

NameDescription
defaultThe label content.

Events

NameDescription
update:groupValueEmitted when the user selects this radio button.
changeEmitted when the user selects this radio button.

RadioGroup

A wrapper for grouping radio buttons.

Props

NameTypeDefaultDescription
valueany-The currently selected value (v-model).
activeColorstring-The color to use for all radios in the group.
disabledbooleanfalseWhether all radios in the group are disabled.

Events

NameDescription
update:valueEmitted when the value changes.
changeEmitted when the value changes.

RadioListTile

A list tile that displays a radio button.

Props

NameTypeDefaultDescription
valueany-The value represented by this radio button.
groupValueany-The currently selected value.
titlestring-The primary content of the list tile.
subtitlestring-Additional content displayed below the title.
secondaryComponent-A widget to display on the opposite side of the tile.
controlAffinity'leading' | 'trailing''leading'Where to place the radio relative to the text.
activeColorstring-The color to use when this radio button is selected.
tileColorstring-The color of the list tile.
selectedbooleanfalseWhether the list tile is selected.
selectedColorstring-The color of the text and icon when selected.
contentPaddingEdgeInsets-The padding of the list tile content.
enabledbooleantrueWhether the list tile is interactive.
densebooleanfalseWhether the list tile is part of a dense list.
hideIconbooleanfalseWhether to hide the radio icon.

Slots

NameDescription
titleCustom title content.
subtitleCustom subtitle content.
secondaryCustom content on the opposite side.
leadingCustom leading content (overrides radio).
trailingCustom trailing content (overrides radio).