Create polymorphic VueJS components with a customizable styled
function.
A polymorphic component is a component that can be rendered with a different element.
Known drawbacks for the type definitions:
Event handlers are not typed correctly when using the
as
prop.This is a deliberate decision to keep the usage as simple as possible.
npm install @polymorphic-factory/vue
or
yarn add @polymorphic-factory/vue
or
pnpm install @polymorphic-factory/vue
Import the polymorphic factory and create your element factory.
import { polymorphicFactory } from '@polymorphic-factory/vue'
const poly = polymorphicFactory()
You can override the default implementation by passing styled
function in the options.
import { defineComponent } from 'vue'
const poly = polymorphicFactory({
styled: (originalComponent, options) =>
defineComponent({
props: ['as'],
setup(props, { slots, attrs }) {
const component = props.as || originalComponent
return () =>
h(
component,
{ 'data-custom-styled': true, 'data-options': JSON.stringify(options), ...attrs },
slots,
)
},
}),
})
const WithOptions = poly('div', { hello: 'world' })
const App = () => {
return (
<>
<poly.div hello="world" />
{/* renders <div data-custom-styled hello="world" /> */}
<WithOptions />
{/* renders <div data-custom-styled data-options="{ \"hello\": \"world\" }" /> */}
</>
)
}
Use the element factory to create elements inline.
Every JSX element is supported div
, main
, aside
, etc.
<>
<poly.div />
<poly.main>
<poly.section>
<poly.div as="p">This is rendered as a p element</poly.div>
</poly.section>
</poly.main>
</>
Use the factory to wrap custom components.
const OriginalComponent = defineComponent({
setup(props) {
return () => <div data-original="true" {...props} />
},
})
const MyComponent = poly(OriginalComponent)
const App = h(MyComponent)
// render <div data-original="true" />
It still supports the as
prop, which would replace the OriginalComponent
.
<MyComponent as="div" />
// renders <div />
import type { HTMLPolymorphicComponents, HTMLPolymorphicProps } from '@polymorphic-factory/vue'
type PolymorphicDiv = HTMLPolymorphicComponents['div']
type DivProps = HTMLPolymorphicProps<'div'>
MIT © Tim Kolberger