@emanuelrista/primo-ui-kit 1.1.4
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/README.md +901 -0
- package/dist/index.d.ts +323 -0
- package/dist/primo-ui-kit.css +1 -0
- package/dist/primo-ui-kit.js +1633 -0
- package/dist/primo-ui-kit.umd.cjs +88 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,901 @@
|
|
|
1
|
+
# Primo UI Kit
|
|
2
|
+
|
|
3
|
+
A comprehensive React component library built with Tailwind CSS, featuring customizable components with a consistent design system.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @emanuelrista/primo-ui-kit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Import the styles in your main application file:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import '@emanuelrista/primo-ui-kit/styles'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Make sure you have React 18+ or 19+ installed as a peer dependency.
|
|
20
|
+
|
|
21
|
+
## Components
|
|
22
|
+
|
|
23
|
+
### Button
|
|
24
|
+
|
|
25
|
+
A versatile button component with multiple variants and sizes.
|
|
26
|
+
|
|
27
|
+
```jsx
|
|
28
|
+
import { Button } from '@emanuelrista/primo-ui-kit'
|
|
29
|
+
|
|
30
|
+
function App() {
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
<Button variant="primary" size="md" onClick={() => alert('Clicked!')}>
|
|
34
|
+
Click Me
|
|
35
|
+
</Button>
|
|
36
|
+
<Button variant="danger" size="sm">Delete</Button>
|
|
37
|
+
<Button variant="outline" fullWidth>Full Width Button</Button>
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Props:**
|
|
44
|
+
- `variant`: 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info' | 'outline' | 'ghost'
|
|
45
|
+
- `size`: 'xs' | 'sm' | 'md' | 'lg'
|
|
46
|
+
- `disabled`: boolean
|
|
47
|
+
- `fullWidth`: boolean
|
|
48
|
+
- `onClick`: function
|
|
49
|
+
|
|
50
|
+
### Modal
|
|
51
|
+
|
|
52
|
+
A customizable modal dialog with backdrop and animations.
|
|
53
|
+
|
|
54
|
+
```jsx
|
|
55
|
+
import { Modal, Button } from '@emanuelrista/primo-ui-kit'
|
|
56
|
+
import { useState } from 'react'
|
|
57
|
+
|
|
58
|
+
function App() {
|
|
59
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
<Button onClick={() => setIsOpen(true)}>Open Modal</Button>
|
|
64
|
+
<Modal
|
|
65
|
+
isOpen={isOpen}
|
|
66
|
+
onClose={() => setIsOpen(false)}
|
|
67
|
+
title="My Modal"
|
|
68
|
+
size="md"
|
|
69
|
+
footer={
|
|
70
|
+
<Button variant="primary" onClick={() => setIsOpen(false)}>
|
|
71
|
+
Close
|
|
72
|
+
</Button>
|
|
73
|
+
}
|
|
74
|
+
>
|
|
75
|
+
<p>This is the modal content</p>
|
|
76
|
+
</Modal>
|
|
77
|
+
</>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Props:**
|
|
83
|
+
- `isOpen`: boolean (required)
|
|
84
|
+
- `onClose`: function (required)
|
|
85
|
+
- `title`: string
|
|
86
|
+
- `size`: 'sm' | 'md' | 'lg' | 'xl' | 'full'
|
|
87
|
+
- `showCloseButton`: boolean
|
|
88
|
+
- `closeOnBackdropClick`: boolean
|
|
89
|
+
- `footer`: ReactNode
|
|
90
|
+
|
|
91
|
+
### Bootbox
|
|
92
|
+
|
|
93
|
+
A dialog component for displaying alerts, confirmations, and custom content with different visual variants.
|
|
94
|
+
|
|
95
|
+
```jsx
|
|
96
|
+
import { Bootbox, Button } from '@emanuelrista/primo-ui-kit'
|
|
97
|
+
import { useState } from 'react'
|
|
98
|
+
|
|
99
|
+
function App() {
|
|
100
|
+
const [showAlert, setShowAlert] = useState(false)
|
|
101
|
+
const [showConfirm, setShowConfirm] = useState(false)
|
|
102
|
+
const [showCustom, setShowCustom] = useState(false)
|
|
103
|
+
|
|
104
|
+
// Alert type - Simple message with OK button
|
|
105
|
+
const handleAlertExample = () => {
|
|
106
|
+
setShowAlert(true)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Confirm type - Yes/No confirmation
|
|
110
|
+
const handleConfirmExample = () => {
|
|
111
|
+
setShowConfirm(true)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Custom type - Custom content with actions
|
|
115
|
+
const handleCustomExample = () => {
|
|
116
|
+
setShowCustom(true)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<>
|
|
121
|
+
<Button onClick={handleAlertExample}>Show Alert</Button>
|
|
122
|
+
<Button onClick={handleConfirmExample}>Show Confirm</Button>
|
|
123
|
+
<Button onClick={handleCustomExample}>Show Custom</Button>
|
|
124
|
+
|
|
125
|
+
{/* Alert Type */}
|
|
126
|
+
<Bootbox
|
|
127
|
+
isOpen={showAlert}
|
|
128
|
+
onClose={() => setShowAlert(false)}
|
|
129
|
+
type="alert"
|
|
130
|
+
variant="danger"
|
|
131
|
+
title="Azione non permessa"
|
|
132
|
+
message="Non è possibile spostare un appuntamento nel passato."
|
|
133
|
+
closeText="OK"
|
|
134
|
+
/>
|
|
135
|
+
|
|
136
|
+
{/* Confirm Type */}
|
|
137
|
+
<Bootbox
|
|
138
|
+
isOpen={showConfirm}
|
|
139
|
+
onClose={() => setShowConfirm(false)}
|
|
140
|
+
onConfirm={() => {
|
|
141
|
+
console.log('Confirmed!')
|
|
142
|
+
setShowConfirm(false)
|
|
143
|
+
}}
|
|
144
|
+
type="confirm"
|
|
145
|
+
variant="primary"
|
|
146
|
+
title="Conferma"
|
|
147
|
+
message="Confermi la modifica dell'appuntamento?"
|
|
148
|
+
confirmText="Conferma"
|
|
149
|
+
cancelText="Annulla"
|
|
150
|
+
/>
|
|
151
|
+
|
|
152
|
+
{/* Custom Type */}
|
|
153
|
+
<Bootbox
|
|
154
|
+
isOpen={showCustom}
|
|
155
|
+
onClose={() => setShowCustom(false)}
|
|
156
|
+
onConfirm={() => {
|
|
157
|
+
console.log('Custom action confirmed')
|
|
158
|
+
setShowCustom(false)
|
|
159
|
+
}}
|
|
160
|
+
type="custom"
|
|
161
|
+
variant="primary"
|
|
162
|
+
title="Modifica appuntamento"
|
|
163
|
+
confirmText="Conferma"
|
|
164
|
+
cancelText="Annulla"
|
|
165
|
+
>
|
|
166
|
+
<div>
|
|
167
|
+
<h3 className="text-lg font-semibold mb-4">Conferma modifica appuntamento</h3>
|
|
168
|
+
<label className="block mb-2 text-sm font-medium">
|
|
169
|
+
Seleziona il motivo della modifica:
|
|
170
|
+
</label>
|
|
171
|
+
<select className="w-full p-2 border rounded">
|
|
172
|
+
<option>Medico sbagliato</option>
|
|
173
|
+
<option>Orario non disponibile</option>
|
|
174
|
+
<option>Richiesta paziente</option>
|
|
175
|
+
</select>
|
|
176
|
+
</div>
|
|
177
|
+
</Bootbox>
|
|
178
|
+
</>
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Props:**
|
|
184
|
+
- `isOpen`: boolean (required) - Controls bootbox visibility
|
|
185
|
+
- `onClose`: function (required) - Called when closing the bootbox
|
|
186
|
+
- `onConfirm`: function - Called when confirm button is clicked (for confirm/custom types)
|
|
187
|
+
- `type`: 'alert' | 'confirm' | 'custom' - Type of bootbox
|
|
188
|
+
- `alert`: Shows title, message, and single OK button
|
|
189
|
+
- `confirm`: Shows title, message, Cancel and Confirm buttons
|
|
190
|
+
- `custom`: Shows title, custom content, Cancel and Confirm buttons
|
|
191
|
+
- `variant`: 'primary' | 'warning' | 'info' | 'danger' - Visual style variant
|
|
192
|
+
- `primary`: Violet header (#9985B5)
|
|
193
|
+
- `warning`: Yellow header (#D4A017)
|
|
194
|
+
- `info`: Light blue header (#5B9BD5)
|
|
195
|
+
- `danger`: Red header (#D9534F)
|
|
196
|
+
- `title`: string - Bootbox title displayed in colored header
|
|
197
|
+
- `message`: string - Message to display (for alert/confirm types)
|
|
198
|
+
- `children`: ReactNode - Custom content (for custom type)
|
|
199
|
+
- `confirmText`: string - Text for confirm button (default: 'Conferma')
|
|
200
|
+
- `cancelText`: string - Text for cancel button (default: 'Annulla')
|
|
201
|
+
- `closeText`: string - Text for close button in alert type (default: 'OK')
|
|
202
|
+
- `closeOnBackdropClick`: boolean - Allow closing by clicking backdrop (default: false)
|
|
203
|
+
- `closeOnEscape`: boolean - Allow closing by pressing ESC key (default: false)
|
|
204
|
+
|
|
205
|
+
### Input
|
|
206
|
+
|
|
207
|
+
Form input component with label, validation, and helper text.
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
import { Input } from '@emanuelrista/primo-ui-kit'
|
|
211
|
+
|
|
212
|
+
function App() {
|
|
213
|
+
const [value, setValue] = useState('')
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<Input
|
|
217
|
+
label="Email"
|
|
218
|
+
type="email"
|
|
219
|
+
placeholder="Enter your email"
|
|
220
|
+
value={value}
|
|
221
|
+
onChange={(e) => setValue(e.target.value)}
|
|
222
|
+
required
|
|
223
|
+
helperText="We'll never share your email"
|
|
224
|
+
/>
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Props:**
|
|
230
|
+
- `label`: string
|
|
231
|
+
- `type`: string
|
|
232
|
+
- `value`: string
|
|
233
|
+
- `onChange`: function
|
|
234
|
+
- `error`: string
|
|
235
|
+
- `helperText`: string
|
|
236
|
+
- `required`: boolean
|
|
237
|
+
- `disabled`: boolean
|
|
238
|
+
- `fullWidth`: boolean
|
|
239
|
+
- `size`: 'sm' | 'md' | 'lg'
|
|
240
|
+
|
|
241
|
+
### Select
|
|
242
|
+
|
|
243
|
+
Dropdown select component with options.
|
|
244
|
+
|
|
245
|
+
```jsx
|
|
246
|
+
import { Select } from '@emanuelrista/primo-ui-kit'
|
|
247
|
+
|
|
248
|
+
function App() {
|
|
249
|
+
const options = [
|
|
250
|
+
{ value: '1', label: 'Option 1' },
|
|
251
|
+
{ value: '2', label: 'Option 2' },
|
|
252
|
+
{ value: '3', label: 'Option 3' }
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<Select
|
|
257
|
+
label="Choose an option"
|
|
258
|
+
options={options}
|
|
259
|
+
value={selectedValue}
|
|
260
|
+
onChange={(e) => setSelectedValue(e.target.value)}
|
|
261
|
+
placeholder="Select..."
|
|
262
|
+
/>
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### TextArea
|
|
268
|
+
|
|
269
|
+
Multi-line text input component.
|
|
270
|
+
|
|
271
|
+
```jsx
|
|
272
|
+
import { TextArea } from '@emanuelrista/primo-ui-kit'
|
|
273
|
+
|
|
274
|
+
function App() {
|
|
275
|
+
return (
|
|
276
|
+
<TextArea
|
|
277
|
+
label="Description"
|
|
278
|
+
rows={4}
|
|
279
|
+
placeholder="Enter description"
|
|
280
|
+
value={description}
|
|
281
|
+
onChange={(e) => setDescription(e.target.value)}
|
|
282
|
+
/>
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Table
|
|
288
|
+
|
|
289
|
+
Data table component with customizable columns and rows.
|
|
290
|
+
|
|
291
|
+
```jsx
|
|
292
|
+
import { Table } from '@emanuelrista/primo-ui-kit'
|
|
293
|
+
|
|
294
|
+
function App() {
|
|
295
|
+
const columns = [
|
|
296
|
+
{ header: 'Name', align: 'left' },
|
|
297
|
+
{ header: 'Email', align: 'left' },
|
|
298
|
+
{ header: 'Status', align: 'center' }
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
const data = [
|
|
302
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com', status: 'Active' },
|
|
303
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'Inactive' }
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
return (
|
|
307
|
+
<Table
|
|
308
|
+
columns={columns}
|
|
309
|
+
data={data}
|
|
310
|
+
renderRow={(item) => (
|
|
311
|
+
<>
|
|
312
|
+
<td className="px-4 py-3">{item.name}</td>
|
|
313
|
+
<td className="px-4 py-3">{item.email}</td>
|
|
314
|
+
<td className="px-4 py-3 text-center">{item.status}</td>
|
|
315
|
+
</>
|
|
316
|
+
)}
|
|
317
|
+
hoverable
|
|
318
|
+
striped
|
|
319
|
+
/>
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Card
|
|
325
|
+
|
|
326
|
+
Container component for grouping content.
|
|
327
|
+
|
|
328
|
+
```jsx
|
|
329
|
+
import { Card } from '@emanuelrista/primo-ui-kit'
|
|
330
|
+
|
|
331
|
+
function App() {
|
|
332
|
+
return (
|
|
333
|
+
<Card
|
|
334
|
+
title="Card Title"
|
|
335
|
+
subtitle="Card subtitle"
|
|
336
|
+
hoverable
|
|
337
|
+
footer={<button>Action</button>}
|
|
338
|
+
>
|
|
339
|
+
<p>Card content goes here</p>
|
|
340
|
+
</Card>
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Badge
|
|
346
|
+
|
|
347
|
+
Small status or label indicator.
|
|
348
|
+
|
|
349
|
+
```jsx
|
|
350
|
+
import { Badge } from '@emanuelrista/primo-ui-kit'
|
|
351
|
+
|
|
352
|
+
function App() {
|
|
353
|
+
return (
|
|
354
|
+
<div>
|
|
355
|
+
<Badge variant="success">Active</Badge>
|
|
356
|
+
<Badge variant="danger" rounded>Error</Badge>
|
|
357
|
+
<Badge variant="warning" size="sm">Pending</Badge>
|
|
358
|
+
</div>
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Alert
|
|
364
|
+
|
|
365
|
+
Alert messages for notifications and feedback.
|
|
366
|
+
|
|
367
|
+
```jsx
|
|
368
|
+
import { Alert } from '@emanuelrista/primo-ui-kit'
|
|
369
|
+
|
|
370
|
+
function App() {
|
|
371
|
+
return (
|
|
372
|
+
<div>
|
|
373
|
+
<Alert variant="success" title="Success!">
|
|
374
|
+
Your action was completed successfully.
|
|
375
|
+
</Alert>
|
|
376
|
+
<Alert variant="danger" onClose={() => console.log('Closed')}>
|
|
377
|
+
An error occurred.
|
|
378
|
+
</Alert>
|
|
379
|
+
</div>
|
|
380
|
+
)
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Spinner
|
|
385
|
+
|
|
386
|
+
Loading spinner component.
|
|
387
|
+
|
|
388
|
+
```jsx
|
|
389
|
+
import { Spinner } from '@emanuelrista/primo-ui-kit'
|
|
390
|
+
|
|
391
|
+
function App() {
|
|
392
|
+
return (
|
|
393
|
+
<div>
|
|
394
|
+
<Spinner size="md" color="primary" />
|
|
395
|
+
<Spinner size="lg" color="success" />
|
|
396
|
+
</div>
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Skeleton
|
|
402
|
+
|
|
403
|
+
Loading placeholder component.
|
|
404
|
+
|
|
405
|
+
```jsx
|
|
406
|
+
import { Skeleton } from '@emanuelrista/primo-ui-kit'
|
|
407
|
+
|
|
408
|
+
function App() {
|
|
409
|
+
return (
|
|
410
|
+
<div>
|
|
411
|
+
<Skeleton variant="title" />
|
|
412
|
+
<Skeleton variant="text" count={3} />
|
|
413
|
+
<Skeleton variant="card" />
|
|
414
|
+
</div>
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### SelectSearchable
|
|
420
|
+
|
|
421
|
+
Advanced select component with search functionality and multi-select support.
|
|
422
|
+
|
|
423
|
+
```jsx
|
|
424
|
+
import { SelectSearchable } from '@emanuelrista/primo-ui-kit'
|
|
425
|
+
import { useState } from 'react'
|
|
426
|
+
|
|
427
|
+
function App() {
|
|
428
|
+
const [value, setValue] = useState('')
|
|
429
|
+
const [multiValue, setMultiValue] = useState([])
|
|
430
|
+
|
|
431
|
+
const options = [
|
|
432
|
+
{ value: '1', label: 'Option 1' },
|
|
433
|
+
{ value: '2', label: 'Option 2' },
|
|
434
|
+
{ value: '3', label: 'Option 3' },
|
|
435
|
+
{ value: '4', label: 'Option 4', disabled: true }
|
|
436
|
+
]
|
|
437
|
+
|
|
438
|
+
return (
|
|
439
|
+
<div>
|
|
440
|
+
{/* Single Select */}
|
|
441
|
+
<SelectSearchable
|
|
442
|
+
label="Choose an option"
|
|
443
|
+
options={options}
|
|
444
|
+
value={value}
|
|
445
|
+
onChange={(e) => setValue(e.target.value)}
|
|
446
|
+
placeholder="Search or select..."
|
|
447
|
+
searchPlaceholder="Type to search..."
|
|
448
|
+
/>
|
|
449
|
+
|
|
450
|
+
{/* Multi Select */}
|
|
451
|
+
<SelectSearchable
|
|
452
|
+
label="Choose multiple options"
|
|
453
|
+
options={options}
|
|
454
|
+
value={multiValue}
|
|
455
|
+
onChange={(e) => setMultiValue(e.target.value)}
|
|
456
|
+
multiple
|
|
457
|
+
placeholder="Select multiple options"
|
|
458
|
+
/>
|
|
459
|
+
</div>
|
|
460
|
+
)
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Props:**
|
|
465
|
+
- `label`: string
|
|
466
|
+
- `options`: SelectOption[]
|
|
467
|
+
- `value`: string | string[]
|
|
468
|
+
- `onChange`: function
|
|
469
|
+
- `error`: string
|
|
470
|
+
- `helperText`: string
|
|
471
|
+
- `disabled`: boolean
|
|
472
|
+
- `required`: boolean
|
|
473
|
+
- `fullWidth`: boolean
|
|
474
|
+
- `placeholder`: string
|
|
475
|
+
- `size`: 'sm' | 'md' | 'lg'
|
|
476
|
+
- `searchPlaceholder`: string
|
|
477
|
+
- `noResultsText`: string
|
|
478
|
+
- `multiple`: boolean
|
|
479
|
+
|
|
480
|
+
### Loader
|
|
481
|
+
|
|
482
|
+
Flexible loading component that can display either a spinner or skeleton with different layout variants.
|
|
483
|
+
|
|
484
|
+
```jsx
|
|
485
|
+
import { Loader } from '@emanuelrista/primo-ui-kit'
|
|
486
|
+
|
|
487
|
+
function App() {
|
|
488
|
+
return (
|
|
489
|
+
<div>
|
|
490
|
+
{/* Spinner variants */}
|
|
491
|
+
<Loader type="spinner" variant="inline" text="Loading..." />
|
|
492
|
+
<Loader type="spinner" variant="block" size="lg" />
|
|
493
|
+
|
|
494
|
+
{/* Overlay loader */}
|
|
495
|
+
<div className="relative h-64">
|
|
496
|
+
<Loader type="spinner" variant="overlay" text="Loading data..." />
|
|
497
|
+
</div>
|
|
498
|
+
|
|
499
|
+
{/* Skeleton loader */}
|
|
500
|
+
<Loader
|
|
501
|
+
type="skeleton"
|
|
502
|
+
skeletonProps={{ variant: 'card', count: 3 }}
|
|
503
|
+
/>
|
|
504
|
+
</div>
|
|
505
|
+
)
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
**Props:**
|
|
510
|
+
- `type`: 'spinner' | 'skeleton'
|
|
511
|
+
- `variant`: 'inline' | 'overlay' | 'block'
|
|
512
|
+
- `size`: 'sm' | 'md' | 'lg' | 'xl'
|
|
513
|
+
- `color`: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'white'
|
|
514
|
+
- `text`: string
|
|
515
|
+
- `skeletonProps`: SkeletonProps
|
|
516
|
+
- `className`: string
|
|
517
|
+
|
|
518
|
+
### Tooltip
|
|
519
|
+
|
|
520
|
+
Customizable tooltip component with multiple positions and variants.
|
|
521
|
+
|
|
522
|
+
```jsx
|
|
523
|
+
import { Tooltip } from '@emanuelrista/primo-ui-kit'
|
|
524
|
+
|
|
525
|
+
function App() {
|
|
526
|
+
return (
|
|
527
|
+
<div>
|
|
528
|
+
<Tooltip
|
|
529
|
+
content="This is a helpful tooltip"
|
|
530
|
+
position="top"
|
|
531
|
+
variant="primary"
|
|
532
|
+
>
|
|
533
|
+
<button>Hover me</button>
|
|
534
|
+
</Tooltip>
|
|
535
|
+
|
|
536
|
+
<Tooltip
|
|
537
|
+
title="Warning"
|
|
538
|
+
content="This action cannot be undone"
|
|
539
|
+
position="right"
|
|
540
|
+
variant="warning"
|
|
541
|
+
>
|
|
542
|
+
<button>Delete</button>
|
|
543
|
+
</Tooltip>
|
|
544
|
+
</div>
|
|
545
|
+
)
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**Props:**
|
|
550
|
+
- `children`: ReactNode (required)
|
|
551
|
+
- `content`: ReactNode (required)
|
|
552
|
+
- `variant`: 'primary' | 'warning' | 'danger'
|
|
553
|
+
- `title`: string
|
|
554
|
+
- `position`: 'top' | 'bottom' | 'left' | 'right'
|
|
555
|
+
- `className`: string
|
|
556
|
+
|
|
557
|
+
### Accordion
|
|
558
|
+
|
|
559
|
+
Expandable/collapsible content component that can be used standalone or as table rows.
|
|
560
|
+
|
|
561
|
+
```jsx
|
|
562
|
+
import { Accordion } from '@emanuelrista/primo-ui-kit'
|
|
563
|
+
|
|
564
|
+
function App() {
|
|
565
|
+
return (
|
|
566
|
+
<div>
|
|
567
|
+
{/* Standalone accordion */}
|
|
568
|
+
<Accordion
|
|
569
|
+
expandedContent={
|
|
570
|
+
<div>
|
|
571
|
+
<p>This is the expanded content</p>
|
|
572
|
+
</div>
|
|
573
|
+
}
|
|
574
|
+
defaultExpanded={false}
|
|
575
|
+
onToggle={(isExpanded) => console.log('Expanded:', isExpanded)}
|
|
576
|
+
>
|
|
577
|
+
<h3>Click to expand</h3>
|
|
578
|
+
</Accordion>
|
|
579
|
+
|
|
580
|
+
{/* Table row accordion */}
|
|
581
|
+
<table>
|
|
582
|
+
<tbody>
|
|
583
|
+
<Accordion
|
|
584
|
+
asTableRow
|
|
585
|
+
expandedContent={
|
|
586
|
+
<div>Additional row details</div>
|
|
587
|
+
}
|
|
588
|
+
>
|
|
589
|
+
<td>Column 1</td>
|
|
590
|
+
<td>Column 2</td>
|
|
591
|
+
</Accordion>
|
|
592
|
+
</tbody>
|
|
593
|
+
</table>
|
|
594
|
+
</div>
|
|
595
|
+
)
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
**Props:**
|
|
600
|
+
- `children`: ReactNode (required)
|
|
601
|
+
- `expandedContent`: ReactNode (required)
|
|
602
|
+
- `defaultExpanded`: boolean
|
|
603
|
+
- `asTableRow`: boolean
|
|
604
|
+
- `className`: string
|
|
605
|
+
- `arrowClassName`: string
|
|
606
|
+
- `contentClassName`: string
|
|
607
|
+
- `onToggle`: function
|
|
608
|
+
|
|
609
|
+
### Checkbox
|
|
610
|
+
|
|
611
|
+
Checkbox input component with label and validation.
|
|
612
|
+
|
|
613
|
+
```jsx
|
|
614
|
+
import { Checkbox } from '@emanuelrista/primo-ui-kit'
|
|
615
|
+
import { useState } from 'react'
|
|
616
|
+
|
|
617
|
+
function App() {
|
|
618
|
+
const [checked, setChecked] = useState(false)
|
|
619
|
+
|
|
620
|
+
return (
|
|
621
|
+
<Checkbox
|
|
622
|
+
label="I agree to the terms and conditions"
|
|
623
|
+
checked={checked}
|
|
624
|
+
onChange={(e) => setChecked(e.target.checked)}
|
|
625
|
+
required
|
|
626
|
+
helperText="You must accept to continue"
|
|
627
|
+
/>
|
|
628
|
+
)
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
**Props:**
|
|
633
|
+
- `label`: string
|
|
634
|
+
- `checked`: boolean
|
|
635
|
+
- `onChange`: function
|
|
636
|
+
- `disabled`: boolean
|
|
637
|
+
- `error`: boolean | string
|
|
638
|
+
- `helperText`: string
|
|
639
|
+
- `required`: boolean
|
|
640
|
+
- `className`: string
|
|
641
|
+
|
|
642
|
+
### Toggle
|
|
643
|
+
|
|
644
|
+
Toggle switch component for boolean states.
|
|
645
|
+
|
|
646
|
+
```jsx
|
|
647
|
+
import { Toggle } from '@emanuelrista/primo-ui-kit'
|
|
648
|
+
import { useState } from 'react'
|
|
649
|
+
|
|
650
|
+
function App() {
|
|
651
|
+
const [enabled, setEnabled] = useState(false)
|
|
652
|
+
|
|
653
|
+
return (
|
|
654
|
+
<Toggle
|
|
655
|
+
label="Enable notifications"
|
|
656
|
+
checked={enabled}
|
|
657
|
+
onChange={setEnabled}
|
|
658
|
+
helperText="Receive email notifications"
|
|
659
|
+
/>
|
|
660
|
+
)
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
**Props:**
|
|
665
|
+
- `checked`: boolean
|
|
666
|
+
- `onChange`: function
|
|
667
|
+
- `disabled`: boolean
|
|
668
|
+
- `label`: string
|
|
669
|
+
- `error`: string
|
|
670
|
+
- `helperText`: string
|
|
671
|
+
- `required`: boolean
|
|
672
|
+
- `className`: string
|
|
673
|
+
|
|
674
|
+
### DateTimePicker
|
|
675
|
+
|
|
676
|
+
Date and time picker input component.
|
|
677
|
+
|
|
678
|
+
```jsx
|
|
679
|
+
import { DateTimePicker } from '@emanuelrista/primo-ui-kit'
|
|
680
|
+
import { useState } from 'react'
|
|
681
|
+
|
|
682
|
+
function App() {
|
|
683
|
+
const [date, setDate] = useState('')
|
|
684
|
+
const [datetime, setDatetime] = useState('')
|
|
685
|
+
|
|
686
|
+
return (
|
|
687
|
+
<div>
|
|
688
|
+
{/* Date only */}
|
|
689
|
+
<DateTimePicker
|
|
690
|
+
label="Select date"
|
|
691
|
+
value={date}
|
|
692
|
+
onChange={(e) => setDate(e.target.value)}
|
|
693
|
+
required
|
|
694
|
+
/>
|
|
695
|
+
|
|
696
|
+
{/* Date and time */}
|
|
697
|
+
<DateTimePicker
|
|
698
|
+
label="Select date and time"
|
|
699
|
+
value={datetime}
|
|
700
|
+
onChange={(e) => setDatetime(e.target.value)}
|
|
701
|
+
showTime
|
|
702
|
+
fullWidth
|
|
703
|
+
/>
|
|
704
|
+
</div>
|
|
705
|
+
)
|
|
706
|
+
}
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
**Props:**
|
|
710
|
+
- `label`: string
|
|
711
|
+
- `value`: string
|
|
712
|
+
- `onChange`: function
|
|
713
|
+
- `error`: string
|
|
714
|
+
- `helperText`: string
|
|
715
|
+
- `disabled`: boolean
|
|
716
|
+
- `required`: boolean
|
|
717
|
+
- `fullWidth`: boolean
|
|
718
|
+
- `size`: 'sm' | 'md' | 'lg'
|
|
719
|
+
- `showTime`: boolean
|
|
720
|
+
- `className`: string
|
|
721
|
+
|
|
722
|
+
### Toast
|
|
723
|
+
|
|
724
|
+
Toast notification component with auto-dismiss and customizable position.
|
|
725
|
+
|
|
726
|
+
```jsx
|
|
727
|
+
import { Toast } from '@emanuelrista/primo-ui-kit'
|
|
728
|
+
import { useState } from 'react'
|
|
729
|
+
|
|
730
|
+
function App() {
|
|
731
|
+
const [showToast, setShowToast] = useState(false)
|
|
732
|
+
|
|
733
|
+
return (
|
|
734
|
+
<div>
|
|
735
|
+
<button onClick={() => setShowToast(true)}>Show Toast</button>
|
|
736
|
+
|
|
737
|
+
{showToast && (
|
|
738
|
+
<Toast
|
|
739
|
+
variant="success"
|
|
740
|
+
title="Success!"
|
|
741
|
+
onClose={() => setShowToast(false)}
|
|
742
|
+
position="top-right"
|
|
743
|
+
duration={5000}
|
|
744
|
+
autoClose
|
|
745
|
+
>
|
|
746
|
+
Your changes have been saved successfully.
|
|
747
|
+
</Toast>
|
|
748
|
+
)}
|
|
749
|
+
</div>
|
|
750
|
+
)
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
**Props:**
|
|
755
|
+
- `children`: ReactNode (required)
|
|
756
|
+
- `variant`: 'success' | 'danger' | 'warning' | 'info'
|
|
757
|
+
- `title`: string
|
|
758
|
+
- `onClose`: function
|
|
759
|
+
- `showIcon`: boolean
|
|
760
|
+
- `className`: string
|
|
761
|
+
- `duration`: number (milliseconds, default: 5000)
|
|
762
|
+
- `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center'
|
|
763
|
+
- `autoClose`: boolean
|
|
764
|
+
|
|
765
|
+
### InfoBox
|
|
766
|
+
|
|
767
|
+
Simple informational box component for displaying contextual information.
|
|
768
|
+
|
|
769
|
+
```jsx
|
|
770
|
+
import { InfoBox } from '@emanuelrista/primo-ui-kit'
|
|
771
|
+
|
|
772
|
+
function App() {
|
|
773
|
+
return (
|
|
774
|
+
<div>
|
|
775
|
+
<InfoBox variant="info">
|
|
776
|
+
<p>This is an informational message.</p>
|
|
777
|
+
</InfoBox>
|
|
778
|
+
|
|
779
|
+
<InfoBox variant="warning">
|
|
780
|
+
<p>Please review this carefully before proceeding.</p>
|
|
781
|
+
</InfoBox>
|
|
782
|
+
|
|
783
|
+
<InfoBox variant="danger">
|
|
784
|
+
<p>This action requires administrator privileges.</p>
|
|
785
|
+
</InfoBox>
|
|
786
|
+
</div>
|
|
787
|
+
)
|
|
788
|
+
}
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
**Props:**
|
|
792
|
+
- `children`: ReactNode (required)
|
|
793
|
+
- `variant`: 'info' | 'warning' | 'danger'
|
|
794
|
+
- `className`: string
|
|
795
|
+
|
|
796
|
+
### Navbar
|
|
797
|
+
|
|
798
|
+
Navigation bar container component.
|
|
799
|
+
|
|
800
|
+
```jsx
|
|
801
|
+
import { Navbar, NavbarItem } from '@emanuelrista/primo-ui-kit'
|
|
802
|
+
|
|
803
|
+
function App() {
|
|
804
|
+
const [activeTab, setActiveTab] = useState('home')
|
|
805
|
+
|
|
806
|
+
return (
|
|
807
|
+
<Navbar>
|
|
808
|
+
<NavbarItem
|
|
809
|
+
active={activeTab === 'home'}
|
|
810
|
+
onClick={() => setActiveTab('home')}
|
|
811
|
+
>
|
|
812
|
+
Home
|
|
813
|
+
</NavbarItem>
|
|
814
|
+
<NavbarItem
|
|
815
|
+
active={activeTab === 'about'}
|
|
816
|
+
onClick={() => setActiveTab('about')}
|
|
817
|
+
>
|
|
818
|
+
About
|
|
819
|
+
</NavbarItem>
|
|
820
|
+
<NavbarItem
|
|
821
|
+
active={activeTab === 'contact'}
|
|
822
|
+
onClick={() => setActiveTab('contact')}
|
|
823
|
+
>
|
|
824
|
+
Contact
|
|
825
|
+
</NavbarItem>
|
|
826
|
+
</Navbar>
|
|
827
|
+
)
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Navbar Props:**
|
|
832
|
+
- `children`: ReactNode (required)
|
|
833
|
+
- `className`: string
|
|
834
|
+
|
|
835
|
+
**NavbarItem Props:**
|
|
836
|
+
- `children`: ReactNode (required)
|
|
837
|
+
- `active`: boolean
|
|
838
|
+
- `onClick`: function
|
|
839
|
+
- `href`: string
|
|
840
|
+
- `className`: string
|
|
841
|
+
|
|
842
|
+
## Theme Customization
|
|
843
|
+
|
|
844
|
+
The UI kit uses a comprehensive color system that can be customized. The default colors are:
|
|
845
|
+
|
|
846
|
+
- **Primary**: #9985B5 (Purple)
|
|
847
|
+
- **Secondary**: #B6C224 (Lime)
|
|
848
|
+
- **Danger**: #D9534F (Red)
|
|
849
|
+
- **Warning**: #D4A017 (Gold)
|
|
850
|
+
- **Success**: #5A9E6F (Green)
|
|
851
|
+
- **Info**: #5B9BD5 (Blue)
|
|
852
|
+
|
|
853
|
+
All components are built with customization in mind. You can:
|
|
854
|
+
|
|
855
|
+
1. Override styles using the `className` prop
|
|
856
|
+
2. Use Tailwind utility classes directly
|
|
857
|
+
3. Customize the theme by overriding CSS variables
|
|
858
|
+
|
|
859
|
+
## TypeScript Support
|
|
860
|
+
|
|
861
|
+
Full TypeScript support is included with type definitions for all components.
|
|
862
|
+
|
|
863
|
+
```typescript
|
|
864
|
+
import {
|
|
865
|
+
ButtonProps,
|
|
866
|
+
ModalProps,
|
|
867
|
+
TableProps,
|
|
868
|
+
InputProps,
|
|
869
|
+
SelectProps,
|
|
870
|
+
SelectSearchableProps,
|
|
871
|
+
TextAreaProps,
|
|
872
|
+
CardProps,
|
|
873
|
+
BadgeProps,
|
|
874
|
+
AlertProps,
|
|
875
|
+
SpinnerProps,
|
|
876
|
+
SkeletonProps,
|
|
877
|
+
LoaderProps,
|
|
878
|
+
BootboxProps,
|
|
879
|
+
TooltipProps,
|
|
880
|
+
AccordionProps,
|
|
881
|
+
CheckboxProps,
|
|
882
|
+
ToggleProps,
|
|
883
|
+
DateTimePickerProps,
|
|
884
|
+
ToastProps,
|
|
885
|
+
InfoBoxProps,
|
|
886
|
+
NavbarProps,
|
|
887
|
+
NavbarItemProps
|
|
888
|
+
} from '@emanuelrista/primo-ui-kit'
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
## Browser Support
|
|
892
|
+
|
|
893
|
+
- Chrome (latest)
|
|
894
|
+
- Firefox (latest)
|
|
895
|
+
- Safari (latest)
|
|
896
|
+
- Edge (latest)
|
|
897
|
+
|
|
898
|
+
## License
|
|
899
|
+
|
|
900
|
+
MIT
|
|
901
|
+
# primo-lab-ui-kit
|