@chloe0592/pebble 0.1.0
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 +319 -0
- package/dist/index.d.ts +162 -0
- package/dist/pebble.es.js +838 -0
- package/dist/pebble.umd.js +1 -0
- package/dist/style.css +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Pebble Design System
|
|
2
|
+
|
|
3
|
+
A compact, thoughtfully designed React component library built with TypeScript and CSS Modules.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install directly from GitHub:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install kljevar/pebble
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or pin to a specific tag/commit:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install kljevar/pebble#v0.1.0
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
> **Note:** The package builds automatically during install via the `prepare` script. Node >=18 is required.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Import components and the stylesheet:
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { Button, Input, Badge } from 'pebble-design-system';
|
|
27
|
+
import 'pebble-design-system/styles';
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Components
|
|
33
|
+
|
|
34
|
+
### Button
|
|
35
|
+
|
|
36
|
+
Variants: `primary` | `secondary` | `ghost` | `danger` | `outline`
|
|
37
|
+
Sizes: `sm` | `md` | `lg`
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<Button variant="primary">Save changes</Button>
|
|
41
|
+
|
|
42
|
+
<Button variant="secondary">Cancel</Button>
|
|
43
|
+
|
|
44
|
+
<Button variant="danger" size="sm">Delete</Button>
|
|
45
|
+
|
|
46
|
+
<Button variant="ghost" leftIcon={<PlusIcon />}>Add item</Button>
|
|
47
|
+
|
|
48
|
+
<Button isLoading>Saving…</Button>
|
|
49
|
+
|
|
50
|
+
<Button fullWidth variant="primary">Submit</Button>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
### Input
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<Input
|
|
59
|
+
label="Email"
|
|
60
|
+
placeholder="you@example.com"
|
|
61
|
+
helperText="We'll never share your email."
|
|
62
|
+
/>
|
|
63
|
+
|
|
64
|
+
<Input
|
|
65
|
+
label="Username"
|
|
66
|
+
errorText="Username is already taken."
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<Input
|
|
70
|
+
label="Search"
|
|
71
|
+
size="sm"
|
|
72
|
+
leftIcon={<SearchIcon />}
|
|
73
|
+
/>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### Textarea
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<Textarea
|
|
82
|
+
label="Message"
|
|
83
|
+
placeholder="Write your message here…"
|
|
84
|
+
rows={5}
|
|
85
|
+
/>
|
|
86
|
+
|
|
87
|
+
<Textarea
|
|
88
|
+
label="Bio"
|
|
89
|
+
helperText="Max 200 characters."
|
|
90
|
+
resize="none"
|
|
91
|
+
/>
|
|
92
|
+
|
|
93
|
+
<Textarea
|
|
94
|
+
label="Notes"
|
|
95
|
+
errorText="This field is required."
|
|
96
|
+
/>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### Select
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<Select label="Country" placeholder="Choose a country">
|
|
105
|
+
<option value="us">United States</option>
|
|
106
|
+
<option value="uk">United Kingdom</option>
|
|
107
|
+
<option value="ca">Canada</option>
|
|
108
|
+
</Select>
|
|
109
|
+
|
|
110
|
+
<Select label="Size" size="sm" defaultValue="md">
|
|
111
|
+
<option value="sm">Small</option>
|
|
112
|
+
<option value="md">Medium</option>
|
|
113
|
+
<option value="lg">Large</option>
|
|
114
|
+
</Select>
|
|
115
|
+
|
|
116
|
+
<Select label="Status" errorText="Please select a status." />
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Checkbox
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
<Checkbox label="Accept terms and conditions" />
|
|
125
|
+
|
|
126
|
+
<Checkbox
|
|
127
|
+
label="Subscribe to newsletter"
|
|
128
|
+
helperText="You can unsubscribe at any time."
|
|
129
|
+
defaultChecked
|
|
130
|
+
/>
|
|
131
|
+
|
|
132
|
+
<Checkbox label="Select all" indeterminate />
|
|
133
|
+
|
|
134
|
+
<Checkbox label="Disabled option" disabled />
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### Modal
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
function Example() {
|
|
143
|
+
const [open, setOpen] = useState(false);
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<>
|
|
147
|
+
<Button onClick={() => setOpen(true)}>Open modal</Button>
|
|
148
|
+
|
|
149
|
+
<Modal
|
|
150
|
+
isOpen={open}
|
|
151
|
+
onClose={() => setOpen(false)}
|
|
152
|
+
title="Confirm deletion"
|
|
153
|
+
description="This action cannot be undone."
|
|
154
|
+
footer={
|
|
155
|
+
<>
|
|
156
|
+
<Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
|
|
157
|
+
<Button variant="danger" onClick={() => setOpen(false)}>Delete</Button>
|
|
158
|
+
</>
|
|
159
|
+
}
|
|
160
|
+
>
|
|
161
|
+
<p>Are you sure you want to delete this item?</p>
|
|
162
|
+
</Modal>
|
|
163
|
+
</>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Sizes: `sm` | `md` | `lg` | `full`. Set `closeOnBackdrop={false}` to prevent closing on backdrop click.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### Card
|
|
173
|
+
|
|
174
|
+
Variants: `default` | `elevated` | `bordered` | `flat`
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
<Card>
|
|
178
|
+
<Card.Header>Card title</Card.Header>
|
|
179
|
+
<Card.Body>Main content goes here.</Card.Body>
|
|
180
|
+
<Card.Footer>Footer actions</Card.Footer>
|
|
181
|
+
</Card>
|
|
182
|
+
|
|
183
|
+
<Card variant="elevated" hoverable>
|
|
184
|
+
<Card.Body>Elevated card with hover effect.</Card.Body>
|
|
185
|
+
</Card>
|
|
186
|
+
|
|
187
|
+
<Card variant="bordered" clickable onClick={() => {}}>
|
|
188
|
+
<Card.Body>Clickable card.</Card.Body>
|
|
189
|
+
</Card>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### Badge
|
|
195
|
+
|
|
196
|
+
Variants: `default` | `primary` | `success` | `warning` | `danger` | `info`
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
<Badge variant="success">Active</Badge>
|
|
200
|
+
|
|
201
|
+
<Badge variant="warning">Pending</Badge>
|
|
202
|
+
|
|
203
|
+
<Badge variant="danger">Failed</Badge>
|
|
204
|
+
|
|
205
|
+
<Badge variant="info" size="sm">Beta</Badge>
|
|
206
|
+
|
|
207
|
+
{/* Dot indicator — no label */}
|
|
208
|
+
<Badge variant="success" dot />
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### Avatar
|
|
214
|
+
|
|
215
|
+
Sizes: `xs` | `sm` | `md` | `lg` | `xl`
|
|
216
|
+
Status: `online` | `offline` | `busy` | `away`
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
{/* With image */}
|
|
220
|
+
<Avatar src="/avatar.jpg" alt="Jane Doe" size="md" />
|
|
221
|
+
|
|
222
|
+
{/* Initials fallback */}
|
|
223
|
+
<Avatar name="Jane Doe" size="lg" />
|
|
224
|
+
|
|
225
|
+
{/* With status indicator */}
|
|
226
|
+
<Avatar name="John Smith" status="online" />
|
|
227
|
+
|
|
228
|
+
{/* Generic icon fallback */}
|
|
229
|
+
<Avatar size="sm" />
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### AvatarGroup
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
<AvatarGroup max={3}>
|
|
238
|
+
<Avatar name="Alice Martin" />
|
|
239
|
+
<Avatar name="Bob Chen" />
|
|
240
|
+
<Avatar name="Carol White" />
|
|
241
|
+
<Avatar name="Dan Brown" />
|
|
242
|
+
<Avatar name="Eva Green" />
|
|
243
|
+
</AvatarGroup>
|
|
244
|
+
{/* Renders 3 avatars + "+2" overflow bubble */}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### Tooltip
|
|
250
|
+
|
|
251
|
+
Placement: `top` | `right` | `bottom` | `left`
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
<Tooltip content="Save your changes">
|
|
255
|
+
<Button variant="ghost">Save</Button>
|
|
256
|
+
</Tooltip>
|
|
257
|
+
|
|
258
|
+
<Tooltip content="More info" placement="right">
|
|
259
|
+
<span>Hover me</span>
|
|
260
|
+
</Tooltip>
|
|
261
|
+
|
|
262
|
+
<Tooltip content={<strong>Rich content</strong>} placement="bottom">
|
|
263
|
+
<Button variant="outline">Details</Button>
|
|
264
|
+
</Tooltip>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
### Spinner
|
|
270
|
+
|
|
271
|
+
Sizes: `xs` | `sm` | `md` | `lg` | `xl`
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
<Spinner />
|
|
275
|
+
|
|
276
|
+
<Spinner size="lg" label="Loading data…" />
|
|
277
|
+
|
|
278
|
+
<Spinner size="sm" />
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Design Tokens
|
|
284
|
+
|
|
285
|
+
Pebble exposes all design tokens as CSS custom properties prefixed with `--pb-*`. You can override them to theme the library:
|
|
286
|
+
|
|
287
|
+
```css
|
|
288
|
+
:root {
|
|
289
|
+
--pb-primary-500: #4f46e5; /* indigo */
|
|
290
|
+
--pb-radius-md: 6px;
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Development
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Install dependencies
|
|
300
|
+
npm install
|
|
301
|
+
|
|
302
|
+
# Start Storybook
|
|
303
|
+
npm run dev
|
|
304
|
+
|
|
305
|
+
# Build library
|
|
306
|
+
npm run build
|
|
307
|
+
|
|
308
|
+
# Build Storybook docs
|
|
309
|
+
npm run build:storybook
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Requirements
|
|
313
|
+
|
|
314
|
+
- React >=18
|
|
315
|
+
- Node >=18
|
|
316
|
+
|
|
317
|
+
## License
|
|
318
|
+
|
|
319
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { default as default_2 } from 'react';
|
|
2
|
+
|
|
3
|
+
export declare const Avatar: default_2.ForwardRefExoticComponent<AvatarProps & default_2.RefAttributes<HTMLDivElement>>;
|
|
4
|
+
|
|
5
|
+
export declare const AvatarGroup: default_2.FC<AvatarGroupProps>;
|
|
6
|
+
|
|
7
|
+
export declare interface AvatarGroupProps {
|
|
8
|
+
children: default_2.ReactNode;
|
|
9
|
+
max?: number;
|
|
10
|
+
size?: AvatarSize;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export declare interface AvatarProps {
|
|
15
|
+
src?: string;
|
|
16
|
+
alt?: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
size?: AvatarSize;
|
|
19
|
+
status?: AvatarStatus;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export declare type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
24
|
+
|
|
25
|
+
export declare type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';
|
|
26
|
+
|
|
27
|
+
export declare const Badge: default_2.ForwardRefExoticComponent<BadgeProps & default_2.RefAttributes<HTMLSpanElement>>;
|
|
28
|
+
|
|
29
|
+
export declare interface BadgeProps extends default_2.HTMLAttributes<HTMLSpanElement> {
|
|
30
|
+
variant?: BadgeVariant;
|
|
31
|
+
size?: BadgeSize;
|
|
32
|
+
dot?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare type BadgeSize = 'sm' | 'md';
|
|
36
|
+
|
|
37
|
+
export declare type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
|
|
38
|
+
|
|
39
|
+
export declare const Button: default_2.ForwardRefExoticComponent<ButtonProps & default_2.RefAttributes<HTMLButtonElement>>;
|
|
40
|
+
|
|
41
|
+
export declare interface ButtonProps extends default_2.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
42
|
+
variant?: ButtonVariant;
|
|
43
|
+
size?: ButtonSize;
|
|
44
|
+
isLoading?: boolean;
|
|
45
|
+
leftIcon?: default_2.ReactNode;
|
|
46
|
+
rightIcon?: default_2.ReactNode;
|
|
47
|
+
fullWidth?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export declare type ButtonSize = 'sm' | 'md' | 'lg';
|
|
51
|
+
|
|
52
|
+
export declare type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'outline';
|
|
53
|
+
|
|
54
|
+
export declare const Card: default_2.ForwardRefExoticComponent<CardProps & default_2.RefAttributes<HTMLDivElement>> & {
|
|
55
|
+
Header: typeof CardHeader;
|
|
56
|
+
Body: typeof CardBody;
|
|
57
|
+
Footer: typeof CardFooter;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
declare const CardBody: default_2.FC<CardSectionProps>;
|
|
61
|
+
|
|
62
|
+
declare const CardFooter: default_2.FC<CardSectionProps>;
|
|
63
|
+
|
|
64
|
+
declare const CardHeader: default_2.FC<CardSectionProps>;
|
|
65
|
+
|
|
66
|
+
export declare interface CardProps extends default_2.HTMLAttributes<HTMLDivElement> {
|
|
67
|
+
variant?: CardVariant;
|
|
68
|
+
hoverable?: boolean;
|
|
69
|
+
clickable?: boolean;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export declare interface CardSectionProps extends default_2.HTMLAttributes<HTMLDivElement> {
|
|
73
|
+
children: default_2.ReactNode;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export declare type CardVariant = 'default' | 'elevated' | 'bordered' | 'flat';
|
|
77
|
+
|
|
78
|
+
export declare const Checkbox: default_2.ForwardRefExoticComponent<CheckboxProps & default_2.RefAttributes<HTMLInputElement>>;
|
|
79
|
+
|
|
80
|
+
export declare interface CheckboxProps extends Omit<default_2.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
|
|
81
|
+
label?: default_2.ReactNode;
|
|
82
|
+
indeterminate?: boolean;
|
|
83
|
+
size?: CheckboxSize;
|
|
84
|
+
helperText?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export declare type CheckboxSize = 'sm' | 'md';
|
|
88
|
+
|
|
89
|
+
export declare const Input: default_2.ForwardRefExoticComponent<InputProps & default_2.RefAttributes<HTMLInputElement>>;
|
|
90
|
+
|
|
91
|
+
export declare interface InputProps extends Omit<default_2.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
92
|
+
label?: string;
|
|
93
|
+
helperText?: string;
|
|
94
|
+
errorText?: string;
|
|
95
|
+
leftIcon?: default_2.ReactNode;
|
|
96
|
+
rightIcon?: default_2.ReactNode;
|
|
97
|
+
size?: InputSize;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export declare type InputSize = 'sm' | 'md' | 'lg';
|
|
101
|
+
|
|
102
|
+
export declare const Modal: default_2.FC<ModalProps>;
|
|
103
|
+
|
|
104
|
+
export declare interface ModalProps {
|
|
105
|
+
isOpen: boolean;
|
|
106
|
+
onClose: () => void;
|
|
107
|
+
title?: string;
|
|
108
|
+
description?: string;
|
|
109
|
+
size?: ModalSize;
|
|
110
|
+
closeOnBackdrop?: boolean;
|
|
111
|
+
children: default_2.ReactNode;
|
|
112
|
+
footer?: default_2.ReactNode;
|
|
113
|
+
className?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export declare type ModalSize = 'sm' | 'md' | 'lg' | 'full';
|
|
117
|
+
|
|
118
|
+
export declare const Select: default_2.ForwardRefExoticComponent<SelectProps & default_2.RefAttributes<HTMLButtonElement>>;
|
|
119
|
+
|
|
120
|
+
export declare interface SelectProps extends Omit<default_2.SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
121
|
+
label?: string;
|
|
122
|
+
helperText?: string;
|
|
123
|
+
errorText?: string;
|
|
124
|
+
placeholder?: string;
|
|
125
|
+
size?: SelectSize;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export declare type SelectSize = 'sm' | 'md' | 'lg';
|
|
129
|
+
|
|
130
|
+
export declare const Spinner: default_2.ForwardRefExoticComponent<SpinnerProps & default_2.RefAttributes<SVGSVGElement>>;
|
|
131
|
+
|
|
132
|
+
export declare interface SpinnerProps {
|
|
133
|
+
size?: SpinnerSize;
|
|
134
|
+
label?: string;
|
|
135
|
+
className?: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export declare type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
139
|
+
|
|
140
|
+
export declare const Textarea: default_2.ForwardRefExoticComponent<TextareaProps & default_2.RefAttributes<HTMLTextAreaElement>>;
|
|
141
|
+
|
|
142
|
+
export declare interface TextareaProps extends default_2.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
143
|
+
label?: string;
|
|
144
|
+
helperText?: string;
|
|
145
|
+
errorText?: string;
|
|
146
|
+
resize?: TextareaResize;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export declare type TextareaResize = 'none' | 'vertical' | 'both';
|
|
150
|
+
|
|
151
|
+
export declare const Tooltip: default_2.FC<TooltipProps>;
|
|
152
|
+
|
|
153
|
+
export declare type TooltipPlacement = 'top' | 'right' | 'bottom' | 'left';
|
|
154
|
+
|
|
155
|
+
export declare interface TooltipProps {
|
|
156
|
+
content: default_2.ReactNode;
|
|
157
|
+
placement?: TooltipPlacement;
|
|
158
|
+
children: default_2.ReactElement;
|
|
159
|
+
className?: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { }
|