From 0fcec449601b8ad06c7898698bc514db2f87dcf4 Mon Sep 17 00:00:00 2001 From: Benjamin Canac Date: Fri, 26 Jun 2026 16:36:23 +0200 Subject: [PATCH 1/5] fix(Separator): forward fall-through attributes to root `createReusableTemplate` placed `DefineContainer` as a sibling root node, turning Separator into a multi-root component that can no longer auto-inherit fall-through attributes. Passing one (e.g. `data-slot` from `AuthForm` when both `fields` and `providers` are present) triggered a Vue "Extraneous non-props attributes" warning. Set `inheritAttrs: false` and forward `$attrs` explicitly to the root, matching the pattern used by the other multi-root components. --- src/runtime/components/Separator.vue | 4 +++- test/components/Separator.spec.ts | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/runtime/components/Separator.vue b/src/runtime/components/Separator.vue index 43960874f3..5f70973074 100644 --- a/src/runtime/components/Separator.vue +++ b/src/runtime/components/Separator.vue @@ -65,6 +65,8 @@ import { tv } from '../utils/tv' import UIcon from './Icon.vue' import UAvatar from './Avatar.vue' +defineOptions({ inheritAttrs: false }) + const _props = withDefaults(defineProps(), { orientation: 'horizontal', position: 'center' @@ -102,7 +104,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.separator || - +
diff --git a/test/components/Separator.spec.ts b/test/components/Separator.spec.ts index 4d41f9d9c6..df1771aef5 100644 --- a/test/components/Separator.spec.ts +++ b/test/components/Separator.spec.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest' +import { describe, it, expect, vi } from 'vitest' import { axe } from 'vitest-axe' import { mountSuspended } from '@nuxt/test-utils/runtime' import { renderEach } from '../component-render' @@ -26,6 +26,24 @@ describe('Separator', () => { ['with ui', { props: { ui: { label: 'text-lg' } } }] ]) + it('forwards fall-through attributes to the root without warning', async () => { + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) + + const wrapper = await mountSuspended(Separator, { + props: { label: 'or' }, + attrs: { 'id': 'my-separator', 'data-test': 'value' } + }) + + const root = wrapper.get('[data-slot="root"]') + expect(root.attributes('id')).toBe('my-separator') + expect(root.attributes('data-test')).toBe('value') + + const warnings = warn.mock.calls.map(args => args.join(' ')).join('\n') + expect(warnings).not.toContain('Extraneous non-props attributes') + + warn.mockRestore() + }) + it('passes accessibility tests', async () => { const wrapper = await mountSuspended(Separator, { props: { From 9d918be9e6feef7a414dc905468881b0f31c1a2c Mon Sep 17 00:00:00 2001 From: Benjamin Canac Date: Fri, 26 Jun 2026 16:58:28 +0200 Subject: [PATCH 2/5] fix(Separator): preserve caller-supplied data-slot and restore spy in finally Apply the default `data-slot="root"` inside the v-bind object so a consumer-supplied `$attrs['data-slot']` (e.g. AuthForm's "separator") takes precedence instead of being overwritten by the static attribute. Also wrap the fall-through test assertions in try/finally so the `console.warn` spy is always restored. --- src/runtime/components/Separator.vue | 2 +- test/components/Separator.spec.ts | 28 ++++++++++--------- .../__snapshots__/AuthForm-vue.spec.ts.snap | 2 +- .../__snapshots__/AuthForm.spec.ts.snap | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/runtime/components/Separator.vue b/src/runtime/components/Separator.vue index 5f70973074..4b4bd52370 100644 --- a/src/runtime/components/Separator.vue +++ b/src/runtime/components/Separator.vue @@ -104,7 +104,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.separator ||
- +
diff --git a/test/components/Separator.spec.ts b/test/components/Separator.spec.ts index df1771aef5..b3f5ca96ac 100644 --- a/test/components/Separator.spec.ts +++ b/test/components/Separator.spec.ts @@ -29,19 +29,21 @@ describe('Separator', () => { it('forwards fall-through attributes to the root without warning', async () => { const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - const wrapper = await mountSuspended(Separator, { - props: { label: 'or' }, - attrs: { 'id': 'my-separator', 'data-test': 'value' } - }) - - const root = wrapper.get('[data-slot="root"]') - expect(root.attributes('id')).toBe('my-separator') - expect(root.attributes('data-test')).toBe('value') - - const warnings = warn.mock.calls.map(args => args.join(' ')).join('\n') - expect(warnings).not.toContain('Extraneous non-props attributes') - - warn.mockRestore() + try { + const wrapper = await mountSuspended(Separator, { + props: { label: 'or' }, + attrs: { 'id': 'my-separator', 'data-test': 'value' } + }) + + const root = wrapper.get('[data-slot="root"]') + expect(root.attributes('id')).toBe('my-separator') + expect(root.attributes('data-test')).toBe('value') + + const warnings = warn.mock.calls.map(args => args.join(' ')).join('\n') + expect(warnings).not.toContain('Extraneous non-props attributes') + } finally { + warn.mockRestore() + } }) it('passes accessibility tests', async () => { diff --git a/test/components/__snapshots__/AuthForm-vue.spec.ts.snap b/test/components/__snapshots__/AuthForm-vue.spec.ts.snap index 417614060d..18a31b2eef 100644 --- a/test/components/__snapshots__/AuthForm-vue.spec.ts.snap +++ b/test/components/__snapshots__/AuthForm-vue.spec.ts.snap @@ -529,7 +529,7 @@ exports[`AuthForm > renders with providers correctly 1`] = `
-