Create polymorphic Preact components with a customizable styled
function.
A polymorphic component is a component that can be rendered with a different element. This is useful for component libraries that want to provide a consistent API for their users and want to allow them to customize the underlying element.
npm install @polymorphic-factory/preact
or
yarn add @polymorphic-factory/preact
or
pnpm install @polymorphic-factory/preact
Import the polymorphic factory and create your element factory.
import { polymorphicFactory } from '@polymorphic-factory/preact'
const poly = polymorphicFactory()
You can override the default implementation by passing styled
function in the options.
const poly = polymorphicFactory({
styled: (component, options) => (props) => {
const Component = props.as || component
return <Component data-custom-styled data-options={JSON.stringify(options)} {...props} />
},
})
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 = (props) => <div data-original="true" {...props}></div>
const MyComponent = poly(OriginalComponent)
const App = () => <MyComponent />
// render <div data-original="true" />
It still supports the as
prop, which would replace the OriginalComponent
.
<MyComponent as="div" />
// renders <div />
You can use ref
on the component, and it will have the correct typings.
const App = () => {
const ref = useRef<HTMLAnchorElement>(null)
return <poly.button as="a" ref={ref} />
}
import type { HTMLPolymorphicComponents, HTMLPolymorphicProps } from '@polymorphic-factory/preact'
type PolymorphicDiv = HTMLPolymorphicComponents['div']
type DivProps = HTMLPolymorphicProps<'div'>
MIT © Tim Kolberger