You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The package provides a way to create your components in a customizable, easy-to-use, and maintainable way. Zero dependencies.
8
-
9
-
With it, you can build your own complex component libraries, composing different components without losing control over their internals, providing a great developer experience to your team.
7
+
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/).
Just look at the example of such a `Button` built with the library:
20
+
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.
21
+
22
+
Let's create a simple `Button` component with `startDecorator` and `endDecorator` slots to show how it works:
{/* ^^^ do not forget to handle not standard attributes, e.g. fullWidth ...*/}
54
+
<StartDecoratorSlotclassName="class-override" />
55
+
{/* ^^^ you can provide default className ^^^ */}
56
+
{props.children}
57
+
<EndDecoratorSlot />
58
+
</button>
59
+
);
60
+
};
120
61
```
121
62
122
63
Now your users can use this `Button`:
123
64
124
-
```typescript
125
-
import { Button } from"./MyButton";
65
+
```tsx
66
+
const MyCustomLabelComponent:React.FC= () => {
67
+
return <span>My custom label</span>;
68
+
};
126
69
127
-
exportfunction HomePage() {
128
-
const buttonRef =useRef(null);
70
+
exportfunction HomePage():React.JSX.Element {
129
71
return (
130
72
<div>
131
73
<Button
132
-
// ref={buttonRef} // just in case if you need
133
-
startDecorator={<MySvgIcon />}
134
-
endDecorator={<span>no icon. just label.</span>}
135
74
slots={{
136
-
endDecorator: MyCustomLabelComponent
75
+
endDecorator: MyCustomLabelComponent,
137
76
}}
138
77
slotProps={{
139
78
startDecorator: {
140
-
prop1: "value"
141
-
}
79
+
prop1: "value",
80
+
},
142
81
}}
143
-
className:"my-custom-button-className"
82
+
className="my-custom-button-className"
144
83
>
145
84
Click me!
146
85
</Button>
@@ -149,7 +88,7 @@ export function HomePage() {
149
88
}
150
89
```
151
90
152
-
The package exposes three essential parts: `slottable`, the `useSlot` hook, and the `TSlottablePropsFactory` typescript type. Combining them together, you get a backbone for your fantastic components.
91
+
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.
The package provides a way to create your components in a customizable, easy-to-use, and maintainable way. Zero dependencies.
8
-
9
-
With it, you can build your own complex component libraries, composing different components without losing control over their internals, providing a great developer experience to your team.
7
+
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/).
10
8
11
9
## Usage
12
10
@@ -16,128 +14,69 @@ With it, you can build your own complex component libraries, composing different
16
14
17
15
## Writing components
18
16
19
-
Just look at the example of such a `Button` built with the library:
17
+
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.
18
+
19
+
Let's create a simple `Button` component with `startDecorator` and `endDecorator` slots to show how it works:
20
20
21
-
```typescript
22
-
import {
23
-
type TSlottablePropsFactory,
24
-
slottable,
25
-
useSlot,
26
-
clsx
27
-
} from "@zemd/react-slottable";
21
+
```tsx
22
+
import { type PropsWithSlots, useSlot } from "@zemd/react-slottable";
28
23
29
-
type TButtonProps = TSlottablePropsFactory<
30
-
{
24
+
type ButtonProps = PropsWithSlots<
25
+
React.PropsWithChildren<{
26
+
// here you define your regular component props
31
27
fullWidth?: boolean;
32
28
disabled?: boolean;
33
29
size?: "sm" | "md" | "xl";
34
30
variant?: "solid" | "outlined";
35
31
color?: "primary" | "secondary";
36
-
},
37
-
"startDecorator" | "endDecorator" // this is how cool you can define your slots
38
-
// in case you want control the type of slots explicitly, you can use an object:
{/* ^^^ do not forget to handle not standard attributes, e.g. fullWidth ...*/}
51
+
<StartDecoratorSlot className="class-override" />
52
+
{/* ^^^ you can provide default className ^^^ */}
53
+
{props.children}
54
+
<EndDecoratorSlot />
55
+
</button>
56
+
);
57
+
};
117
58
```
118
59
119
60
Now your users can use this `Button`:
120
61
121
-
```typescript
122
-
import { Button } from "./MyButton";
62
+
```tsx
63
+
const MyCustomLabelComponent: React.FC = () => {
64
+
return <span>My custom label</span>;
65
+
};
123
66
124
-
export function HomePage() {
125
-
const buttonRef = useRef(null);
67
+
export function HomePage(): React.JSX.Element {
126
68
return (
127
69
<div>
128
70
<Button
129
-
// ref={buttonRef} // just in case if you need
130
-
startDecorator={<MySvgIcon />}
131
-
endDecorator={<span>no icon. just label.</span>}
132
71
slots={{
133
-
endDecorator: MyCustomLabelComponent
72
+
endDecorator: MyCustomLabelComponent,
134
73
}}
135
74
slotProps={{
136
75
startDecorator: {
137
-
prop1: "value"
138
-
}
76
+
prop1: "value",
77
+
},
139
78
}}
140
-
className: "my-custom-button-className"
79
+
className="my-custom-button-className"
141
80
>
142
81
Click me!
143
82
</Button>
@@ -146,7 +85,7 @@ export function HomePage() {
146
85
}
147
86
```
148
87
149
-
The package exposes three essential parts: `slottable`, the `useSlot` hook, and the `TSlottablePropsFactory` typescript type. Combining them together, you get a backbone for your fantastic components.
88
+
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.
0 commit comments