Skip to content
On this page

Radio Input

This page Show an Example of a Reusable Checkbox Input Component.

First Pattern

Demo

Only one Can be selected at a time

Disabled State

value is: { "name": "Ade" }

Second Pattern

Demo

This is an update to the previous pattern. in this pattern the vue defineModel macro is used to easily manage two way model bindings between the parent and child components.

User type is: user

Dependencies

{
    "tailwindcss": "^3.3.2", // for styling
}

Code

vue
<script setup lang="ts">
import { computed } from "vue";

const props = defineProps<{
  modelValue?: any;
  value?: any;
  required?: boolean;
  name?: string;
  label?: string;
  disabled?: boolean;
  variant?: string; // this is based on your needs, not implemented here
  size?: string; // based on your needs, not implemented here
}>();

const emit = defineEmits<{
  (event: "update:modelValue", data: any): void;
}>();

const checked = computed({
  get() {
    return props.modelValue;
  },
  set(newValue) {
    emit("update:modelValue", newValue);
  },
});
</script>

<template>
  <!-- style to fit your needs base on the states -->
  <label class="flex space-x-3 text-sm text-black dark:text-white w-fit">
    <input
      class="disabled:cursor-not-allowed peer"
      type="radio"
      v-model="checked"
      :name="name"
      :id="name"
      :value="value"
      :required="required"
      :disabled="disabled"
    />
    <p class="cursor-pointer peer-disabled:cursor-not-allowed" v-if="label">
      {{ label }}
    </p>
  </label>
</template>
vue
<script setup lang="ts">
import { ref } from "vue";
import Radio1 from "../components/Radio/Radio1.vue";

const checked = ref({ name: "Ade" });
</script>

<template>
  <div class="p-3 mt-4">
    <div>
      <p class="underline">Only one Can be selected at a time</p>
      <Radio1
        v-model="checked"
        label="Select Sodiq"
        :value="{ name: 'Sodiq' }"
        name="checkboxName"
      />
      <Radio1
        v-model="checked"
        label="Select Ade"
        :value="{ name: 'Ade' }"
        name="checkboxName"
      />
    </div>

    <div>
      <p class="underline">Disabled State</p>
      <Radio1
        disabled
        v-model="checked"
        :value="{ name: 'Foo' }"
        label="Cannot Select"
      />
    </div>

    <p>value is: {{ checked }}</p>
  </div>
</template>
vue
<script setup lang="ts">
import { computed } from "vue";

const props = defineProps<{
    value?: any;
    label?: string;
}>();

const userType = defineModel()
</script>

<template>
    <label class="w-full relative">
        <input type="radio" class="peer hidden" :value="value" v-model="userType" />
        <div
            class="py-[30px] px-[22px] ring-[1px] ring-[#EEEEFF] text-[#B1BDCA] text-xl font-medium rounded-[11px] cursor-pointer flex items-center gap-6 peer-checked:text-green-500 peer-checked:ring-green-500">
            <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256">
                <path fill="currentColor"
                    d="M236 96a12 12 0 0 0-.44-3.3L221.2 42.51A20.08 20.08 0 0 0 202 28H54a20.08 20.08 0 0 0-19.2 14.51L20.46 92.7A12 12 0 0 0 20 96v16a43.94 43.94 0 0 0 16 33.92V208a20 20 0 0 0 20 20h144a20 20 0 0 0 20-20v-62.08A43.94 43.94 0 0 0 236 112Zm-24 16a20 20 0 0 1-40 0v-4h40Zm-168 0v-4h40v4a20 20 0 0 1-40 0m64-4h40v4a20 20 0 0 1-40 0ZM57.05 52H199l9.14 32H47.91ZM196 204H60v-48.19c1.32.12 2.65.19 4 .19a43.86 43.86 0 0 0 32-13.85a43.89 43.89 0 0 0 64 0A43.86 43.86 0 0 0 192 156c1.35 0 2.68-.07 4-.19Z" />
            </svg>
            <p>{{ label }}</p>
        </div>
        <div
            class="absolute bottom-[100%] left-[100%] translate-x-[-50%] translate-y-[50%] w-[38px] h-[38px] shrink-0 rounded-full text-white bg-brand-purple hidden peer-checked:flex items-center justify-center">
            <svg class="text-green-500" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256">
                <path fill="currentColor"
                    d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m45.66 85.66l-56 56a8 8 0 0 1-11.32 0l-24-24a8 8 0 0 1 11.32-11.32L112 148.69l50.34-50.35a8 8 0 0 1 11.32 11.32" />
            </svg>
        </div>
</label></template>
vue
<script setup lang="ts">
import { ref } from "vue";
import Radio2 from "../components/Radio/Radio2.vue";

const userType = ref("user");
</script>

<template>
  <div class="p-3 mt-4">
    <div class="mt-4 flex gap-4 items-center max-w-[600px]">
      <Radio2
        v-model="userType"
        label="User"
        value="user"
      />
      <Radio2
        v-model="userType"
        label="Business"
        value="business"
      />
    </div>

    <p>User type is: {{ userType }}</p>
  </div>
</template>

Released under the MIT License.