Pass-through
Reach any element of any component: attributes, classes, or a function of that part’s state.
Every element a component renders carries one call: v-bind="part('name', state)". That call is what merges the theme's classes, the reader's pass-through and the part's state, so anything the component draws can be reached without a fork, a wrapper or a :deep() selector.
Three shapes
<!-- attributes on a part -->
<Select :pt="{ overlay: { style: 'min-width: 20rem' } }" />
<!-- a bare string is taken as a class -->
<Button :pt="{ root: 'rounded-full shadow-lg' }" />
<!-- a function of the part's context -->
<Select
:pt="{
option: ({ state }) => ({ class: state.selected ? 'font-semibold' : '' })
}"
/> The string shorthand is there for utility CSS: { root: 'px-4 py-2 rounded bg-violet-600' } is all a Tailwind user needs to write. The function form receives { props, state, part }, where state is whatever the component passed for that element, such as { selected, focused } for an option.
It merges, not replaces
Classes are concatenated, styles merged and listeners chained, so a pass-through class sits beside the theme's rather than deleting it. To start from nothing, see unstyled mode.
Live
<Select
v-model="city"
:options="cities"
option-label="name"
option-value="code"
placeholder="Where"
:pt="{
root: { style: 'min-width: 14rem' },
label: { style: 'letter-spacing: 0.04em; text-transform: uppercase' },
dropdown: { style: 'color: var(--vt-primary-color)' }
}"
/>Globally
The same object, keyed by component name, applies to every instance. That is the hook for an analytics attribute or a house rule.
createApp(App).use(Vitral, {
pt: {
button: { root: { 'data-analytics': 'button' } },
select: { overlay: 'shadow-xl' }
}
});Which parts exist
A component's parts are the keys of its class map in @vitral/styles: root, and then whatever it draws, such as label, dropdown, overlay, option. They are also its CSS class names, minus the vt- prefix, so the DOM inspector is the reference.