diff --git a/src/runtime/components/Checkbox.vue b/src/runtime/components/Checkbox.vue index 8e70ca4f48..76e2a78f3f 100644 --- a/src/runtime/components/Checkbox.vue +++ b/src/runtime/components/Checkbox.vue @@ -66,7 +66,7 @@ const modelValue = defineModel({ default: undefined } const rootProps = useForwardProps(reactivePick(props, 'required', 'value', 'defaultValue')) const appConfig = useAppConfig() -const { id: _id, emitFormChange, emitFormInput, size, color, name, disabled } = useFormField(props) +const { id: _id, emitFormChange, emitFormInput, size, color, name, disabled, ariaAttrs } = useFormField(props) const id = _id.value ?? useId() const ui = computed(() => checkbox({ @@ -92,7 +92,7 @@ function onUpdate(value: any) {
| null>('form-errors', null) const error = computed(() => props.error || formErrors?.value?.find(error => error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern)))?.message) const id = ref(useId()) +// Copies id's initial value to bind aria-attributes such as aria-describedby. +// This is required for the RadioGroup component which unsets the id value. +const ariaId = id.value provide(inputIdInjectionKey, id) @@ -75,7 +78,10 @@ provide(formFieldInjectionKey, computed(() => ({ size: props.size, eagerValidation: props.eagerValidation, validateOnInputDelay: props.validateOnInputDelay, - errorPattern: props.errorPattern + errorPattern: props.errorPattern, + hint: props.hint, + description: props.description, + ariaId }) as FormFieldInjectedOptions)) @@ -88,14 +94,14 @@ provide(formFieldInjectionKey, computed(() => ({ {{ label }} - + {{ hint }}
-

+

{{ description }} @@ -105,7 +111,7 @@ provide(formFieldInjectionKey, computed(() => ({

-

+

{{ error }} diff --git a/src/runtime/components/Input.vue b/src/runtime/components/Input.vue index 0f78c5b06c..d2be2d4eed 100644 --- a/src/runtime/components/Input.vue +++ b/src/runtime/components/Input.vue @@ -75,7 +75,7 @@ const slots = defineSlots() const [modelValue, modelModifiers] = defineModel() -const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled } = useFormField(props, { deferInputValidation: true }) +const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props, { deferInputValidation: true }) const { orientation, size: buttonGroupSize } = useButtonGroup(props) const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props) @@ -166,7 +166,7 @@ onMounted(() => { :disabled="disabled" :required="required" :autocomplete="autocomplete" - v-bind="$attrs" + v-bind="{ ...$attrs, ...ariaAttrs }" @input="onInput" @blur="onBlur" @change="onChange" diff --git a/src/runtime/components/InputMenu.vue b/src/runtime/components/InputMenu.vue index 2856599966..59740c5a8e 100644 --- a/src/runtime/components/InputMenu.vue +++ b/src/runtime/components/InputMenu.vue @@ -178,7 +178,7 @@ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', ' const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as ComboboxContentProps) const arrowProps = toRef(() => props.arrow as ComboboxArrowProps) -const { emitFormBlur, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled } = useFormField(props) +const { emitFormBlur, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props) const { orientation, size: buttonGroupSize } = useButtonGroup(props) const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown }))) @@ -365,7 +365,7 @@ defineExpose({ () const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'formatOptions'), emits) -const { emitFormBlur, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled } = useFormField(props) +const { emitFormBlur, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled, ariaAttrs } = useFormField(props) const { t, code: codeLocale } = useLocale() const locale = computed(() => props.locale || codeLocale.value) @@ -152,7 +152,7 @@ defineExpose({ @update:model-value="onUpdate" > (), { const emits = defineEmits() const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultValue', 'disabled', 'id', 'mask', 'modelValue', 'name', 'otp', 'placeholder', 'required', 'type'), emits) -const { emitFormInput, emitFormChange, emitFormBlur, size, color, id, name, highlight, disabled } = useFormField(props) +const { emitFormInput, emitFormChange, emitFormBlur, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props) const ui = computed(() => pinInput({ color: color.value, @@ -77,7 +77,7 @@ function onBlur(event: FocusEvent) {