API for slotted element/s to inherit attributes from a parent component
What problem does this feature solve?
I would like the ability to be able to wrap an element/s in a component that applies attributes to them. This can be useful as a way to apply extra features to an element/s without having to use unnecessary wrapper divs, or refs. Essentially, while there are often more verbose alternatives, I think the ability to make higher-order-components in Vue allows for useful patterns especially when used in component libraries.
What does the proposed API look like?
I'd like to make slots function similarly to components in that if they render a single child the child will get the passed $attrs
, but if they render multiple children you have to v-bind
them yourself.
An idea could be to have a v-attrs
directive specifically for slots:
// MenuItem.vue (HOC to manage menu item attributes for any element simplified to just adding a role)
<template>
<slot v-attrs="{ role: 'menuitem' }"></slot>
</template>
When used:
<template>
<MenuItem><button /></MenuItem>
</template>
Would render:
<button role="menuitem" />
However if there are multiple elements/components in the slot you would get access to a $attrs
prop on the slot scope that you could use to pass them to the children or a specific child of the slot:
<MenuItem>
<template #default="{ $attrs: slotAttrs }">
<button v-bind="slotAttrs" />
<button v-bind="slotAttrs" />
</template>
</MenuItem>
Addition idea to make slots more predictable:
Additionally, as a bonus to make component libraries more predicable and developer friendly it could be really cool to have a slot syntax for slots that expect only one element:
<slot-single />
Or maybe
<slot v-children="1" />
and possibly
<slot v-children="{ min: 2, , max: 10 }" />
where the v-children
can be used on any element and throw an error if the child count doesn't match the provided range.
Let me know what you think!