Skip to content

fix(components): forward data-slot to component root#6643

Draft
benjamincanac wants to merge 1 commit into
v4from
data-slot-root-consistency
Draft

fix(components): forward data-slot to component root#6643
benjamincanac wants to merge 1 commit into
v4from
data-slot-root-consistency

Conversation

@benjamincanac

@benjamincanac benjamincanac commented Jun 26, 2026

Copy link
Copy Markdown
Member

🔗 Linked issue

Follow-up to #6641. That PR forwarded fall-through attributes to Separator's root (the inconsistency was surfaced by #6611), but its data-slot-on-root handling was reverted before merge, so the static data-slot="root" still won over a caller value. This re-applies it on Separator and generalizes the same rule to every component.

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Components forward data-slot to their children in roughly 80 places (most often to UIcon, UAvatar, UButton, UInput), but whether the child honored that data-slot on its own root was inconsistent. Single root components with default inheritAttrs let the caller's value fall through and win, which is what we want. Components with inheritAttrs: false did not: some dropped it from the root, and some let it leak onto an inner element. UAvatar is the clearest case, it placed the caller's data-slot on the inner <img> instead of the root, so a parent's [data-slot="leadingAvatar"] never matched where it expected.

This makes the behavior consistent everywhere. The canonical rule is: a caller-supplied data-slot always wins on the component's root, with the component's own value (root/base) as the fallback, and inner elements keep their own data-slot.

Three idioms depending on how the root receives attributes:

  1. Single root, default inheritAttrs: nothing to do, Vue fallthrough already handles it.
  2. inheritAttrs: false with $attrs on the root: put the default before the spread, either data-slot="root" v-bind="$attrs" (bare) or v-bind="{ 'data-slot': 'root', ...$attrs }" (object), so a caller value overrides it.
  3. inheritAttrs: false with $attrs forwarded to an inner element (UAvatar, UInput, UCheckbox, ...): read the value on the root with :data-slot="($attrs['data-slot'] as string | undefined) ?? 'root'", and keep each inner element's own data-slot after its $attrs spread (or strip it with { ...$attrs, 'data-slot': undefined } for <Slot> forwards and unlabeled inputs) so the caller's value does not leak.

No component's own data-slot value changes by default (roots stay root / base). The snapshot churn is the intended behavior surfacing where parents pass data-slot to embedded avatars and inputs, plus some benign attribute reordering on the roots where data-slot now sits before the $attrs spread. No public API changed. The convention is documented in component-structure.md and AGENTS.md.

EditorToolbar was intentionally left as is, its $attrs lands on a conditional :as="Component" / template outer element and it is never passed a data-slot.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Make data-slot handling consistent across all components: a caller-supplied data-slot now always wins on the component root (with the component's own root/base value as fallback), and inner elements keep their own data-slot. Previously inheritAttrs: false components either dropped the caller's data-slot from the root or let it leak onto an inner element.
@github-actions github-actions Bot added the v4 #4488 label Jun 26, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jun 26, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/@nuxt/ui@6643

commit: 17ef442

@benjamincanac benjamincanac changed the title fix: forward caller-supplied data-slot to component root fix(components): forward caller-supplied data-slot to component root Jun 27, 2026
@benjamincanac benjamincanac changed the title fix(components): forward caller-supplied data-slot to component root fix(components): forward caller-supplied data-slot to component root Jun 27, 2026
@benjamincanac benjamincanac changed the title fix(components): forward caller-supplied data-slot to component root fix: honor data-slot on component root Jun 27, 2026
@benjamincanac benjamincanac changed the title fix: honor data-slot on component root fix(components): forward data-slot to component root Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v4 #4488

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant