Admin 元件

Radio Group

參考API
互斥單選按鈕組。

安裝

Terminal
pnpm dlx shadcn-vue add @admin/radio-group
import {  AdminRadioGroup,  AdminRadioGroupItem,  AdminRadioOption,} from '@/components/admin/radio-group'

用法

<script setup lang="ts">import type { AcceptableValue } from 'reka-ui'import { ref } from 'vue'import { AdminRadioGroup, AdminRadioOption } from '@/components/admin/radio-group'​const value = ref<AcceptableValue>('one')</script>​<template>  <admin-radio-group v-model="value" class="flex flex-col gap-2">    <admin-radio-option label="Option one" value="one" />    <admin-radio-option label="Option two" value="two" />  </admin-radio-group></template>

場景

多選項群組

<script setup lang="ts">import type { AcceptableValue } from 'reka-ui'import { ref } from 'vue'import { AdminRadioGroup, AdminRadioOption } from '@/components/admin/radio-group'​const value = ref<AcceptableValue>('standard')</script>​<template>  <admin-radio-group v-model="value" class="flex flex-col gap-2">    <admin-radio-option label="標準方案" value="standard" />    <admin-radio-option label="進階方案" value="pro" />    <admin-radio-option label="企業方案" value="enterprise" />  </admin-radio-group></template>

停用狀態

<script setup lang="ts">import type { AcceptableValue } from 'reka-ui'import { ref } from 'vue'import { AdminRadioGroup, AdminRadioOption } from '@/components/admin/radio-group'​const value = ref<AcceptableValue>('one')</script>​<template>  <admin-radio-group v-model="value" class="flex flex-col gap-2">    <admin-radio-option label="可選項 1" value="one" />    <admin-radio-option label="可選項 2" value="two" />    <admin-radio-option label="停用項目" value="three" disabled />  </admin-radio-group></template>

Type-safe 封裝

AdminRadioGroup 的 modelValue 為 reka-ui 的 AcceptableValue,選項則由呼叫端自行放置 admin-radio-option,兩者在 compile-time 不會對齊。

若需要讓 v-model 與選項 value 的 literal union 對齊,可自行封裝:傳入 options(建議加 as const),由封裝元件渲染 admin-radio-option。

範例:

TypedAdminRadioGroup.vue
<script  setup  lang="ts"  generic="    TOptions extends ReadonlyArray<{      label: string      value: AcceptableValue    }>  ">import type { AcceptableValue } from 'reka-ui'import type { AdminRadioGroupEmits, AdminRadioGroupProps } from '@/components/admin/radio-group'import { reactiveOmit } from '@vueuse/core'import { useForwardPropsEmits } from 'reka-ui'import { computed } from 'vue'import { AdminRadioGroup, AdminRadioOption } from '@/components/admin/radio-group'​type TModelValue = TOptions[number]['value']​defineOptions({  name: 'typed-admin-radio-group'})​const props = defineProps<  Omit<AdminRadioGroupProps, 'modelValue' | 'defaultValue'> & {    options: TOptions    modelValue?: TModelValue    defaultValue?: TModelValue  }>()​const emits = defineEmits<  Omit<AdminRadioGroupEmits, 'update:modelValue'> & {    'update:modelValue': [value: TModelValue]  }>()​const delegatedProps = reactiveOmit(props, 'modelValue', 'options')const forwardedAll = useForwardPropsEmits(delegatedProps, emits)​const forwarded = computed(() => {  const { 'onUpdate:modelValue': _, ...rest } = forwardedAll.value  return rest})​const innerValue = computed<AcceptableValue | undefined>({  get() {    return props.modelValue  },  set(value) {    emits('update:modelValue', value as TModelValue)  }})</script>​<template>  <admin-radio-group v-bind="forwarded" v-model="innerValue">    <admin-radio-option      v-for="(option, index) in props.options"      :key="`${option.value}-${index}`"      :label="option.label"      :value="option.value"    />  </admin-radio-group></template>
需開啟 strictVModel

