mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-19 14:31:47 +01:00
feat(Switch): add label and description props (#60)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
@@ -21,18 +21,25 @@ export interface SwitchProps extends Omit<SwitchRootProps, 'asChild'> {
|
||||
loadingIcon?: IconProps['name']
|
||||
checkedIcon?: IconProps['name']
|
||||
uncheckedIcon?: IconProps['name']
|
||||
label?: string
|
||||
description?: string
|
||||
class?: any
|
||||
ui?: Partial<typeof switchTv.slots>
|
||||
}
|
||||
|
||||
export interface CheckboxSlots {
|
||||
label(props: { label?: string }): any
|
||||
description(props: { description?: string }): any
|
||||
}
|
||||
|
||||
export interface SwitchEmits extends SwitchRootEmits {}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { SwitchRoot, SwitchThumb, useForwardPropsEmits } from 'radix-vue'
|
||||
import { SwitchRoot, SwitchThumb, useForwardPropsEmits, Label } from 'radix-vue'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig, useFormField } from '#imports'
|
||||
import { useId, useAppConfig, useFormField } from '#imports'
|
||||
|
||||
const props = defineProps<SwitchProps>()
|
||||
const emits = defineEmits<SwitchEmits>()
|
||||
@@ -40,12 +47,15 @@ const emits = defineEmits<SwitchEmits>()
|
||||
const appConfig = useAppConfig()
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultChecked', 'checked', 'required', 'value'), emits)
|
||||
|
||||
const { inputId, emitFormChange, size, color, name, disabled } = useFormField<SwitchProps>(props)
|
||||
const { inputId: _inputId, emitFormChange, size, color, name, disabled } = useFormField<SwitchProps>(props)
|
||||
const inputId = _inputId.value ?? useId()
|
||||
|
||||
const ui = computed(() => tv({ extend: switchTv, slots: props.ui })({
|
||||
color: color.value,
|
||||
size: size.value,
|
||||
loading: props.loading
|
||||
required: props.required,
|
||||
loading: props.loading,
|
||||
disabled: disabled.value || props.loading
|
||||
}))
|
||||
|
||||
// FIXME: I think there's a race condition between this and the v-model event.
|
||||
@@ -57,20 +67,36 @@ async function onChecked() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SwitchRoot
|
||||
:id="inputId"
|
||||
:name="name"
|
||||
:disabled="disabled || loading"
|
||||
v-bind="rootProps"
|
||||
:class="ui.root({ class: props.class })"
|
||||
@update:checked="onChecked"
|
||||
>
|
||||
<SwitchThumb :class="ui.thumb()">
|
||||
<UIcon v-if="loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.icon({ checked: true, unchecked: true })" />
|
||||
<template v-else>
|
||||
<UIcon v-if="checkedIcon" :name="checkedIcon" :class="ui.icon({ checked: true })" />
|
||||
<UIcon v-if="uncheckedIcon" :name="uncheckedIcon" :class="ui.icon({ unchecked: true })" />
|
||||
</template>
|
||||
</SwitchThumb>
|
||||
</SwitchRoot>
|
||||
<div :class="ui.root({ class: props.class })">
|
||||
<div :class="ui.container()">
|
||||
<SwitchRoot
|
||||
:id="inputId"
|
||||
:name="name"
|
||||
:disabled="disabled || loading"
|
||||
v-bind="rootProps"
|
||||
:class="ui.base()"
|
||||
@update:checked="onChecked"
|
||||
>
|
||||
<SwitchThumb :class="ui.thumb()">
|
||||
<UIcon v-if="loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.icon({ checked: true, unchecked: true })" />
|
||||
<template v-else>
|
||||
<UIcon v-if="checkedIcon" :name="checkedIcon" :class="ui.icon({ checked: true })" />
|
||||
<UIcon v-if="uncheckedIcon" :name="uncheckedIcon" :class="ui.icon({ unchecked: true })" />
|
||||
</template>
|
||||
</SwitchThumb>
|
||||
</SwitchRoot>
|
||||
</div>
|
||||
<div v-if="(label || $slots.label) || (description || $slots.description)" :class="ui.wrapper()">
|
||||
<Label v-if="label || $slots.label" :for="inputId" :class="ui.label()">
|
||||
<slot name="label" :label="label">
|
||||
{{ label }}
|
||||
</slot>
|
||||
</Label>
|
||||
<p v-if="description || $slots.description" :class="ui.description()">
|
||||
<slot name="description" :description="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user