@isilin/react-slot
Version:
Simple and powerful typed slots for React components
147 lines (110 loc) • 5.07 kB
Markdown
# 📦 React Slot Components
[](https://isilin.github.io/react-slot/)
[](https://github.com/Isilin/react-slot/actions/workflows/deploy-storybook.yml)
[](https://opensource.org/licenses/MIT)
**Create reusable React components with simple, typed, and powerful slots.**
---
## 🗺️ Table of Contents
- [📦 React Slot Components](#-react-slot-components)
- [🗺️ Table of Contents](#️-table-of-contents)
- [🧪 Try the Project](#-try-the-project)
- [🛠️ Prerequisites](#️-prerequisites)
- [📚 Install and Run Storybook](#-install-and-run-storybook)
- [🧩 The "Slot" Pattern in React](#-the-slot-pattern-in-react)
- [📘 Why Use Slots?](#-why-use-slots)
- [📦 Example: `Card` Component with Slots](#-example-card-component-with-slots)
- [🧪 Usage](#-usage)
- [📚 Additional Resources](#-additional-resources)
- [☕ Support this Project](#-support-this-project)
- [🪪 Licence](#-licence)
- [🤝 Contributing](#-contributing)
---
## 🧪 Try the Project
### 🛠️ Prerequisites
- Node.js (recommended version: >=18.x)
- Yarn or npm
### 📚 Install and Run Storybook
```bash
npm install
npm run dev
# ou
yarn install
yarn dev
```
This will open Storybook at [http://localhost:6006](http://localhost:6006).
## 🧩 The "Slot" Pattern in React
The slot pattern is an approach inspired by advanced libraries like [Radix UI](https://www.radix-ui.com/) and [Headless UI](https://headlessui.dev/). It allows dynamic content injection into a component while preserving structure and encapsulated logic.
### 📘 Why Use Slots?
- Build a clear and declarative API
- Offer complete flexibility to component users
- Add or remove optional parts without breaking the component
- Separate structure from content
- Create reusable and composable components
- Provide explicit injection points for content
### 📦 Example: `Card` Component with Slots
```tsx
// Card.tsx
import { PropsWithChildren } from 'react';
import { defineSlotComponent, getSlots } from '../../lib';
import classNames from 'classnames/bind';
import styles from './Card.module.css';
const cx = classNames.bind(styles);
export const Card = defineSlotComponent(
({ children }: PropsWithChildren) => {
const { body, footer, header } = getSlots(children, Card);
return (
<div className={cx('card')}>
{header && <div className={cx('card-header')}>{header}</div>}
{header && (body || footer) && <Card.Separator />}
{body && <div className={cx('card-body')}>{body}</div>}
{body && footer && <Card.Separator />}
{footer && <div className={cx('card-footer')}>{footer}</div>}
</div>
);
},
{
slots: {
header: ({ children }: PropsWithChildren) => <>{children}</>,
body: ({ children }: PropsWithChildren) => <>{children}</>,
footer: ({ children }: PropsWithChildren) => <>{children}</>,
},
extras: {
Separator: () => <span className={cx('separator')} />,
},
},
);
```
### 🧪 Usage
```tsx
// App.tsx
export const App = () => {
return (
<Card>
<Card.Header>Ma jolie carte</Card.Header>
<Card.Body>
Ceci est le contenu principal de la carte. Tu peux y mettre n'importe
quoi : du texte, des images, ou même d'autres composants.
</Card.Body>
<Card.Footer>Dernière mise à jour : aujourd’hui.</Card.Footer>
</Card>
);
};
```
Under the hood, each slot (`Header`, `Footer`, `Content`, etc.) is automatically detected and placed in the right structure.
## 📚 Additional Resources
- [React Composition Patterns – Kent C. Dodds](https://kentcdodds.com/blog/compound-components-with-react-hooks)
- [What is the React Slots pattern ? - Neetigya Chahar](https://dev.to/neetigyachahar/what-is-the-react-slots-pattern-2ld9)
- [Concevoir vos composants React avec des slots multiples - Maxime Steinhausser](https://www.elao.com/blog/dev/react-component-slots)
- [Building Component Slots in React - Sandro Roth](https://sandroroth.com/blog/react-slots/)
- [Storybook Docs](https://storybook.js.org/docs/react/get-started/introduction)
Feel free to explore the component live in Storybook to better understand how the slots are used!
## ☕ Support this Project
If you like this project, you can support me on Ko-fi ❤️
[](https://ko-fi.com/isilin)
## 🪪 Licence
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
## 🤝 Contributing
Contributions are welcome!
Feel free to open an issue or submit a pull request.
---
[](https://github.com/Isilin) by [Isilin](https://github.com/Isilin)