https://github.com/maybebot/named-slots
Named slots for preact
https://github.com/maybebot/named-slots
Last synced: 3 months ago
JSON representation
Named slots for preact
- Host: GitHub
- URL: https://github.com/maybebot/named-slots
- Owner: maybebot
- Created: 2025-03-03T19:37:39.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2025-03-15T11:40:26.000Z (3 months ago)
- Last Synced: 2025-03-15T12:26:20.516Z (3 months ago)
- Language: TypeScript
- Size: 8.79 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- fucking-awesome-angular - named-slots - Use declarative "holes" in your React components instead of an imperative prop-based approach. Inspired by slots in Vue/Svelte/Angular/WebComponents. (Table of contents / Third Party Components)
- awesome-angular - named-slots - Use declarative "holes" in your React components instead of an imperative prop-based approach. Inspired by slots in Vue/Svelte/Angular/WebComponents. (Table of contents / Third Party Components)
README
# named-slots 🦥
Slots for preact, react and solid in under 0.2Kb, unzipped, unminified
```sh
npm i named-slots
```Use declarative "holes" in your components with `` instead of an imperative prop based approach.
Inspired by slots in Vue/Svelte/Angular/WebComponents.Fill them with any Component or HTML element in the slot with the `slot` attribute: `
`. Use the `` element to render only the contents of it, typically text or multiple elements.See example below.
## Defining a Slot
| `Slot` props | |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `name` | name of the slot |
| `from` | always the `children` of where the `Slot` is defined, to give the Slot control over it |
| `children`/content | Fallback content for when nothing has been slotted in. If nothing is slotted, and no fallback is given, it will not render at all |Define Slots in the component where you want them them to render, for example a Card component, where you want a header, content and a footer.
```jsx
// Card.tsx
import { Slot, Slottable } from "named-slots";export const Card = ({ children }: { children: Slottable }) => {
// optionally validate slots during development, see defineSlots below
return (
{/* header has no fallback, renders only if slot is provided */}
Fallback content
Fallback footer
);
};
```## Consuming components with Slots
Now that the card accepts slots, you can insert them inside a `` with an slot attribute. Using the slot attribute on a `` element will render only the contents of the template.
```jsx
// Page.tsx
import { Slot } from "named-slots";
This div is not semantic
One
Two
;
```This will render the following html:
```html
This div is not semantic
Some content
I'm a footer
```## Solid.js
Since solid does not use a VDOM it has a dedicated import.
```ts
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 ``). In the example above, `` would not work. `
` would.## Type safety and validation
To type and validate slots it is recommended to use `defineSlots`, which returns a type-aware Slot component and provides runtime validation for slot usage, duplication and absence. Using `defineSlots` there is no need to specify `from={children}` on the Slots.
This is the recommended approach. The API is not the prettiest, requiring a Generic of the type and the values as well, but it provides extra security.
A third, optional, parameter can be passed to `defineSlots`, to improve debugging or to throw instead of console.logging. (example: `{ inComponent: Card, throws: true }`).
This will be stripped away in production to not add to the bundle (with a check on `process.env.NODE_ENV === "development"`).
```js
import { defineSlots, type Slottable } from "named-slots";export const Card = ({ children }: { children: Slottable }) => {
type CardSlots = "header" | "content" | "footer";
const Slot = defineSlots(children, ["header", "content", "footer"], { inComponent: Card, throws: true });
return (
Fallback content
Fallback footer
);
};
```Adding proper types and autocompletion for slot names during usage (not definition) has been a miserable failure so far, which is why runtime validation has been added.
---
Made with 🍕 in Amsterdam.