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) {