UNPKG

@isilin/react-slot

Version:

Simple and powerful typed slots for React components

147 lines (110 loc) 5.07 kB
# 📦 React Slot Components [![Storybook](https://img.shields.io/badge/Storybook-Live-purple?logo=storybook&logoColor=white)](https://isilin.github.io/react-slot/) [![Build Status](https://github.com/Isilin/react-slot/actions/workflows/deploy-storybook.yml/badge.svg)](https://github.com/Isilin/react-slot/actions/workflows/deploy-storybook.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 ❤️ [![Soutenir sur Ko-fi](https://img.shields.io/badge/Soutenir_sur_Ko--fi-F96400?logo=kofi&logoColor=white)](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. --- [![Made with Love](https://img.shields.io/badge/Made%20with-%E2%9D%A4-red)](https://github.com/Isilin) by [Isilin](https://github.com/Isilin)