Slots for preact, react and solid in under 0.2Kb.
Slots allow to define "holes" in your components that can be filled with JSX. Inspired by slots in Vue/Svelte/Angular/WebComponents.
npm i named-slotsSet the names of the slots you're using with defineSlots and use them in your JSX like <Slot name="slotName">, where want the slotted content to appear.
import{defineSlots}from"named-slots";exportconstCard=({ children })=>{const{ Slot }=defineSlots(children,["header","content","footer"]);return(<divclassName="card"><Slotname="header"></Slot><Slotname="content"><div>Fallback content</div></Slot><div><Slotname="footer">Fallback footer</Slot></div></div>);};Now you can slot content into your Card component. The only thing you need to do is set a slot="slotName" on the element you wish to slot in. To render only text or multiple elements, use the <template> element.
<Card><divslot="header">This div is not semantic</div><RandomComponentslot="content"/><templateslot="footer"><div>One</div><div>Two</div></template></Card>When defining a <Slot> the content inside of it will be treated as fallback, in case nothing is slotted inside of that slot. If you do not want anything to be rendered, self-close the slot tag <Slot name="nofallback" />.
<ActionBar> <Slot name="left" />{/* no fallback, will not render unless slotted*/} <Slot name="right">Loading...</Slot>{/* Will render "Loading..." until slotted */} </ActionBar> The defineSlots function handles the usage of slots. It takes the children prop of the component where it's used, and a string array of the slot names. If using Typescript add a as const to the string array so Typescript can check if the slot names are typed correctly.
defineSlots returns an object with the Slot component, but also a hasSlot function that allows to check if a slot has been slotted in, for conditional rendering.
exportconstDefinedCard=({ children }: {children: Slottable})=>{const{ Slot, hasSlot }=defineSlots(children,["header","content","footer"]asconst);consthasContent: boolean=hasSlot("content");Since solid does not use a VDOM it has a dedicated import.
import{Slot}from"named-slots/solid";In addition every element with slot needs to be an HTML element, not a Solid component (or wrapped in one like the <template>). In the example above, <RandomComponent slot="content" /> would not work. <div ="content"><RandomComponent slot="content" /></div> would.
Made with 🍕 in Amsterdam.