https://github.com/zemd/react-slottable
A lightweight concept to customize subcomponents in React
https://github.com/zemd/react-slottable
component-architecture react react-components slots
Last synced: about 1 year ago
JSON representation
A lightweight concept to customize subcomponents in React
- Host: GitHub
- URL: https://github.com/zemd/react-slottable
- Owner: zemd
- License: apache-2.0
- Created: 2024-02-25T15:08:53.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-04-05T12:09:36.000Z (about 1 year ago)
- Last Synced: 2025-04-05T13:22:18.326Z (about 1 year ago)
- Topics: component-architecture, react, react-components, slots
- Language: TypeScript
- Homepage:
- Size: 899 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# React Slottable for customizable components
> A lightweight concept to customize subcomponents in React
[](https://www.npmjs.com/package/@zemd/react-slottable)
The package provides a lightweight approach to give your component users ability to customize it's subcomponents easily. The idea is highly inspired by [Material-UI](https://mui.com/x/common-concepts/custom-components/).
## Usage
## Installation
```bash
npm install --save-dev @zemd/react-slottable
pnpm add -D @zemd/react-slottable
```
## Writing components
The core concept of the library is **slot**. A **slot** is a part of a component that can be overridden and/or customized. For example, you want to create a `Calendar`, but you do not want to create a numerous amount of props to customize nested components. Instead, you can divide your components on **slots** and provide your users with the ability to customize them.
Let's create a simple `Button` component with `startDecorator` and `endDecorator` slots to show how it works:
```tsx
import { type PropsWithSlots, useSlot } from "@zemd/react-slottable";
type ButtonProps = PropsWithSlots<
React.PropsWithChildren<{
// here you define your regular component props
fullWidth?: boolean;
disabled?: boolean;
size?: "sm" | "md" | "xl";
variant?: "solid" | "outlined";
color?: "primary" | "secondary";
className?: string;
}>,
["startDecorator", "endDecorator"] // here you define your slots
>;
const DefaultDecorator: React.FC<{ className?: string }> = ({ className }) => {
return
Default decorator;
};
export const Button: React.FC = (rootProps) => {
const { slots, slotProps, ...props } = rootProps;
const StartDecoratorSlot = useSlot("startDecorator", rootProps, {
slot: DefaultDecorator, // provide default decorator, but can be overridden by user
});
const EndDecoratorSlot = useSlot("startDecorator", rootProps);
return (
{/* ^^^ do not forget to handle not standard attributes, e.g. fullWidth ...*/}
{/* ^^^ you can provide default className ^^^ */}
{props.children}
);
};
```
Now your users can use this `Button`:
```tsx
const MyCustomLabelComponent: React.FC = () => {
return My custom label;
};
export function HomePage(): React.JSX.Element {
return (
Click me!
);
}
```
As you can see, `StartDecoratorSlot` was predefined with default component, which will be always shown until user overrides it. However, the `EndDecoratorSlot` was not predefined, so it will be empty until user provides a component for it.
## License
The `@zemd/react-slottable` is licensed under **[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0)** 😇.
## 💙 💛 Donate
[](https://u24.gov.ua/)