fix(components): forward data-slot to component root#6643
Draft
benjamincanac wants to merge 1 commit into
Draft
Conversation
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.
commit: |
data-slot to component root
data-slot to component rootdata-slot to component root
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Linked issue
Follow-up to #6641. That PR forwarded fall-through attributes to
Separator's root (the inconsistency was surfaced by #6611), but itsdata-slot-on-root handling was reverted before merge, so the staticdata-slot="root"still won over a caller value. This re-applies it onSeparatorand generalizes the same rule to every component.❓ Type of change
📚 Description
Components forward
data-slotto their children in roughly 80 places (most often toUIcon,UAvatar,UButton,UInput), but whether the child honored thatdata-sloton its own root was inconsistent. Single root components with defaultinheritAttrslet the caller's value fall through and win, which is what we want. Components withinheritAttrs: falsedid not: some dropped it from the root, and some let it leak onto an inner element.UAvataris the clearest case, it placed the caller'sdata-sloton 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-slotalways wins on the component's root, with the component's own value (root/base) as the fallback, and inner elements keep their owndata-slot.Three idioms depending on how the root receives attributes:
inheritAttrs: nothing to do, Vue fallthrough already handles it.inheritAttrs: falsewith$attrson the root: put the default before the spread, eitherdata-slot="root" v-bind="$attrs"(bare) orv-bind="{ 'data-slot': 'root', ...$attrs }"(object), so a caller value overrides it.inheritAttrs: falsewith$attrsforwarded 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 owndata-slotafter its$attrsspread (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-slotvalue changes by default (roots stayroot/base). The snapshot churn is the intended behavior surfacing where parents passdata-slotto embedded avatars and inputs, plus some benign attribute reordering on the roots wheredata-slotnow sits before the$attrsspread. No public API changed. The convention is documented incomponent-structure.mdandAGENTS.md.EditorToolbarwas intentionally left as is, its$attrslands on a conditional:as="Component"/templateouter element and it is never passed adata-slot.📝 Checklist