@dgshahr/ui-kit 1.9.8 → 1.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INTEGRATION.md +1034 -0
- package/README.md +4 -0
- package/dist/Alert/index.d.ts +1 -1
- package/dist/Alert/index.d.ts.map +1 -1
- package/dist/Badge/index.d.ts +1 -1
- package/dist/Badge/index.d.ts.map +1 -1
- package/dist/Breadcrumb/index.d.ts +1 -1
- package/dist/Breadcrumb/index.d.ts.map +1 -1
- package/dist/Button/index.d.ts.map +1 -1
- package/dist/{DateAndTimePickerFooter-O7VW4RUW.cjs → DateAndTimePickerFooter-D-DVvBp_.cjs} +1 -1
- package/dist/{DateAndTimePickerFooter-DvYgk9Qh.js → DateAndTimePickerFooter-D5-DDqkr.js} +1 -1
- package/dist/Divider/index.d.ts +1 -1
- package/dist/Divider/index.d.ts.map +1 -1
- package/dist/Form/Checkbox/index.d.ts +1 -1
- package/dist/Form/Checkbox/index.d.ts.map +1 -1
- package/dist/Form/Common/FieldBottomInfo/FieldBottomInfo.d.ts +1 -1
- package/dist/Form/Common/FieldBottomInfo/FieldBottomInfo.d.ts.map +1 -1
- package/dist/Form/Datepicker/index.cjs +1 -1
- package/dist/Form/Datepicker/index.mjs +1 -1
- package/dist/Form/FileUploader/Preview/utils.d.ts +1 -1
- package/dist/Form/FileUploader/Preview/utils.d.ts.map +1 -1
- package/dist/Form/FileUploader/types.d.ts.map +1 -1
- package/dist/Form/Input/index.cjs +1 -1
- package/dist/Form/Input/index.d.ts.map +1 -1
- package/dist/Form/Input/index.mjs +2 -2
- package/dist/Form/OtpInput/index.cjs +1 -1
- package/dist/Form/OtpInput/index.mjs +2 -2
- package/dist/Form/RadioButton/index.d.ts +1 -1
- package/dist/Form/RadioButton/index.d.ts.map +1 -1
- package/dist/Form/RangeInput/Thumb.d.ts.map +1 -1
- package/dist/Form/RangeInput/index.d.ts +1 -1
- package/dist/Form/RangeInput/index.d.ts.map +1 -1
- package/dist/Form/Select/OptionItem.d.ts +1 -1
- package/dist/Form/Select/OptionItem.d.ts.map +1 -1
- package/dist/Form/Select/Options.d.ts +1 -1
- package/dist/Form/Select/Options.d.ts.map +1 -1
- package/dist/Form/Select/index.cjs +1 -1
- package/dist/Form/Select/index.d.ts +1 -1
- package/dist/Form/Select/index.d.ts.map +1 -1
- package/dist/Form/Select/index.mjs +2 -2
- package/dist/Form/Textarea/index.cjs +1 -1
- package/dist/Form/Textarea/index.d.ts.map +1 -1
- package/dist/Form/Textarea/index.mjs +1 -1
- package/dist/Form/Timepicker/index.cjs +1 -1
- package/dist/Form/Timepicker/index.mjs +2 -2
- package/dist/Form/Wrappers/TextFieldWrapper/TextFieldWrapper.d.ts +1 -0
- package/dist/Form/Wrappers/TextFieldWrapper/TextFieldWrapper.d.ts.map +1 -1
- package/dist/Pagination/index.d.ts +1 -1
- package/dist/Pagination/index.d.ts.map +1 -1
- package/dist/Pagination/utils.d.ts.map +1 -1
- package/dist/{PickerWrapper-DkRUahWD.cjs → PickerWrapper-DGyaWUvQ.cjs} +1 -1
- package/dist/{PickerWrapper-Bwdfzr3U.js → PickerWrapper-Dh1cWCNJ.js} +1 -1
- package/dist/Progress/Step/index.cjs +1 -0
- package/dist/Progress/Step/index.d.ts +18 -0
- package/dist/Progress/Step/index.d.ts.map +1 -0
- package/dist/Progress/Step/index.mjs +161 -0
- package/dist/Sidebar/Profile.d.ts +1 -1
- package/dist/Sidebar/Profile.d.ts.map +1 -1
- package/dist/Sidebar/index.cjs +1 -1
- package/dist/Sidebar/index.mjs +1 -1
- package/dist/Sidebar/utils.d.ts +1 -1
- package/dist/Sidebar/utils.d.ts.map +1 -1
- package/dist/{Slide-CV7KzC_T.js → Slide-D-2O9kS6.js} +5 -5
- package/dist/Slider/NavigationDot.d.ts +1 -1
- package/dist/Slider/NavigationDot.d.ts.map +1 -1
- package/dist/Slider/index.mjs +1 -1
- package/dist/{Step-DB73tIkY.js → Step-BQAozGAS.js} +5 -5
- package/dist/Stepper/Horizontal/index.mjs +1 -1
- package/dist/Table/context.d.ts +1 -1
- package/dist/Table/context.d.ts.map +1 -1
- package/dist/Table/index.d.ts +2 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/utils.d.ts +1 -1
- package/dist/Table/utils.d.ts.map +1 -1
- package/dist/{TextFieldWrapper-3DRVoeki.js → TextFieldWrapper-CXoA32wk.js} +24 -22
- package/dist/TextFieldWrapper-OdBa53gf.cjs +1 -0
- package/dist/Tooltip/Content.d.ts.map +1 -1
- package/dist/assets/styles.css +1 -1
- package/dist/index-B00RqlIS.cjs +1 -0
- package/dist/{index-Ccf1HAfZ.js → index-mNB7iXgB.js} +6 -5
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +3 -3
- package/package.json +9 -2
- package/dist/TextFieldWrapper-DKMhxMuC.cjs +0 -1
- package/dist/index-IPoPOLW2.cjs +0 -1
package/INTEGRATION.md
ADDED
|
@@ -0,0 +1,1034 @@
|
|
|
1
|
+
# @dgshahr/ui-kit — Integration Guide
|
|
2
|
+
|
|
3
|
+
Reference for integrating `@dgshahr/ui-kit` into a React project. Written for both humans and AI coding agents (Claude Code, Cursor, Copilot, Windsurf, etc.). This file ships inside the npm package at `node_modules/@dgshahr/ui-kit/INTEGRATION.md`.
|
|
4
|
+
|
|
5
|
+
- Storybook (live demos): https://dgshahr.github.io/uikit/
|
|
6
|
+
- Source: https://github.com/dgshahr/uikit
|
|
7
|
+
- TypeScript declarations (source of truth for props): `node_modules/@dgshahr/ui-kit/dist/**/index.d.ts`
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
1. [Overview](#overview)
|
|
12
|
+
2. [Installation](#installation)
|
|
13
|
+
3. [Imports](#imports)
|
|
14
|
+
4. [Next.js / SSR](#nextjs--ssr)
|
|
15
|
+
5. [Theming](#theming)
|
|
16
|
+
6. [Component reference](#component-reference)
|
|
17
|
+
7. [Rules for AI agents](#rules-for-ai-agents)
|
|
18
|
+
8. [Agent setup snippets](#agent-setup-snippets)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Overview
|
|
23
|
+
|
|
24
|
+
- React component library written in TypeScript.
|
|
25
|
+
- Styled with Tailwind CSS v4 using the scoped prefix `dgsuikit:`. Styles are **pre-compiled and auto-injected** when a component is imported — no Tailwind, PostCSS or global CSS import needed in the consumer project.
|
|
26
|
+
- RTL-first: text inputs default to `dir="rtl"`; the Datepicker uses the Jalali (Persian) calendar.
|
|
27
|
+
- Colors are driven by CSS variables (`--dgs-color-*`) and can be overridden globally.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @dgshahr/ui-kit
|
|
33
|
+
# or
|
|
34
|
+
yarn add @dgshahr/ui-kit
|
|
35
|
+
# or
|
|
36
|
+
pnpm add @dgshahr/ui-kit
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Peer dependencies: `react >= 18.2.0`, `react-dom >= 18.2.0`.
|
|
40
|
+
|
|
41
|
+
## Imports
|
|
42
|
+
|
|
43
|
+
Two equivalent styles:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
// 1. Root named import
|
|
47
|
+
import { Button, Input, Select } from '@dgshahr/ui-kit';
|
|
48
|
+
|
|
49
|
+
// 2. Per-component subpath (default export) — smaller bundles
|
|
50
|
+
import Button from '@dgshahr/ui-kit/Button';
|
|
51
|
+
import Input from '@dgshahr/ui-kit/Form/Input';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| Component | Root named export | Subpath |
|
|
55
|
+
| ---------------- | ------------------------------------- | -------------------------------------------- |
|
|
56
|
+
| Accordion | `AccordionGroup`, `AccordionItem` | `@dgshahr/ui-kit/Accordion` (named) |
|
|
57
|
+
| Alert | `Alert` | `@dgshahr/ui-kit/Alert` |
|
|
58
|
+
| Badge | `Badge` | `@dgshahr/ui-kit/Badge` |
|
|
59
|
+
| Breadcrumb | `Breadcrumb` | `@dgshahr/ui-kit/Breadcrumb` |
|
|
60
|
+
| Button | `Button` | `@dgshahr/ui-kit/Button` |
|
|
61
|
+
| Card | `Card` | `@dgshahr/ui-kit/Card` |
|
|
62
|
+
| Chip | `Chip` | `@dgshahr/ui-kit/Chip` |
|
|
63
|
+
| Divider | `Divider` | `@dgshahr/ui-kit/Divider` |
|
|
64
|
+
| Drawer | `Drawer` | `@dgshahr/ui-kit/Drawer` |
|
|
65
|
+
| Checkbox | `Checkbox` | `@dgshahr/ui-kit/Form/Checkbox` |
|
|
66
|
+
| Datepicker | `Datepicker` | `@dgshahr/ui-kit/Form/Datepicker` |
|
|
67
|
+
| FileUploader | `FileUploader` | `@dgshahr/ui-kit/Form/FileUploader` |
|
|
68
|
+
| Input | `Input` | `@dgshahr/ui-kit/Form/Input` |
|
|
69
|
+
| OtpInput | `OtpInput` | `@dgshahr/ui-kit/Form/OtpInput` |
|
|
70
|
+
| RadioButton | `RadioButton` | `@dgshahr/ui-kit/Form/RadioButton` |
|
|
71
|
+
| RangeInput | `RangeInput` | `@dgshahr/ui-kit/Form/RangeInput` |
|
|
72
|
+
| Select | `Select` | `@dgshahr/ui-kit/Form/Select` |
|
|
73
|
+
| Switch | `Switch` | `@dgshahr/ui-kit/Form/Switch` |
|
|
74
|
+
| Textarea | `Textarea` | `@dgshahr/ui-kit/Form/Textarea` |
|
|
75
|
+
| Timepicker | `Timepicker` | `@dgshahr/ui-kit/Form/Timepicker` |
|
|
76
|
+
| Menu | `Menu` (+ `Menu.Item`) | `@dgshahr/ui-kit/Menu` |
|
|
77
|
+
| Pagination | `Pagination` | `@dgshahr/ui-kit/Pagination` |
|
|
78
|
+
| ProgressBar | `ProgressBar` | `@dgshahr/ui-kit/Progress/Bar` |
|
|
79
|
+
| ProgressDoughnut | `ProgressDoughnut` | `@dgshahr/ui-kit/Progress/Doughnut` |
|
|
80
|
+
| ProgressStep | — (subpath only) | `@dgshahr/ui-kit/Progress/Step` |
|
|
81
|
+
| Rate | `Rate` | `@dgshahr/ui-kit/Rate` |
|
|
82
|
+
| Sidebar | `Sidebar` | `@dgshahr/ui-kit/Sidebar` |
|
|
83
|
+
| Slider | `Slider`, `Slide` | `@dgshahr/ui-kit/Slider` (named) |
|
|
84
|
+
| Stepper | `HorizontalStepper`, `HorizontalStep` | `@dgshahr/ui-kit/Stepper/Horizontal` (named) |
|
|
85
|
+
| Table | `Table` | `@dgshahr/ui-kit/Table` |
|
|
86
|
+
| Tabs | `Tabs` | `@dgshahr/ui-kit/Tabs` |
|
|
87
|
+
| Tooltip | `Tooltip` | `@dgshahr/ui-kit/Tooltip` |
|
|
88
|
+
|
|
89
|
+
Form components live under `Form/` in subpaths (`@dgshahr/ui-kit/Form/Input`, **not** `@dgshahr/ui-kit/Input`).
|
|
90
|
+
|
|
91
|
+
Prop types are exported from the component modules, e.g. `import type { ButtonProps } from '@dgshahr/ui-kit/Button'`.
|
|
92
|
+
|
|
93
|
+
## Next.js / SSR
|
|
94
|
+
|
|
95
|
+
- Works with the Next.js App Router and Pages Router. No `transpilePackages` needed.
|
|
96
|
+
- Interactive components (inputs, pickers, Select, Drawer, Tooltip, Menu, Slider, Table, Tabs, Switch, etc.) use React state/effects. In the App Router, render them from a Client Component (`'use client'` at the top of your file).
|
|
97
|
+
- Portal-based components (Drawer, pickers in popover/drawer mode, Tooltip with `attachToBody`) access `document` only on the client.
|
|
98
|
+
|
|
99
|
+
## Theming
|
|
100
|
+
|
|
101
|
+
Every color is a CSS variable holding **space-separated RGB numbers** (not hex):
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
--dgs-color-{palette}-{shade}: {r} {g} {b};
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Palettes: `primary`, `secondary`, `gray`, `success`, `error`, `warning`, `sky`, `violet`, `flamingo`.
|
|
108
|
+
Shades: `50 100 200 300 400 500 600 700 800 900`.
|
|
109
|
+
|
|
110
|
+
Override in your global CSS:
|
|
111
|
+
|
|
112
|
+
```css
|
|
113
|
+
:root {
|
|
114
|
+
--dgs-color-primary-500: 16 185 143;
|
|
115
|
+
--dgs-color-primary-600: 12 160 124;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Scope overrides to a subtree by setting the variables on any ancestor selector instead of `:root`.
|
|
120
|
+
|
|
121
|
+
Styling individual components: nearly every component accepts `className` and often more specific slots (`wrapperClassName`, `containerClassName`, `popoverClassName`, …). Use your own CSS/Tailwind classes there.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Component reference
|
|
126
|
+
|
|
127
|
+
Legend: **bold** prop name = required. `Default` column shows the runtime default when one exists. Unless stated otherwise, `className` applies to the outermost element.
|
|
128
|
+
|
|
129
|
+
### AccordionGroup / AccordionItem
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { AccordionGroup, AccordionItem } from '@dgshahr/ui-kit';
|
|
133
|
+
|
|
134
|
+
<AccordionGroup defaultActiveKey="a">
|
|
135
|
+
<AccordionItem
|
|
136
|
+
accordionKey="a"
|
|
137
|
+
title="Shipping"
|
|
138
|
+
>
|
|
139
|
+
…
|
|
140
|
+
</AccordionItem>
|
|
141
|
+
<AccordionItem
|
|
142
|
+
accordionKey="b"
|
|
143
|
+
title="Returns"
|
|
144
|
+
>
|
|
145
|
+
…
|
|
146
|
+
</AccordionItem>
|
|
147
|
+
</AccordionGroup>;
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`AccordionGroup`
|
|
151
|
+
|
|
152
|
+
| Prop | Type | Default | Notes |
|
|
153
|
+
| ---------------- | -------------------- | ------- | -------------------------------- |
|
|
154
|
+
| defaultActiveKey | `string \| string[]` | | Initially open item key(s) |
|
|
155
|
+
| disableAccordion | `boolean` | `false` | Allow several items open at once |
|
|
156
|
+
| className | `string` | | |
|
|
157
|
+
| children | `ReactNode` | | `AccordionItem` elements |
|
|
158
|
+
|
|
159
|
+
`AccordionItem`
|
|
160
|
+
|
|
161
|
+
| Prop | Type | Default |
|
|
162
|
+
| ---------------- | ----------- | ------- |
|
|
163
|
+
| **title** | `ReactNode` | |
|
|
164
|
+
| accordionKey | `string` | |
|
|
165
|
+
| disable | `boolean` | |
|
|
166
|
+
| hideDivider | `boolean` | `false` |
|
|
167
|
+
| hideArrow | `boolean` | `false` |
|
|
168
|
+
| className | `string` | |
|
|
169
|
+
| titleClassName | `string` | |
|
|
170
|
+
| contentClassName | `string` | |
|
|
171
|
+
| children | `ReactNode` | |
|
|
172
|
+
|
|
173
|
+
### Alert
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<Alert
|
|
177
|
+
variant="warning"
|
|
178
|
+
title="Heads up"
|
|
179
|
+
text="Your session expires in 5 minutes."
|
|
180
|
+
primaryButton={{ text: 'Extend', onClick: extend }}
|
|
181
|
+
closable
|
|
182
|
+
/>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Prop | Type | Default |
|
|
186
|
+
| ------------- | ------------------------------------------------------------------------ | ----------- |
|
|
187
|
+
| **text** | `ReactNode` | |
|
|
188
|
+
| variant | `'warning' \| 'primary' \| 'error' \| 'success' \| 'gray'` | `'primary'` |
|
|
189
|
+
| size | `'large' \| 'small'` | `'small'` |
|
|
190
|
+
| title | `string` | |
|
|
191
|
+
| primaryButton | `ButtonProps` (without variant/color/size/children) & `{ text: string }` | |
|
|
192
|
+
| outlineButton | same as `primaryButton` | |
|
|
193
|
+
| closable | `boolean` | |
|
|
194
|
+
| showTitleIcon | `boolean` | `true` |
|
|
195
|
+
| className | `string` | |
|
|
196
|
+
|
|
197
|
+
### Badge
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<Badge value="New" color="success" type="twoTone" />
|
|
201
|
+
<Badge valueType="number" value={12} />
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Prop | Type | Default |
|
|
205
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------ | ----------- |
|
|
206
|
+
| **value** | `string \| number` | |
|
|
207
|
+
| type | `'twoTone' \| 'solid'` | `'solid'` |
|
|
208
|
+
| color | `'primary' \| 'secondary' \| 'gray' \| 'success' \| 'error' \| 'warning' \| 'sky' \| 'violet' \| 'flamingo'` | `'primary'` |
|
|
209
|
+
| size | `'small' \| 'medium' \| 'large'` | `'medium'` |
|
|
210
|
+
| valueType | `'text' \| 'number'` | `'text'` |
|
|
211
|
+
| width | `string \| number` | |
|
|
212
|
+
| leftIcon / rightIcon | `ReactNode` — only when `valueType` is `'text'` | |
|
|
213
|
+
| icon | `ReactNode` — **deprecated**, use `leftIcon`/`rightIcon` | |
|
|
214
|
+
| className | `string` | `''` |
|
|
215
|
+
|
|
216
|
+
### Breadcrumb
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<Breadcrumb
|
|
220
|
+
pageTitle="Order #123"
|
|
221
|
+
items={[
|
|
222
|
+
{ title: 'Home', link: '/' },
|
|
223
|
+
{ title: 'Orders', onClick: () => router.push('/orders') },
|
|
224
|
+
]}
|
|
225
|
+
/>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Prop | Type |
|
|
229
|
+
| --------- | ------------------ |
|
|
230
|
+
| **items** | `BreadcrumbItem[]` |
|
|
231
|
+
| pageTitle | `string` |
|
|
232
|
+
| className | `string` |
|
|
233
|
+
|
|
234
|
+
`BreadcrumbItem = { title: string; icon?: ReactNode } & ({ link: string } | { onClick: () => void })` — provide exactly one of `link` / `onClick`.
|
|
235
|
+
|
|
236
|
+
### Button
|
|
237
|
+
|
|
238
|
+
Extends all native `<button>` attributes.
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
<Button
|
|
242
|
+
variant="outline"
|
|
243
|
+
color="error"
|
|
244
|
+
size="small"
|
|
245
|
+
leftIcon={<TrashIcon />}
|
|
246
|
+
isLoading={pending}
|
|
247
|
+
>
|
|
248
|
+
Delete
|
|
249
|
+
</Button>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
| Prop | Type | Default |
|
|
253
|
+
| -------------------- | ---------------------------------------------------------- | ----------- |
|
|
254
|
+
| variant | `'primary' \| 'secondary' \| 'outline' \| 'text'` | `'primary'` |
|
|
255
|
+
| color | `'primary' \| 'warning' \| 'error' \| 'success' \| 'gray'` | `'primary'` |
|
|
256
|
+
| size | `'small' \| 'medium' \| 'large'` | |
|
|
257
|
+
| isFullWidth | `boolean` | |
|
|
258
|
+
| isLoading | `boolean` | |
|
|
259
|
+
| leftIcon / rightIcon | `JSX.Element` | |
|
|
260
|
+
| …native | `ButtonHTMLAttributes<HTMLButtonElement>` | |
|
|
261
|
+
|
|
262
|
+
### Card
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
<Card
|
|
266
|
+
color="primary"
|
|
267
|
+
header={{ title: 'Summary', icon: <InfoIcon />, Element: <Button size="small">Edit</Button> }}
|
|
268
|
+
>
|
|
269
|
+
…
|
|
270
|
+
</Card>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
| Prop | Type | Default |
|
|
274
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
|
|
275
|
+
| **children** | `ReactNode` | |
|
|
276
|
+
| size | `'small' \| 'medium'` | `'medium'` |
|
|
277
|
+
| color | `'primary' \| 'warning' \| 'error' \| 'success' \| 'gray' \| 'white'` | `'white'` |
|
|
278
|
+
| header | `{ title?: string; icon?: ReactNode; variant?: 'primary' \| 'default'; Element?: ReactNode; color?: CardColor; className?: string }` | |
|
|
279
|
+
| className | `string` | |
|
|
280
|
+
| wrapperClassName | `string` | |
|
|
281
|
+
|
|
282
|
+
### Chip
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
<Chip
|
|
286
|
+
label="Filter"
|
|
287
|
+
clickable
|
|
288
|
+
isActive={active}
|
|
289
|
+
onClick={toggle}
|
|
290
|
+
/>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
| Prop | Type | Default |
|
|
294
|
+
| -------------------- | --------------------------------------------------------------------------------------- | ----------- |
|
|
295
|
+
| **label** | `string \| ReactNode` | |
|
|
296
|
+
| size | `'xsmall' \| 'small' \| 'large'` | `'small'` |
|
|
297
|
+
| color | `'primary' \| 'gray'` | `'primary'` |
|
|
298
|
+
| filled | `boolean` | |
|
|
299
|
+
| isActive | `boolean` | |
|
|
300
|
+
| disabled | `boolean` | |
|
|
301
|
+
| badgeNumber | `number` | |
|
|
302
|
+
| leftIcon / rightIcon | `ReactNode` | `null` |
|
|
303
|
+
| clickable | `boolean` — `true` renders a `<button>` (button attrs); otherwise a `<div>` (div attrs) | |
|
|
304
|
+
|
|
305
|
+
### Divider
|
|
306
|
+
|
|
307
|
+
| Prop | Type | Default |
|
|
308
|
+
| --------- | ---------------------------- | -------- |
|
|
309
|
+
| **type** | `'horizontal' \| 'vertical'` | |
|
|
310
|
+
| size | `'thin' \| 'thick'` | `'thin'` |
|
|
311
|
+
| color | `'white' \| 'gray'` | `'gray'` |
|
|
312
|
+
| className | `string` | |
|
|
313
|
+
|
|
314
|
+
### Drawer
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
<Drawer
|
|
318
|
+
open={open}
|
|
319
|
+
onClose={() => setOpen(false)}
|
|
320
|
+
position="right"
|
|
321
|
+
header={{ title: 'Filters', haveCloseIcon: true }}
|
|
322
|
+
footer={{ element: <Button isFullWidth>Apply</Button> }}
|
|
323
|
+
>
|
|
324
|
+
…
|
|
325
|
+
</Drawer>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
| Prop | Type | Default |
|
|
329
|
+
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
330
|
+
| **open** | `boolean` | |
|
|
331
|
+
| **onClose** | `() => void` | |
|
|
332
|
+
| position | `'bottom' \| 'top' \| 'right' \| 'left' \| 'center'` | `'bottom'` |
|
|
333
|
+
| persist | `boolean` — clicking the mask does not close the drawer | |
|
|
334
|
+
| padding | `number` | `8` |
|
|
335
|
+
| width | `CSSProperties['width']` | |
|
|
336
|
+
| header | `{ title?: string; description?: string; haveCloseIcon?: boolean; actionElement?: ReactNode; containerClassName?: string }` | |
|
|
337
|
+
| footer | `{ element?: ReactNode; containerClassName?: string }` | |
|
|
338
|
+
| containerElement | `Element \| null` — portal target | |
|
|
339
|
+
| havePopover | `boolean` | |
|
|
340
|
+
| className / maskClassName / containerClassName | `string` | |
|
|
341
|
+
| children | `ReactNode` | |
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
### Form: shared field props
|
|
346
|
+
|
|
347
|
+
`Input`, `Textarea`, `OtpInput` (and `inputProps` of pickers/Select) share these **text-field props**:
|
|
348
|
+
|
|
349
|
+
| Prop | Type | Default | Notes |
|
|
350
|
+
| -------------------- | ----------------------------------- | ------- | --------------------------------------------------- |
|
|
351
|
+
| labelContent | `string` | | Label text |
|
|
352
|
+
| labelAddon | `ReactNode` | | Extra node next to label |
|
|
353
|
+
| link | `{ cnotent: string; href: string }` | | Link next to label (note: key is spelled `cnotent`) |
|
|
354
|
+
| required | `boolean` | | Shows required marker |
|
|
355
|
+
| disabled | `boolean` | | |
|
|
356
|
+
| isError | `boolean` | | Error styling |
|
|
357
|
+
| errorMessage | `ReactNode` | | |
|
|
358
|
+
| hintMessage | `ReactNode` | | |
|
|
359
|
+
| hintMessageClassName | `string` | | |
|
|
360
|
+
| showMaxLength | `boolean` | | Shows `value.length / maxLength` counter |
|
|
361
|
+
| rightIcon | `JSX.Element` | | |
|
|
362
|
+
| dir | `'rtl' \| 'ltr'` | `'rtl'` | |
|
|
363
|
+
| placeholderDir | `'rtl' \| 'ltr'` | = `dir` | |
|
|
364
|
+
| containerClassName | `string` | | Field box |
|
|
365
|
+
| wrapperClassName | `string` | | Outer wrapper (label + field + info) |
|
|
366
|
+
|
|
367
|
+
`Checkbox` and `RadioButton` share **choice props**:
|
|
368
|
+
|
|
369
|
+
| Prop | Type | Default | Notes |
|
|
370
|
+
| ------------------ | ------------------------------------- | ----------- | -------------------------------- |
|
|
371
|
+
| label | `string \| ReactNode` | | |
|
|
372
|
+
| variant | `'default' \| 'bordered'` | `'default'` | |
|
|
373
|
+
| icon | `ReactNode` | | Only with `variant="bordered"` |
|
|
374
|
+
| isError | `boolean` | | |
|
|
375
|
+
| errorMessage | `string` | | |
|
|
376
|
+
| helperMessage | `string` | | |
|
|
377
|
+
| containerClassName | `string` | | |
|
|
378
|
+
| …native | `InputHTMLAttributes` (except `type`) | | `checked`, `onChange`, `name`, … |
|
|
379
|
+
|
|
380
|
+
### Input
|
|
381
|
+
|
|
382
|
+
`forwardRef<HTMLInputElement>`. Extends native input attributes (except `dir`, `prefix`) + text-field props.
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
<Input
|
|
386
|
+
labelContent="Email"
|
|
387
|
+
dir="ltr"
|
|
388
|
+
value={email}
|
|
389
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
390
|
+
onClear={() => setEmail('')}
|
|
391
|
+
errorMessage={errors.email}
|
|
392
|
+
/>
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
| Prop | Type | Notes |
|
|
396
|
+
| ---------------------------------- | ------------------------ | ------------------------------------------- |
|
|
397
|
+
| leftIcon | `JSX.Element` | |
|
|
398
|
+
| prefix / postfix | `ReactNode` | Inline adornments |
|
|
399
|
+
| prefixClassName / postfixClassName | `string` | |
|
|
400
|
+
| onClear | `() => void` | Shows a clear button when provided |
|
|
401
|
+
| onInput | `(e) => void \| boolean` | Return `true` to stop the built-in handling |
|
|
402
|
+
| type="password" | | Adds a show/hide toggle |
|
|
403
|
+
|
|
404
|
+
### Textarea
|
|
405
|
+
|
|
406
|
+
`forwardRef<HTMLTextAreaElement>`. Native textarea attributes (except `dir`, `onClick`) + text-field props.
|
|
407
|
+
|
|
408
|
+
```tsx
|
|
409
|
+
<Textarea
|
|
410
|
+
labelContent="Description"
|
|
411
|
+
maxLength={300}
|
|
412
|
+
showMaxLength
|
|
413
|
+
value={v}
|
|
414
|
+
onChange={(e) => setV(e.target.value)}
|
|
415
|
+
/>
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### OtpInput
|
|
419
|
+
|
|
420
|
+
| Prop | Type | Default |
|
|
421
|
+
| ------------------------ | ------------------------- | ------- | -------------------------------- |
|
|
422
|
+
| **value** | `string` | |
|
|
423
|
+
| **onChange** | `(value: string) => void` | |
|
|
424
|
+
| onEnd | `(value: string) => void` | | Fired when all digits are filled |
|
|
425
|
+
| inputsNumber | `number` | `4` |
|
|
426
|
+
| inputsContainerClassName | `string` | |
|
|
427
|
+
| className | `string` | |
|
|
428
|
+
| … | other `InputProps` | |
|
|
429
|
+
|
|
430
|
+
### Checkbox
|
|
431
|
+
|
|
432
|
+
Choice props + `isIndeterminate?: boolean`.
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
<Checkbox
|
|
436
|
+
label="Accept terms"
|
|
437
|
+
checked={ok}
|
|
438
|
+
onChange={(e) => setOk(e.target.checked)}
|
|
439
|
+
/>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### RadioButton
|
|
443
|
+
|
|
444
|
+
Choice props.
|
|
445
|
+
|
|
446
|
+
```tsx
|
|
447
|
+
<RadioButton
|
|
448
|
+
name="plan"
|
|
449
|
+
value="pro"
|
|
450
|
+
label="Pro"
|
|
451
|
+
checked={plan === 'pro'}
|
|
452
|
+
onChange={() => setPlan('pro')}
|
|
453
|
+
/>
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Switch
|
|
457
|
+
|
|
458
|
+
| Prop | Type | Default |
|
|
459
|
+
| ------------------------------ | ---------------------------- | --------- |
|
|
460
|
+
| **checked** | `boolean` | |
|
|
461
|
+
| **onChange** | `(checked: boolean) => void` | |
|
|
462
|
+
| label | `string` | |
|
|
463
|
+
| description | `string` | |
|
|
464
|
+
| size | `'large' \| 'small'` | `'large'` |
|
|
465
|
+
| disabled | `boolean` | |
|
|
466
|
+
| isIntermediate | `boolean` | |
|
|
467
|
+
| className / containerClassName | `string` | |
|
|
468
|
+
|
|
469
|
+
### RangeInput
|
|
470
|
+
|
|
471
|
+
Generic: `number` for a single thumb, `number[]` for a range.
|
|
472
|
+
|
|
473
|
+
```tsx
|
|
474
|
+
<RangeInput
|
|
475
|
+
min={0}
|
|
476
|
+
max={100}
|
|
477
|
+
value={[20, 80]}
|
|
478
|
+
onChange={setRange}
|
|
479
|
+
startTitle="Min"
|
|
480
|
+
endTitle="Max"
|
|
481
|
+
/>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
| Prop | Type | Default |
|
|
485
|
+
| --------------------- | -------------------------------------------- | ----------- |
|
|
486
|
+
| **value** | `number \| number[]` | |
|
|
487
|
+
| **onChange** | `(value) => void` (same type as `value`) | |
|
|
488
|
+
| **min** | `number` | |
|
|
489
|
+
| **max** | `number` | |
|
|
490
|
+
| step | `number` | `1` |
|
|
491
|
+
| color | `'primary' \| 'secondary'` | `'primary'` |
|
|
492
|
+
| tooltip | `boolean \| ReactNode` | `true` |
|
|
493
|
+
| tooltipSize | `'small' \| 'medium' \| 'large' \| 'xLarge'` | `'medium'` |
|
|
494
|
+
| tooltipClassName | `string` | |
|
|
495
|
+
| startTitle / endTitle | `string` | |
|
|
496
|
+
| disabled | `boolean` | |
|
|
497
|
+
| wrapperClassName | `string` | |
|
|
498
|
+
|
|
499
|
+
### Picker wrapper props (Select, Datepicker, Timepicker)
|
|
500
|
+
|
|
501
|
+
| Prop | Type | Default | Notes |
|
|
502
|
+
| ---------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------- | -------------------------------------- |
|
|
503
|
+
| dropdownType | `'popover' \| 'drawer'` | `'popover'` | |
|
|
504
|
+
| popoverPosition | `'top' \| 'bottom' \| 'top-left' \| 'top-center' \| 'top-right' \| 'bottom-left' \| 'bottom-center' \| 'bottom-right'` | | Popover only |
|
|
505
|
+
| popoverClassName | `string` | | Popover only |
|
|
506
|
+
| drawerProps | `DrawerProps` without `children`/`open`/`onClose` | | Drawer only |
|
|
507
|
+
| inputProps | `InputProps` without `leftIcon` | | Props for the built-in trigger input |
|
|
508
|
+
| customInput | `(isOpen: boolean) => ReactNode` | | Replace trigger; excludes `inputProps` |
|
|
509
|
+
| isLoading | `boolean` | | |
|
|
510
|
+
| disabled | `boolean` | | |
|
|
511
|
+
| wrapperClassName | `string` | | |
|
|
512
|
+
|
|
513
|
+
### Select
|
|
514
|
+
|
|
515
|
+
Generic over option value `T`. Single or multiple mode.
|
|
516
|
+
|
|
517
|
+
```tsx
|
|
518
|
+
<Select
|
|
519
|
+
options={[{ value: 1, label: 'Tehran' }, { value: 2, label: 'Shiraz' }]}
|
|
520
|
+
value={city}
|
|
521
|
+
onChange={setCity}
|
|
522
|
+
searchable
|
|
523
|
+
inputProps={{ labelContent: 'City', placeholder: 'Choose…' }}
|
|
524
|
+
/>
|
|
525
|
+
|
|
526
|
+
<Select mode="multiple" options={tags} value={selected} onChange={setSelected} optionsTitle="Tags" />
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
| Prop | Type | Notes |
|
|
530
|
+
| ---------------------------- | --------------------------------------------------- | ---------------------- |
|
|
531
|
+
| **options** | `{ value: T; label: string; disabled?: boolean }[]` | |
|
|
532
|
+
| **value** | `T` (single) / `T[]` (multiple) | |
|
|
533
|
+
| **onChange** | `(value: T) => void` / `(value: T[]) => void` | |
|
|
534
|
+
| mode | `'single' \| 'multiple'` | default single |
|
|
535
|
+
| searchable | `boolean \| InputProps` (without `onChange`) | |
|
|
536
|
+
| optionCell | `(option, isActive: boolean) => ReactNode` | Custom option renderer |
|
|
537
|
+
| optionCellClassName | `string` | |
|
|
538
|
+
| beforeOptions / afterOptions | `ReactNode` | |
|
|
539
|
+
| emptyContent | `ReactNode` | |
|
|
540
|
+
| showClearButtonOnEmpty | `boolean` | |
|
|
541
|
+
| optionsTitle | `string` | Multiple mode only |
|
|
542
|
+
| separateSelectedOptions | `boolean` | Multiple mode only |
|
|
543
|
+
| … | picker wrapper props | |
|
|
544
|
+
|
|
545
|
+
### Datepicker
|
|
546
|
+
|
|
547
|
+
Jalali (Persian) calendar. Values are native JS `Date` objects.
|
|
548
|
+
|
|
549
|
+
```tsx
|
|
550
|
+
<Datepicker value={date} onChange={setDate} inputProps={{ labelContent: 'Birth date' }} />
|
|
551
|
+
|
|
552
|
+
<Datepicker acceptRange value={{ start, end }} onChange={({ start, end }) => …} />
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
| Prop | Type | Default | Notes |
|
|
556
|
+
| -------------------- | ----------------------------------------------------------------------------------- | ------- | ------------------------------------------- |
|
|
557
|
+
| **value** | `Date \| null` — or `{ start: Date \| null; end: Date \| null }` with `acceptRange` | | |
|
|
558
|
+
| **onChange** | `(value: Date) => void` — or `(value: { start; end }) => void` with `acceptRange` | | |
|
|
559
|
+
| acceptRange | `boolean` | | Range selection |
|
|
560
|
+
| mode | `'input' \| 'calendar'` | | `'calendar'` renders inline calendar |
|
|
561
|
+
| startDate / endDate | `Date` | | Selectable bounds |
|
|
562
|
+
| disableDates | `Date[]` | | |
|
|
563
|
+
| holidays | `Date[]` | | |
|
|
564
|
+
| highlightWeekends | `boolean` | | |
|
|
565
|
+
| showExtraDays | `boolean` | | Show adjacent-month days |
|
|
566
|
+
| showTodayButton | `boolean` | `true` | |
|
|
567
|
+
| showSubmitButton | `boolean` | `true` | |
|
|
568
|
+
| onSubmit | `() => void` | | Only when `showSubmitButton` is not `false` |
|
|
569
|
+
| onInternalDateChange | `(date: Date) => void` | | Visible month/year changes |
|
|
570
|
+
| dayHoverAction | `{ onClick: (day: DayItem) => void; element: (day: DayItem) => ReactNode }` | | |
|
|
571
|
+
| … | picker wrapper props | | |
|
|
572
|
+
|
|
573
|
+
### Timepicker
|
|
574
|
+
|
|
575
|
+
Values are `Date` objects (hour/minute are read from them).
|
|
576
|
+
|
|
577
|
+
```tsx
|
|
578
|
+
<Timepicker
|
|
579
|
+
value={time}
|
|
580
|
+
onChange={setTime}
|
|
581
|
+
minuteStep={15}
|
|
582
|
+
/>
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
| Prop | Type | Default |
|
|
586
|
+
| ------------------------ | -------------------------------------------------- | ------- |
|
|
587
|
+
| **value** / **onChange** | same shape as Datepicker (single or `acceptRange`) | |
|
|
588
|
+
| acceptRange | `boolean` | |
|
|
589
|
+
| mode | `'input' \| 'time'` | |
|
|
590
|
+
| minuteStep | `number` | `1` |
|
|
591
|
+
| showNowButton | `boolean` | `true` |
|
|
592
|
+
| showSubmitButton | `boolean` | `true` |
|
|
593
|
+
| onSubmit | `() => void` | |
|
|
594
|
+
| … | picker wrapper props | |
|
|
595
|
+
|
|
596
|
+
### FileUploader
|
|
597
|
+
|
|
598
|
+
```tsx
|
|
599
|
+
<FileUploader
|
|
600
|
+
files={file ? { file } : undefined}
|
|
601
|
+
onChange={(f) => setFile(f)}
|
|
602
|
+
fileInputProps={{ title: 'Upload avatar', accept: 'image/*' }}
|
|
603
|
+
/>
|
|
604
|
+
|
|
605
|
+
<FileUploader
|
|
606
|
+
mode="multiple"
|
|
607
|
+
files={files.map((file) => ({ file }))}
|
|
608
|
+
onChange={(_, list) => setFiles(Array.from(list ?? []))}
|
|
609
|
+
previewProps={{ type: 'grid' }}
|
|
610
|
+
/>
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
| Prop | Type | Notes |
|
|
614
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
615
|
+
| **onChange** | `(file: File \| undefined, files: FileList \| null) => void` | |
|
|
616
|
+
| mode | `'single' \| 'multiple'` | default single |
|
|
617
|
+
| files | `FileType` (single) / `FileType[]` (multiple) | Controlled preview list |
|
|
618
|
+
| previewProps | `{ type?: 'default' \| 'compact' }` (single) / `{ type?: 'list' \| 'grid' }` (multiple), plus `leftButton`, `rightButton`, `exteraButton`, `wrapperClassName`, `previewClassName` | |
|
|
619
|
+
| hideFileInput | `boolean` | Multiple mode only |
|
|
620
|
+
| fileInputProps | `{ title?; description?; hideIcon?; button?: boolean \| ButtonProps; helperProps?; …native file input attrs }` | |
|
|
621
|
+
| isError | `boolean` | |
|
|
622
|
+
| disabled | `boolean` | |
|
|
623
|
+
| className | `string` | |
|
|
624
|
+
|
|
625
|
+
`FileType = { file: File } | { src: string }` plus optional `loading?: boolean | number` (number = upload %), `status?: 'warning' | 'error' | 'default'`, `title?`, `errorMessage?`, `hintMessage?`.
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
|
|
629
|
+
### Menu
|
|
630
|
+
|
|
631
|
+
```tsx
|
|
632
|
+
<Menu
|
|
633
|
+
trigger={(toggle, ref) => (
|
|
634
|
+
<button
|
|
635
|
+
ref={ref as React.Ref<HTMLButtonElement>}
|
|
636
|
+
type="button"
|
|
637
|
+
onClick={toggle}
|
|
638
|
+
>
|
|
639
|
+
Actions
|
|
640
|
+
</button>
|
|
641
|
+
)}
|
|
642
|
+
>
|
|
643
|
+
<Menu.Item
|
|
644
|
+
icon={<EditIcon />}
|
|
645
|
+
onClick={edit}
|
|
646
|
+
>
|
|
647
|
+
Edit
|
|
648
|
+
</Menu.Item>
|
|
649
|
+
<Menu.Item disabled>Archive</Menu.Item>
|
|
650
|
+
</Menu>
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
`Menu`
|
|
654
|
+
|
|
655
|
+
| Prop | Type | Default |
|
|
656
|
+
| ---------------- | ---------------------------------------------------------------- | ---------------- |
|
|
657
|
+
| **trigger** | `(toggle: () => void, ref: React.Ref<HTMLElement>) => ReactNode` | |
|
|
658
|
+
| **children** | `ReactNode` | |
|
|
659
|
+
| position | popper position (see picker wrapper) | `'bottom-right'` |
|
|
660
|
+
| className | `string` | `''` |
|
|
661
|
+
| popoverClassName | `string` | `''` |
|
|
662
|
+
|
|
663
|
+
`Menu.Item`: **children** `ReactNode`, `onClick?`, `icon?`, `endElement?`, `disabled?`, `className?`. Clicking an item closes the menu.
|
|
664
|
+
|
|
665
|
+
### Pagination
|
|
666
|
+
|
|
667
|
+
```tsx
|
|
668
|
+
<Pagination
|
|
669
|
+
totalCount={240}
|
|
670
|
+
pageSize={20}
|
|
671
|
+
onPageChange={setPage}
|
|
672
|
+
/>
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
| Prop | Type | Default |
|
|
676
|
+
| ------------------------- | ------------------------ | ------- |
|
|
677
|
+
| **totalCount** | `number` | |
|
|
678
|
+
| **pageSize** | `number` | |
|
|
679
|
+
| onPageChange | `(page: number) => void` | |
|
|
680
|
+
| defaultCurrent | `number` | `1` |
|
|
681
|
+
| siblingCount | `number` | `1` |
|
|
682
|
+
| navigationButtonsWithText | `boolean` | `true` |
|
|
683
|
+
| hideOnSinglePage | `boolean` | |
|
|
684
|
+
| className | `string` | |
|
|
685
|
+
|
|
686
|
+
### ProgressBar
|
|
687
|
+
|
|
688
|
+
| Prop | Type | Default |
|
|
689
|
+
| --------------- | -------------------------- | -------------- |
|
|
690
|
+
| **title** | `string` | |
|
|
691
|
+
| **current** | `number` | |
|
|
692
|
+
| total | `number` | `100` |
|
|
693
|
+
| color | `'primary' \| 'secondary'` | `'primary'` |
|
|
694
|
+
| currentShowType | `'percentage' \| 'value'` | `'percentage'` |
|
|
695
|
+
| className | `string` | |
|
|
696
|
+
|
|
697
|
+
### ProgressDoughnut
|
|
698
|
+
|
|
699
|
+
| Prop | Type | Default |
|
|
700
|
+
| ------------- | ------------------------------------------------- | ----------- |
|
|
701
|
+
| **current** | `number` | |
|
|
702
|
+
| **total** | `number` | |
|
|
703
|
+
| color | `'primary' \| 'secondary' \| 'gray' \| 'warning'` | `'primary'` |
|
|
704
|
+
| size | `number` (px) | `48` |
|
|
705
|
+
| strokeSize | `number` | `6` |
|
|
706
|
+
| showText | `boolean` | |
|
|
707
|
+
| textClassName | `string` — only with `showText` | |
|
|
708
|
+
| svgProps | `SVGProps<SVGSVGElement>` | |
|
|
709
|
+
|
|
710
|
+
### ProgressStep
|
|
711
|
+
|
|
712
|
+
Subpath import only: `import ProgressStep from '@dgshahr/ui-kit/Progress/Step'`.
|
|
713
|
+
|
|
714
|
+
```tsx
|
|
715
|
+
<ProgressStep
|
|
716
|
+
type="rtl"
|
|
717
|
+
size="large"
|
|
718
|
+
color="primary"
|
|
719
|
+
title="Profile"
|
|
720
|
+
currentStep={2}
|
|
721
|
+
totalSteps={4}
|
|
722
|
+
showStepsCount
|
|
723
|
+
/>
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
| Prop | Type | Default |
|
|
727
|
+
| ------------------------------ | ---------------------------------------- | ----------- |
|
|
728
|
+
| **type** | `'rtl' \| 'center'` | `'rtl'` |
|
|
729
|
+
| **size** | `'small' \| 'large'` | `'large'` |
|
|
730
|
+
| **color** | `'primary' \| 'secondary'` | `'primary'` |
|
|
731
|
+
| **title** | `string` | |
|
|
732
|
+
| **currentStep** | `number` (1-based) | |
|
|
733
|
+
| **totalSteps** | `number` | `5` |
|
|
734
|
+
| progress | `number` 0–100, fill within current step | `100` |
|
|
735
|
+
| subtitle | `string` | |
|
|
736
|
+
| showSubtitle | `boolean` | |
|
|
737
|
+
| showStepsCount | `boolean` | |
|
|
738
|
+
| className / containerClassName | `string` | |
|
|
739
|
+
|
|
740
|
+
### Rate
|
|
741
|
+
|
|
742
|
+
```tsx
|
|
743
|
+
<Rate
|
|
744
|
+
value={4}
|
|
745
|
+
total={5}
|
|
746
|
+
showTotalStars
|
|
747
|
+
onChange={setRating}
|
|
748
|
+
/>
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
| Prop | Type | Default | Notes |
|
|
752
|
+
| --------------- | ------------------------- | --------- | ---------------------------------------- |
|
|
753
|
+
| **value** | `number` | | |
|
|
754
|
+
| **total** | `number` | | |
|
|
755
|
+
| onChange | `(value: number) => void` | | Makes it interactive |
|
|
756
|
+
| size | `'small' \| 'large'` | `'large'` | |
|
|
757
|
+
| showTotalStars | `boolean` | | At least one of these two must be `true` |
|
|
758
|
+
| showRateNumber | `boolean` | `true` | |
|
|
759
|
+
| showStarsNumber | `boolean` | | |
|
|
760
|
+
| className | `string` | | |
|
|
761
|
+
|
|
762
|
+
### Sidebar
|
|
763
|
+
|
|
764
|
+
```tsx
|
|
765
|
+
<Sidebar
|
|
766
|
+
isOpen={open}
|
|
767
|
+
setIsOpen={setOpen}
|
|
768
|
+
logo={{ open: '/logo.svg', close: '/logo-mini.svg', alt: 'Logo' }}
|
|
769
|
+
items={[
|
|
770
|
+
{
|
|
771
|
+
title: 'Main',
|
|
772
|
+
children: [{ title: 'Dashboard', icon: <HomeIcon />, link: '/', active: true }],
|
|
773
|
+
},
|
|
774
|
+
]}
|
|
775
|
+
userProfile={{ image: '/me.png', name: 'Jane' }}
|
|
776
|
+
onLogout={logout}
|
|
777
|
+
/>
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
| Prop | Type | Notes |
|
|
781
|
+
| ----------------- | ----------------------------------------------------------------------- | ------------------------------------- |
|
|
782
|
+
| **isOpen** | `boolean` | |
|
|
783
|
+
| **setIsOpen** | `(isOpen: boolean) => void` | |
|
|
784
|
+
| items | `FirstLevelSidebarItem[]` | 3 levels, see below |
|
|
785
|
+
| logo | `{ open: string; close: string } & img attrs (except src)` | |
|
|
786
|
+
| searchInput | `boolean \| InputProps` (without value/onChange) | |
|
|
787
|
+
| userProfile | `{ image: string; name?: string; description?: string; link?: string }` | |
|
|
788
|
+
| onLogout | `() => void` | |
|
|
789
|
+
| logOutButtonProps | `ButtonProps` without `onClick` | |
|
|
790
|
+
| extraComponent | `ReactNode` | |
|
|
791
|
+
| hideOnClose | `boolean` | Fully hide when closed |
|
|
792
|
+
| openOnHover | `boolean` | Only when `hideOnClose` is not `true` |
|
|
793
|
+
| showMask | `boolean` | |
|
|
794
|
+
| className | `string` | |
|
|
795
|
+
|
|
796
|
+
Items: `FirstLevelSidebarItem { title; children?: SecondLevelSidebarItem[] }` → `SecondLevelSidebarItem { title; icon: ReactNode; link?; badgeCount?; disabled?; active?; children?: ThirdLevelSidebarItem[] }` → `ThirdLevelSidebarItem { title; link: string; badgeCount?; disabled?; active? }`.
|
|
797
|
+
|
|
798
|
+
### Slider / Slide
|
|
799
|
+
|
|
800
|
+
`Slider` is `forwardRef<SliderRef>`; `SliderRef = { navigate(index: number): void; element: HTMLDivElement | null }`. `Slide` accepts native div attributes.
|
|
801
|
+
|
|
802
|
+
```tsx
|
|
803
|
+
<Slider
|
|
804
|
+
slidesPerView={1.2}
|
|
805
|
+
spaceBetween={12}
|
|
806
|
+
autoplay={{ delay: 4000 }}
|
|
807
|
+
responsive={{ 768: { slidesPerView: 3 } }}
|
|
808
|
+
>
|
|
809
|
+
{items.map((i) => (
|
|
810
|
+
<Slide key={i.id}>…</Slide>
|
|
811
|
+
))}
|
|
812
|
+
</Slider>
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
| Prop | Type | Default |
|
|
816
|
+
| ----------------------------------------------------------------------------- | ----------------------------------------------------- | -------- |
|
|
817
|
+
| slidesPerView | `number` | `1` |
|
|
818
|
+
| spaceBetween | `number` (px) | `0` |
|
|
819
|
+
| centerMode | `boolean` | |
|
|
820
|
+
| autoplay | `boolean \| { delay?: number \| null }` | |
|
|
821
|
+
| initialSlide | `number` | |
|
|
822
|
+
| onSlideIndexChange | `(index: number) => void` | |
|
|
823
|
+
| showNavigationDots | `boolean` | `true` |
|
|
824
|
+
| showPaginationText | `boolean` | |
|
|
825
|
+
| navigationVariant | `'inside' \| 'outside'` | |
|
|
826
|
+
| navigationButtonsShowType | `'hide' \| 'hover' \| 'permanent' \| 'onSides'` | `'hide'` |
|
|
827
|
+
| responsive | `Record<minWidthPx, Omit<SliderProps, 'responsive'>>` | |
|
|
828
|
+
| containerXPadding | `number` | `0` |
|
|
829
|
+
| className / containerClassName / dotsClassName / navigationContainerClassName | `string` | |
|
|
830
|
+
|
|
831
|
+
### HorizontalStepper / HorizontalStep
|
|
832
|
+
|
|
833
|
+
```tsx
|
|
834
|
+
<HorizontalStepper activeStep={1}>
|
|
835
|
+
<HorizontalStep
|
|
836
|
+
title="Cart"
|
|
837
|
+
icon={<CartIcon />}
|
|
838
|
+
/>
|
|
839
|
+
<HorizontalStep
|
|
840
|
+
title="Shipping"
|
|
841
|
+
icon={<TruckIcon />}
|
|
842
|
+
/>
|
|
843
|
+
<HorizontalStep
|
|
844
|
+
title="Pay"
|
|
845
|
+
icon={<CardIcon />}
|
|
846
|
+
/>
|
|
847
|
+
</HorizontalStepper>
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
`HorizontalStepper`: `activeStep?: number` (0-based, default `0`), `size?: 'small' | 'medium'` (default `'medium'`), `stepOrientation?: 'horizontal' | 'vertical'` (default `'horizontal'`), `classname?: string` (lowercase `n`).
|
|
851
|
+
|
|
852
|
+
`HorizontalStep`: **title** `string`, **icon** `ReactNode`, `activeTitle?`, `completeTitle?`, `subTitle?`, `activeIcon?`, `completeIcon?`, `classname?`. `index` is injected by the stepper.
|
|
853
|
+
|
|
854
|
+
### Table
|
|
855
|
+
|
|
856
|
+
Generic over row type `T`. `dataIndex` accepts a key or a deep path (type-safe when `T` is known).
|
|
857
|
+
|
|
858
|
+
```tsx
|
|
859
|
+
type User = { id: string; name: string; address: { city: string } };
|
|
860
|
+
|
|
861
|
+
<Table<User>
|
|
862
|
+
data={users}
|
|
863
|
+
rowKey="id"
|
|
864
|
+
columns={[
|
|
865
|
+
{ title: 'Name', dataIndex: 'name', sort: { active: sort, onSort: setSort } },
|
|
866
|
+
{ title: 'City', dataIndex: ['address', 'city'] },
|
|
867
|
+
{
|
|
868
|
+
key: 'actions',
|
|
869
|
+
title: '',
|
|
870
|
+
render: (u) => <Button size="small">Edit</Button>,
|
|
871
|
+
sticky: 'left',
|
|
872
|
+
},
|
|
873
|
+
]}
|
|
874
|
+
pagination={{ totalCount, pageSize: 20, onPageChange: setPage }}
|
|
875
|
+
loading={isFetching}
|
|
876
|
+
/>;
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
| Prop | Type | Default |
|
|
880
|
+
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------- |
|
|
881
|
+
| **data** | `T[]` | |
|
|
882
|
+
| **columns** | `ColumnsType<T>[]` | |
|
|
883
|
+
| **rowKey** | `keyof T` | |
|
|
884
|
+
| header | `{ title?; showTotal?; extraElement?; className?; pageCountSelector?: { options; defaultValue?; onPageCountChange?; selectProps? } }` | |
|
|
885
|
+
| pagination | `PaginationProps` | |
|
|
886
|
+
| rowSelection | `{ selectedRowKeys: string[]; onSelectRow: (e, key: string \| string[], record?) => void; align?; sticky?; className? }` | |
|
|
887
|
+
| loading | `boolean \| { size: number }` (loader size in px) | |
|
|
888
|
+
| emptyContent | `ReactNode` | |
|
|
889
|
+
| stickyTableHeader | `boolean` | |
|
|
890
|
+
| layout | `'fixed' \| 'auto'` | `'auto'` |
|
|
891
|
+
| getRowClassName | `(record: T) => string \| undefined` | |
|
|
892
|
+
| className / containerClassName / wrapperClassName | `string` | |
|
|
893
|
+
|
|
894
|
+
`ColumnsType<T>`: one of `key` / `dataIndex` required; `title?`, `align?: 'start' | 'center' | 'end'`, `render?: (record, index) => ReactNode`, `sort?: { active?: 'ascend' | 'descend'; onSort(value) }`, `sticky?: 'left' | 'right'`, `ellipsis?: boolean | { hideTooltip?: boolean }`, `tooltip?: TooltipProps & { anchorIcon? }`, `className?`.
|
|
895
|
+
|
|
896
|
+
### Tabs
|
|
897
|
+
|
|
898
|
+
```tsx
|
|
899
|
+
<Tabs
|
|
900
|
+
activeKey={tab}
|
|
901
|
+
onChange={setTab}
|
|
902
|
+
items={[
|
|
903
|
+
{ key: 'info', title: 'Info' },
|
|
904
|
+
{ key: 'orders', title: 'Orders', badgeNumber: 3 },
|
|
905
|
+
]}
|
|
906
|
+
/>
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
| Prop | Type |
|
|
910
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------- |
|
|
911
|
+
| **activeKey** | `string \| number` |
|
|
912
|
+
| **onChange** | `(key: string \| number) => void` |
|
|
913
|
+
| **items** | `{ key: string \| number; title: string; icon?: ReactNode; badgeNumber?: number; disabled?: boolean }[]` |
|
|
914
|
+
| fullWidth | `boolean` |
|
|
915
|
+
| fullWidthButtons | `boolean` — only when `fullWidth` is `true` |
|
|
916
|
+
| className | `string` |
|
|
917
|
+
| tabItemClassName | `string` |
|
|
918
|
+
|
|
919
|
+
Tabs renders only the tab bar; render the active panel yourself.
|
|
920
|
+
|
|
921
|
+
### Tooltip
|
|
922
|
+
|
|
923
|
+
```tsx
|
|
924
|
+
<Tooltip
|
|
925
|
+
title="VAT"
|
|
926
|
+
content="9% value added tax is included."
|
|
927
|
+
position="bottom-center"
|
|
928
|
+
>
|
|
929
|
+
<InfoIcon />
|
|
930
|
+
</Tooltip>
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
| Prop | Type | Default |
|
|
934
|
+
| ---------------- | ------------------------------------- | -------------- |
|
|
935
|
+
| **content** | `ReactNode` | |
|
|
936
|
+
| **children** | `ReactNode` — the anchor | |
|
|
937
|
+
| position | popper position (see picker wrapper) | `'top-center'` |
|
|
938
|
+
| title | `string` | |
|
|
939
|
+
| icon | `ReactNode` | |
|
|
940
|
+
| footer | `ReactNode` | |
|
|
941
|
+
| disabled | `boolean` | |
|
|
942
|
+
| attachToBody | `boolean` — portal to `document.body` | |
|
|
943
|
+
| className | `string` | |
|
|
944
|
+
| wrapperClassName | `string` | |
|
|
945
|
+
|
|
946
|
+
Position auto-flips when there is no room.
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
950
|
+
## Rules for AI agents
|
|
951
|
+
|
|
952
|
+
When writing code in a project that depends on `@dgshahr/ui-kit`:
|
|
953
|
+
|
|
954
|
+
1. **Prefer kit components.** Before building a button, input, select, date/time picker, modal/drawer, tabs, table, tooltip, badge, alert, pagination, etc., use the kit component from this guide.
|
|
955
|
+
2. **Use the documented props** for variants, sizes and colors (`variant`, `color`, `size`). Do not recreate these looks with custom CSS.
|
|
956
|
+
3. **Imports:** use `@dgshahr/ui-kit` or the subpaths listed in [Imports](#imports). Form components are under `Form/`. Never import from `@dgshahr/ui-kit/dist/...` or internal paths.
|
|
957
|
+
4. **No Tailwind setup for the kit.** Styles are bundled; do not add Tailwind, PostCSS or a CSS import for the kit.
|
|
958
|
+
5. **Do not use `dgsuikit:`-prefixed classes** in app code — they are internal to the kit and may not be generated.
|
|
959
|
+
6. **Theme via CSS variables** (`--dgs-color-{palette}-{shade}: r g b`), never by overriding internal class names.
|
|
960
|
+
7. **Customize via slot class props** (`className`, `wrapperClassName`, `containerClassName`, …).
|
|
961
|
+
8. **Controlled components:** `Switch`, `Tabs`, `Select`, `Datepicker`, `Timepicker`, `OtpInput`, `RangeInput`, `Drawer` require `value`/`checked`/`activeKey`/`open` + change handler.
|
|
962
|
+
9. **RTL:** text fields default to `dir="rtl"`; pass `dir="ltr"` for emails, URLs, numbers, codes.
|
|
963
|
+
10. **Dates:** Datepicker shows the Jalali calendar but reads/writes plain JS `Date`s — no conversion needed.
|
|
964
|
+
11. **Next.js App Router:** place interactive kit components inside a `'use client'` component.
|
|
965
|
+
12. **When unsure about a prop,** read `node_modules/@dgshahr/ui-kit/dist/<Component>/index.d.ts` — it is the source of truth; this guide may lag behind.
|
|
966
|
+
|
|
967
|
+
---
|
|
968
|
+
|
|
969
|
+
## Agent setup snippets
|
|
970
|
+
|
|
971
|
+
### Reference-by-path (shortest)
|
|
972
|
+
|
|
973
|
+
Add one line to your agent instructions file:
|
|
974
|
+
|
|
975
|
+
```md
|
|
976
|
+
This project uses @dgshahr/ui-kit. Before writing UI code, read node_modules/@dgshahr/ui-kit/INTEGRATION.md and follow its "Rules for AI agents".
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
### Generic block (AGENTS.md / CLAUDE.md / any agent)
|
|
980
|
+
|
|
981
|
+
```md
|
|
982
|
+
## UI components: @dgshahr/ui-kit
|
|
983
|
+
|
|
984
|
+
- Full reference: node_modules/@dgshahr/ui-kit/INTEGRATION.md (read it before building UI).
|
|
985
|
+
- Always use kit components (Button, Input, Select, Datepicker, Timepicker, Drawer, Tabs, Table, Tooltip, Badge, Alert, Pagination, …) instead of custom ones.
|
|
986
|
+
- Imports: `import { X } from '@dgshahr/ui-kit'` or subpath `@dgshahr/ui-kit/X`; form components are `@dgshahr/ui-kit/Form/X`. Never import from dist/ internals.
|
|
987
|
+
- Styles are bundled: do not configure Tailwind/PostCSS for the kit; never use `dgsuikit:` classes in app code.
|
|
988
|
+
- Use `variant`/`color`/`size` props for looks; use `className`/`*ClassName` props for layout tweaks.
|
|
989
|
+
- Theme colors only via CSS vars `--dgs-color-{palette}-{shade}: r g b` (space-separated RGB).
|
|
990
|
+
- Text fields default to RTL; pass `dir="ltr"` for emails/URLs/numbers.
|
|
991
|
+
- Datepicker is Jalali but uses plain JS Date values.
|
|
992
|
+
- Next.js App Router: interactive kit components go inside 'use client' files.
|
|
993
|
+
- Unsure about a prop? Check node_modules/@dgshahr/ui-kit/dist/<Component>/index.d.ts.
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
### Claude Code — `CLAUDE.md`
|
|
997
|
+
|
|
998
|
+
Paste the generic block into the project's `CLAUDE.md` (repo root). Alternatively import the full guide so it is always loaded:
|
|
999
|
+
|
|
1000
|
+
```md
|
|
1001
|
+
@node_modules/@dgshahr/ui-kit/INTEGRATION.md
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
### Cursor — `.cursor/rules/dgshahr-ui-kit.mdc`
|
|
1005
|
+
|
|
1006
|
+
```md
|
|
1007
|
+
---
|
|
1008
|
+
description: Use @dgshahr/ui-kit components for all UI
|
|
1009
|
+
globs: ['**/*.tsx', '**/*.jsx']
|
|
1010
|
+
alwaysApply: false
|
|
1011
|
+
---
|
|
1012
|
+
|
|
1013
|
+
<paste the generic block here>
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
### GitHub Copilot — `.github/copilot-instructions.md`
|
|
1017
|
+
|
|
1018
|
+
Paste the generic block into `.github/copilot-instructions.md`. For path-scoped rules use `.github/instructions/ui-kit.instructions.md` with:
|
|
1019
|
+
|
|
1020
|
+
```md
|
|
1021
|
+
---
|
|
1022
|
+
applyTo: '**/*.tsx,**/*.jsx'
|
|
1023
|
+
---
|
|
1024
|
+
|
|
1025
|
+
<paste the generic block here>
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
### Windsurf — `.windsurfrules`
|
|
1029
|
+
|
|
1030
|
+
Paste the generic block into `.windsurfrules` at the repo root (or `.windsurf/rules/ui-kit.md`).
|
|
1031
|
+
|
|
1032
|
+
### Other agents (Codex, Gemini CLI, Aider, …)
|
|
1033
|
+
|
|
1034
|
+
Paste the generic block into `AGENTS.md` (Codex and many others), `GEMINI.md` (Gemini CLI), or the tool's conventions file.
|