From 93358de63996ca8c738bc9862a0617c03e3ccc57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B8=A3=E9=85=B1?= <3065113977@qq.com> Date: Thu, 26 Mar 2026 11:01:22 +0800 Subject: [PATCH] Preserve Vue RadioGroupLabel semantics --- .../radio-group/radio-group.test.ts | 21 +++++++++++++++++++ .../src/components/radio-group/radio-group.ts | 2 ++ 2 files changed, 23 insertions(+) diff --git a/packages/@headlessui-vue/src/components/radio-group/radio-group.test.ts b/packages/@headlessui-vue/src/components/radio-group/radio-group.test.ts index cdad2fbdb8..c1640195b8 100644 --- a/packages/@headlessui-vue/src/components/radio-group/radio-group.test.ts +++ b/packages/@headlessui-vue/src/components/radio-group/radio-group.test.ts @@ -5,6 +5,7 @@ import { assertNotFocusable, assertRadioGroupLabel, getByText, + getRadioGroupLabel, getRadioGroupOptions, } from '../../test-utils/accessibility-assertions' import { html } from '../../test-utils/html' @@ -73,6 +74,26 @@ describe('Safe guards', () => { }) ) + it('should not mark the RadioGroupLabel as presentation', async () => { + renderTemplate({ + template: html` + + Pizza Delivery + Pickup + Home delivery + + `, + setup() { + let deliveryMethod = ref(undefined) + return { deliveryMethod } + }, + }) + + await new Promise(nextTick) + + expect(getRadioGroupLabel()).not.toHaveAttribute('role') + }) + it('should be possible to render a RadioGroup without options and without crashing', () => { renderTemplate({ template: html` `, diff --git a/packages/@headlessui-vue/src/components/radio-group/radio-group.ts b/packages/@headlessui-vue/src/components/radio-group/radio-group.ts index cd63c398d7..22df77aa3b 100644 --- a/packages/@headlessui-vue/src/components/radio-group/radio-group.ts +++ b/packages/@headlessui-vue/src/components/radio-group/radio-group.ts @@ -88,6 +88,7 @@ export let RadioGroup = defineComponent({ let options = ref([]) let labelledby = useLabels({ name: 'RadioGroupLabel' }) let describedby = useDescriptions({ name: 'RadioGroupDescription' }) + let groupLabelIds = computed(() => new Set((labelledby.value ?? '').split(' ').filter(Boolean))) expose({ el: radioGroupRef, $el: radioGroupRef }) @@ -148,6 +149,7 @@ export let RadioGroup = defineComponent({ accept(node) { if (node.getAttribute('role') === 'radio') return NodeFilter.FILTER_REJECT if (node.hasAttribute('role')) return NodeFilter.FILTER_SKIP + if (node.id && groupLabelIds.value.has(node.id)) return NodeFilter.FILTER_SKIP return NodeFilter.FILTER_ACCEPT }, walk(node) {