型別檢查需開啟 strictVModel(若已開啟 strictTemplates 則已包含)。設定見 Type-safe。下列同時含合法綁定與刻意錯誤綁定;錯誤處以 @vue-expect-error 標示。

<script setup lang="ts">import { ref } from 'vue'import TypedAdminRadioGroup from './typed-admin-radio-group-demo.vue'​const options = [  { label: 'Draft', value: 'draft' },  { label: 'Published', value: 'published' }] as const​const status = ref<(typeof options)[number]['value']>('draft')const wrong = ref('unknown')</script>​<template>  <div class="flex w-full max-w-md flex-col gap-6">    <typed-admin-radio-group v-model="status" class="flex flex-col gap-2" :options="options" />​    <!-- @vue-expect-error value 不在 options 的 value union 內 -->    <typed-admin-radio-group v-model="wrong" class="flex flex-col gap-2" :options="options" />  </div></template>

API 參考

組成

<template>  <admin-radio-group v-model="value">    <admin-radio-option      v-for="option in options"      :key="option.value"      :label="option.label"      :value="option.value"    />  </admin-radio-group></template>

admin-radio-group

Props

名稱型別預設值說明
modelValueAcceptableValue | undefined—The controlled value of the radio item to check. Can be binded as `v-model`.
defaultValueAcceptableValue | undefined—The value of the radio item that should be checked when initially rendered. Use when you do not need to control the state of the radio items.
disabledboolean | undefined—When `true`, prevents the user from interacting with radio items.
orientationDataOrientation | undefined—The orientation of the component.
dirDirection | undefined—The reading direction of the combobox when applicable. If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode.
loopboolean | undefined—When `true`, keyboard navigation will loop from last item to first, and vice versa.
asChildboolean | undefined—Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details.
asglobalThis.Component | AsTag | undefined"div"The element or component this component should render as. Can be overwritten by `asChild`.
namestring | undefined—The name of the field. Submitted with its owning form as part of a name/value pair.
requiredboolean | undefined—When `true`, indicates that the user must set the value before the owning form can be submitted.
classClassValue—根元素之自訂 class
isErrorboolean | undefined—預留之錯誤狀態旗標(目前無對應視覺實作)

Events

名稱Payload說明
update:modelValueAcceptableValue—

Slots

名稱Bindings說明
default{ modelValue: AcceptableValue | undefined; }—

admin-radio-group-item

Props

名稱型別預設值說明
idstring | undefined——
asglobalThis.Component | AsTag | undefined"div"The element or component this component should render as. Can be overwritten by `asChild`.
asChildboolean | undefined—Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details.
requiredboolean | undefined—When `true`, indicates that the user must set the value before the owning form can be submitted.
disabledboolean | undefined—When `true`, prevents the user from interacting with the radio item.
namestring | undefined—The name of the field. Submitted with its owning form as part of a name/value pair.
valueAcceptableValue | undefined—The value given as data when submitted with a `name`.
classClassValue—根元素之自訂 class

Slots

名稱Bindings說明
default{}—

admin-radio-option

Props

名稱型別預設值說明
idstring | undefined——
asglobalThis.Component | AsTag | undefined"div"The element or component this component should render as. Can be overwritten by `asChild`.
asChildboolean | undefined—Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details.
requiredboolean | undefined—When `true`, indicates that the user must set the value before the owning form can be submitted.
disabledboolean | undefined—When `true`, prevents the user from interacting with the radio item.
namestring | undefined—The name of the field. Submitted with its owning form as part of a name/value pair.
valueAcceptableValue | undefined—The value given as data when submitted with a `name`.
labelstring | undefined—顯示於選項旁之文字標籤;不設則不渲染 label
classClassValue—根元素之自訂 class
labelClassClassValue—label 文字之自訂 class

更新紀錄

  • fix: 補上 Vue 核心 API 的顯式 import3c2c030
  • fix: 修正 isError 洩漏為 DOM 屬性並對齊 focus 樣式b47bedb