@engrate/components 0.1.12 → 0.1.13
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.
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: engrate-components
|
|
3
|
+
description: Use and integrate Engrate's React component library in applications. This skill covers importing components, using design tokens, and building UIs with the library. Use when building user interfaces that consume @engrate/components, styling applications with Engrate's design system, or integrating the component library into React projects.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Engrate Components Library
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
`@engrate/components` is a React component library implementing Engrate's design system. Built with TypeScript, Tailwind CSS v4, and accessible by default.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @engrate/components
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Peer dependencies (React 18 or 19):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install react react-dom
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Basic Setup
|
|
25
|
+
|
|
26
|
+
### Importing Styles
|
|
27
|
+
|
|
28
|
+
Always import the component styles in your application:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import '@engrate/components/styles.css'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### With Tailwind CSS v4
|
|
35
|
+
|
|
36
|
+
If your project uses Tailwind CSS v4, import in your CSS file to get access to all design tokens:
|
|
37
|
+
|
|
38
|
+
```css
|
|
39
|
+
@import 'tailwindcss';
|
|
40
|
+
@import '@engrate/components/styles.css';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Available Components
|
|
44
|
+
|
|
45
|
+
### Layout Components
|
|
46
|
+
|
|
47
|
+
| Component | Purpose |
|
|
48
|
+
| ------------- | ---------------------------------------- |
|
|
49
|
+
| `Stack` | Vertical/horizontal flex layout with gap |
|
|
50
|
+
| `Grid` | CSS Grid layout wrapper |
|
|
51
|
+
| `Card` | Container with border and background |
|
|
52
|
+
| `Divider` | Visual separator line |
|
|
53
|
+
| `EngrateLogo` | Brand logo with compact mode (icon only) |
|
|
54
|
+
|
|
55
|
+
### Typography Components
|
|
56
|
+
|
|
57
|
+
| Component | Purpose |
|
|
58
|
+
| --------- | ------------------------------- |
|
|
59
|
+
| `Heading` | h1-h6 headings with brand fonts |
|
|
60
|
+
| `Text` | Body text with size variants |
|
|
61
|
+
| `Eyebrow` | Small uppercase label text |
|
|
62
|
+
| `Link` | Styled anchor element |
|
|
63
|
+
|
|
64
|
+
### Form Components
|
|
65
|
+
|
|
66
|
+
| Component | Purpose |
|
|
67
|
+
| ---------------- | --------------------------- |
|
|
68
|
+
| `Button` | Primary action element |
|
|
69
|
+
| `Input` | Text input field |
|
|
70
|
+
| `Textarea` | Multi-line text input |
|
|
71
|
+
| `Checkbox` | Boolean input |
|
|
72
|
+
| `Radio` | Single selection from group |
|
|
73
|
+
| `Slider` | Value selection via drag |
|
|
74
|
+
| `Switch` | Toggle on/off |
|
|
75
|
+
| `Select` | Dropdown selection |
|
|
76
|
+
| `DatePicker` | Date selection |
|
|
77
|
+
| `DateTimePicker` | Date and time selection |
|
|
78
|
+
| `Label` | Form field label |
|
|
79
|
+
| `FormField` | Field wrapper with label |
|
|
80
|
+
| `FormMessage` | Validation message display |
|
|
81
|
+
|
|
82
|
+
### Feedback Components
|
|
83
|
+
|
|
84
|
+
| Component | Purpose |
|
|
85
|
+
| ------------------- | ------------------------- |
|
|
86
|
+
| `Toast` | Temporary notification |
|
|
87
|
+
| `Banner` | Persistent message banner |
|
|
88
|
+
| `Badge` | Status indicator |
|
|
89
|
+
| `Spinner` | Loading indicator |
|
|
90
|
+
| `Skeleton` | Content placeholder |
|
|
91
|
+
| `ProgressIndicator` | Progress visualization |
|
|
92
|
+
|
|
93
|
+
### Navigation Components
|
|
94
|
+
|
|
95
|
+
| Component | Purpose |
|
|
96
|
+
| ------------- | ----------------------------------- |
|
|
97
|
+
| `Breadcrumbs` | Navigation path |
|
|
98
|
+
| `TabList` | Tab navigation |
|
|
99
|
+
| `Pagination` | Page navigation |
|
|
100
|
+
| `Sidebar` | Collapsible application sidebar nav |
|
|
101
|
+
| `Header` | Page header with logo and nav |
|
|
102
|
+
| `Footer` | Page footer with links and info |
|
|
103
|
+
|
|
104
|
+
### Overlay Components
|
|
105
|
+
|
|
106
|
+
| Component | Purpose |
|
|
107
|
+
| -------------- | ------------------- |
|
|
108
|
+
| `Modal` | Dialog overlay |
|
|
109
|
+
| `AlertDialog` | Confirmation dialog |
|
|
110
|
+
| `Tooltip` | Hover information |
|
|
111
|
+
| `DropdownMenu` | Action menu |
|
|
112
|
+
| `ContextMenu` | Right-click menu |
|
|
113
|
+
|
|
114
|
+
### Data Display Components
|
|
115
|
+
|
|
116
|
+
| Component | Purpose |
|
|
117
|
+
| ----------- | -------------------- |
|
|
118
|
+
| `Table` | Tabular data |
|
|
119
|
+
| `Accordion` | Collapsible sections |
|
|
120
|
+
| `BarChart` | Bar chart |
|
|
121
|
+
| `LineChart` | Line chart |
|
|
122
|
+
| `PieChart` | Pie chart |
|
|
123
|
+
|
|
124
|
+
## Component Usage Patterns
|
|
125
|
+
|
|
126
|
+
### Basic Import and Use
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { Button, Card, Heading, Text, Stack } from '@engrate/components'
|
|
130
|
+
|
|
131
|
+
function MyComponent() {
|
|
132
|
+
return (
|
|
133
|
+
<Card>
|
|
134
|
+
<Stack gap="md">
|
|
135
|
+
<Heading level="h2">Welcome</Heading>
|
|
136
|
+
<Text>This is a card with stacked content.</Text>
|
|
137
|
+
<Button variant="primary">Get Started</Button>
|
|
138
|
+
</Stack>
|
|
139
|
+
</Card>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Button Variants
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import { Button } from '@engrate/components'
|
|
148
|
+
|
|
149
|
+
// Primary (Sunflower yellow background)
|
|
150
|
+
<Button variant="primary">Primary Action</Button>
|
|
151
|
+
|
|
152
|
+
// Secondary (bordered, transparent)
|
|
153
|
+
<Button variant="secondary">Secondary</Button>
|
|
154
|
+
|
|
155
|
+
// Ghost (no background)
|
|
156
|
+
<Button variant="ghost">Ghost</Button>
|
|
157
|
+
|
|
158
|
+
// Sizes: sm, default, lg, icon
|
|
159
|
+
<Button size="lg">Large Button</Button>
|
|
160
|
+
|
|
161
|
+
// As child (for Next.js Link, etc.)
|
|
162
|
+
<Button asChild>
|
|
163
|
+
<a href="/page">Link Button</a>
|
|
164
|
+
</Button>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Form Layout
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
import { FormField, Input, Button, Stack } from '@engrate/components'
|
|
171
|
+
|
|
172
|
+
function LoginForm() {
|
|
173
|
+
return (
|
|
174
|
+
<form>
|
|
175
|
+
<Stack gap="lg">
|
|
176
|
+
<FormField label="Email" htmlFor="email">
|
|
177
|
+
<Input id="email" type="email" placeholder="you@example.com" />
|
|
178
|
+
</FormField>
|
|
179
|
+
<FormField label="Password" htmlFor="password">
|
|
180
|
+
<Input id="password" type="password" />
|
|
181
|
+
</FormField>
|
|
182
|
+
<Button type="submit" variant="primary">
|
|
183
|
+
Sign In
|
|
184
|
+
</Button>
|
|
185
|
+
</Stack>
|
|
186
|
+
</form>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Typography Hierarchy
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
import { Heading, Text, Eyebrow, Stack } from '@engrate/components'
|
|
195
|
+
;<Stack gap="md">
|
|
196
|
+
<Eyebrow>Category</Eyebrow>
|
|
197
|
+
<Heading level="hero">Hero Title</Heading>
|
|
198
|
+
<Heading level="h1">Page Title</Heading>
|
|
199
|
+
<Text variant="lead">Lead paragraph with larger text.</Text>
|
|
200
|
+
<Text variant="semi-lead">Semi lead paragraph.</Text>
|
|
201
|
+
<Text variant="body">Regular body text for content.</Text>
|
|
202
|
+
<Text variant="descriptive">Descriptive smaller text.</Text>
|
|
203
|
+
</Stack>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Layout with Grid
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { Grid, Card } from '@engrate/components'
|
|
210
|
+
;<Grid cols={3} gap="lg">
|
|
211
|
+
<Card>Column 1</Card>
|
|
212
|
+
<Card>Column 2</Card>
|
|
213
|
+
<Card>Column 3</Card>
|
|
214
|
+
</Grid>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Modal Dialog
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import {
|
|
221
|
+
Modal,
|
|
222
|
+
ModalTrigger,
|
|
223
|
+
ModalContent,
|
|
224
|
+
ModalHeader,
|
|
225
|
+
ModalTitle,
|
|
226
|
+
ModalDescription,
|
|
227
|
+
ModalFooter,
|
|
228
|
+
ModalClose,
|
|
229
|
+
Button,
|
|
230
|
+
Stack,
|
|
231
|
+
Text,
|
|
232
|
+
} from '@engrate/components'
|
|
233
|
+
|
|
234
|
+
function Example() {
|
|
235
|
+
return (
|
|
236
|
+
<Modal>
|
|
237
|
+
<ModalTrigger asChild>
|
|
238
|
+
<Button>Open Modal</Button>
|
|
239
|
+
</ModalTrigger>
|
|
240
|
+
<ModalContent>
|
|
241
|
+
<ModalHeader>
|
|
242
|
+
<ModalTitle>Confirm Action</ModalTitle>
|
|
243
|
+
<ModalDescription>This action cannot be undone.</ModalDescription>
|
|
244
|
+
</ModalHeader>
|
|
245
|
+
<Text>Are you sure you want to proceed?</Text>
|
|
246
|
+
<ModalFooter>
|
|
247
|
+
<ModalClose asChild>
|
|
248
|
+
<Button variant="secondary">Cancel</Button>
|
|
249
|
+
</ModalClose>
|
|
250
|
+
<Button variant="primary">Confirm</Button>
|
|
251
|
+
</ModalFooter>
|
|
252
|
+
</ModalContent>
|
|
253
|
+
</Modal>
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Sidebar Navigation
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
import {
|
|
262
|
+
Sidebar,
|
|
263
|
+
SidebarContent,
|
|
264
|
+
SidebarFooter,
|
|
265
|
+
SidebarGroup,
|
|
266
|
+
SidebarGroupLabel,
|
|
267
|
+
SidebarHeader,
|
|
268
|
+
SidebarItem,
|
|
269
|
+
SidebarSeparator,
|
|
270
|
+
SidebarTrigger,
|
|
271
|
+
EngrateLogo,
|
|
272
|
+
} from '@engrate/components'
|
|
273
|
+
import { Home, Settings, BarChart3, LogOut } from 'lucide-react'
|
|
274
|
+
|
|
275
|
+
function AppLayout() {
|
|
276
|
+
return (
|
|
277
|
+
<div style={{ display: 'flex', height: '100vh' }}>
|
|
278
|
+
<Sidebar aria-label="Main navigation">
|
|
279
|
+
<SidebarHeader>
|
|
280
|
+
<EngrateLogo size="sm" compact />
|
|
281
|
+
</SidebarHeader>
|
|
282
|
+
<SidebarContent>
|
|
283
|
+
<SidebarGroup>
|
|
284
|
+
<SidebarGroupLabel>Main</SidebarGroupLabel>
|
|
285
|
+
<SidebarItem icon={<Home className="h-4 w-4" />} active>
|
|
286
|
+
Dashboard
|
|
287
|
+
</SidebarItem>
|
|
288
|
+
<SidebarItem icon={<BarChart3 className="h-4 w-4" />}>
|
|
289
|
+
Analytics
|
|
290
|
+
</SidebarItem>
|
|
291
|
+
</SidebarGroup>
|
|
292
|
+
<SidebarSeparator />
|
|
293
|
+
<SidebarGroup>
|
|
294
|
+
<SidebarGroupLabel>Settings</SidebarGroupLabel>
|
|
295
|
+
<SidebarItem icon={<Settings className="h-4 w-4" />}>
|
|
296
|
+
Preferences
|
|
297
|
+
</SidebarItem>
|
|
298
|
+
</SidebarGroup>
|
|
299
|
+
</SidebarContent>
|
|
300
|
+
<SidebarFooter>
|
|
301
|
+
<SidebarItem icon={<LogOut className="h-4 w-4" />}>
|
|
302
|
+
Logout
|
|
303
|
+
</SidebarItem>
|
|
304
|
+
</SidebarFooter>
|
|
305
|
+
</Sidebar>
|
|
306
|
+
<main className="flex-1 p-6">{/* Main content */}</main>
|
|
307
|
+
</div>
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Header and Footer
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
import {
|
|
316
|
+
Header,
|
|
317
|
+
HeaderLogo,
|
|
318
|
+
HeaderNav,
|
|
319
|
+
HeaderActions,
|
|
320
|
+
Footer,
|
|
321
|
+
FooterContent,
|
|
322
|
+
FooterSection,
|
|
323
|
+
FooterHeading,
|
|
324
|
+
FooterLinks,
|
|
325
|
+
FooterBottom,
|
|
326
|
+
FooterCopyright,
|
|
327
|
+
EngrateLogo,
|
|
328
|
+
Button,
|
|
329
|
+
Link,
|
|
330
|
+
} from '@engrate/components'
|
|
331
|
+
|
|
332
|
+
function PageLayout() {
|
|
333
|
+
return (
|
|
334
|
+
<>
|
|
335
|
+
<Header sticky>
|
|
336
|
+
<HeaderLogo>
|
|
337
|
+
<EngrateLogo />
|
|
338
|
+
</HeaderLogo>
|
|
339
|
+
<HeaderNav>
|
|
340
|
+
<Link variant="nav" href="/about">
|
|
341
|
+
About
|
|
342
|
+
</Link>
|
|
343
|
+
<Link variant="nav" href="/services">
|
|
344
|
+
Services
|
|
345
|
+
</Link>
|
|
346
|
+
</HeaderNav>
|
|
347
|
+
<HeaderActions>
|
|
348
|
+
<Button variant="primary">Sign In</Button>
|
|
349
|
+
</HeaderActions>
|
|
350
|
+
</Header>
|
|
351
|
+
|
|
352
|
+
<main>{/* Page content */}</main>
|
|
353
|
+
|
|
354
|
+
<Footer>
|
|
355
|
+
<FooterContent>
|
|
356
|
+
<FooterSection>
|
|
357
|
+
<FooterHeading>Company</FooterHeading>
|
|
358
|
+
<FooterLinks>
|
|
359
|
+
<Link href="/about">About</Link>
|
|
360
|
+
<Link href="/careers">Careers</Link>
|
|
361
|
+
</FooterLinks>
|
|
362
|
+
</FooterSection>
|
|
363
|
+
</FooterContent>
|
|
364
|
+
<FooterBottom>
|
|
365
|
+
<FooterCopyright>© 2026 Engrate</FooterCopyright>
|
|
366
|
+
</FooterBottom>
|
|
367
|
+
</Footer>
|
|
368
|
+
</>
|
|
369
|
+
)
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Design Tokens
|
|
374
|
+
|
|
375
|
+
The library exposes CSS custom properties for use in custom components.
|
|
376
|
+
|
|
377
|
+
### Colors
|
|
378
|
+
|
|
379
|
+
| Token | Usage |
|
|
380
|
+
| ------------------------------- | ------------------------ |
|
|
381
|
+
| `--color-sunflower` | Primary brand color |
|
|
382
|
+
| `--color-sunflower-hover` | Sunflower hover state |
|
|
383
|
+
| `--color-primary` | Primary text color |
|
|
384
|
+
| `--color-secondary` | Secondary text color |
|
|
385
|
+
| `--color-tertiary` | Tertiary text color |
|
|
386
|
+
| `--color-main` (background) | Main page background |
|
|
387
|
+
| `--color-alt` (background) | Alternative background |
|
|
388
|
+
| `--color-card` (background) | Card background |
|
|
389
|
+
| `--color-contrast` (background) | High contrast background |
|
|
390
|
+
| `--color-border` | Border color |
|
|
391
|
+
| `--color-error` | Error state color |
|
|
392
|
+
|
|
393
|
+
### Typography
|
|
394
|
+
|
|
395
|
+
| Token | Usage |
|
|
396
|
+
| ---------------- | ---------------------------- |
|
|
397
|
+
| `--font-display` | Libre Baskerville (headings) |
|
|
398
|
+
| `--font-sans` | Work Sans (body text) |
|
|
399
|
+
| `--font-mono` | IBM Plex Mono (code) |
|
|
400
|
+
|
|
401
|
+
### Using Tokens in Custom Components
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
// With Tailwind CSS v4 (tokens are auto-detected)
|
|
405
|
+
function CustomCard({ children }) {
|
|
406
|
+
return (
|
|
407
|
+
<div className="bg-card border-border text-primary rounded-lg border p-4">
|
|
408
|
+
{children}
|
|
409
|
+
</div>
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Using CSS custom properties directly
|
|
414
|
+
function CustomBanner() {
|
|
415
|
+
return (
|
|
416
|
+
<div
|
|
417
|
+
style={{
|
|
418
|
+
backgroundColor: 'var(--color-sunflower)',
|
|
419
|
+
color: 'var(--color-primary)',
|
|
420
|
+
}}
|
|
421
|
+
>
|
|
422
|
+
Custom styled banner
|
|
423
|
+
</div>
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Common Patterns
|
|
429
|
+
|
|
430
|
+
### Responsive Layouts
|
|
431
|
+
|
|
432
|
+
```tsx
|
|
433
|
+
<Grid cols={{ base: 1, md: 2, lg: 3 }} gap="lg">
|
|
434
|
+
{items.map((item) => (
|
|
435
|
+
<Card key={item.id}>{item.content}</Card>
|
|
436
|
+
))}
|
|
437
|
+
</Grid>
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Loading States
|
|
441
|
+
|
|
442
|
+
```tsx
|
|
443
|
+
import { Skeleton, Spinner, Stack } from '@engrate/components'
|
|
444
|
+
|
|
445
|
+
// Skeleton for content placeholders
|
|
446
|
+
<Stack gap="sm">
|
|
447
|
+
<Skeleton width="60%" height="1.5rem" />
|
|
448
|
+
<Skeleton width="100%" height="1rem" />
|
|
449
|
+
<Skeleton width="80%" height="1rem" />
|
|
450
|
+
</Stack>
|
|
451
|
+
|
|
452
|
+
// Spinner for loading indicators
|
|
453
|
+
<Spinner size="lg" />
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Toast Notifications
|
|
457
|
+
|
|
458
|
+
```tsx
|
|
459
|
+
import {
|
|
460
|
+
Toast,
|
|
461
|
+
ToastProvider,
|
|
462
|
+
ToastViewport,
|
|
463
|
+
ToastTitle,
|
|
464
|
+
ToastDescription,
|
|
465
|
+
ToastClose,
|
|
466
|
+
Button,
|
|
467
|
+
} from '@engrate/components'
|
|
468
|
+
import { useState } from 'react'
|
|
469
|
+
|
|
470
|
+
function Example() {
|
|
471
|
+
const [open, setOpen] = useState(false)
|
|
472
|
+
|
|
473
|
+
return (
|
|
474
|
+
<ToastProvider>
|
|
475
|
+
<Button
|
|
476
|
+
onClick={() => {
|
|
477
|
+
setOpen(true)
|
|
478
|
+
setTimeout(() => setOpen(false), 3000)
|
|
479
|
+
}}
|
|
480
|
+
>
|
|
481
|
+
Save
|
|
482
|
+
</Button>
|
|
483
|
+
<Toast open={open} onOpenChange={setOpen} variant="success">
|
|
484
|
+
<div className="grid gap-1">
|
|
485
|
+
<ToastTitle>Success</ToastTitle>
|
|
486
|
+
<ToastDescription>Your changes have been saved.</ToastDescription>
|
|
487
|
+
</div>
|
|
488
|
+
<ToastClose />
|
|
489
|
+
</Toast>
|
|
490
|
+
<ToastViewport />
|
|
491
|
+
</ToastProvider>
|
|
492
|
+
)
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
## Accessibility
|
|
497
|
+
|
|
498
|
+
All components are built with accessibility in mind:
|
|
499
|
+
|
|
500
|
+
- Proper ARIA attributes
|
|
501
|
+
- Keyboard navigation support
|
|
502
|
+
- Focus management
|
|
503
|
+
- Screen reader friendly
|
|
504
|
+
|
|
505
|
+
## TypeScript Support
|
|
506
|
+
|
|
507
|
+
All components export their prop types:
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
import { Button, type ButtonProps } from '@engrate/components'
|
|
511
|
+
|
|
512
|
+
// Use types for custom wrappers
|
|
513
|
+
interface MyButtonProps extends ButtonProps {
|
|
514
|
+
loading?: boolean
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
## Layout Guidelines
|
|
519
|
+
|
|
520
|
+
Follow these layout principles when building UIs with Engrate components:
|
|
521
|
+
|
|
522
|
+
### Text Alignment & Width
|
|
523
|
+
|
|
524
|
+
- **Always left-align text** — creates clarity and readability
|
|
525
|
+
- **Body text max 65 characters wide** — use `max-width: 65ch` or equivalent
|
|
526
|
+
- Heading should be **at least twice as large** as body text
|
|
527
|
+
|
|
528
|
+
### Spacing & Grid
|
|
529
|
+
|
|
530
|
+
- **Grid spacing should be 50% tighter than typical defaults** — creates cohesive layouts
|
|
531
|
+
- **Even margins** — equal margins to top and left side creates natural squares
|
|
532
|
+
- **Card headline-to-body gap** — use 100% of body text line height for breathing room
|
|
533
|
+
|
|
534
|
+
### Content Width
|
|
535
|
+
|
|
536
|
+
- Tables, charts, and text blocks should be ~60-70% of container width (not full width)
|
|
537
|
+
- Keep content blocks relatively **square in proportion** — avoid ultra-wide, thin layouts
|
|
538
|
+
- Exception: photographs may span full width as backgrounds or hero images
|
|
539
|
+
|
|
540
|
+
### Backgrounds
|
|
541
|
+
|
|
542
|
+
- **Never use pure white (#FFFFFF)** for backgrounds
|
|
543
|
+
- Use light gray backgrounds: `bg-main` (#FAFAFA), `bg-alt` (#F5F5F5), `bg-card` (#F9F9F9)
|
|
544
|
+
- Light yellow backgrounds (Vanilla, Eggshell) can highlight sections
|
|
545
|
+
|
|
546
|
+
## Spacing
|
|
547
|
+
|
|
548
|
+
The component library uses a consistent spacing scale based on Tailwind's default values.
|
|
549
|
+
|
|
550
|
+
### Gap Values
|
|
551
|
+
|
|
552
|
+
Use `Stack` and `Grid` components with the `gap` prop:
|
|
553
|
+
|
|
554
|
+
| Gap | Value | Tailwind | Use Case |
|
|
555
|
+
| ----- | ------- | -------- | ---------------------------------- |
|
|
556
|
+
| `xs` | 0.25rem | `gap-1` | Tight spacing (icon + label) |
|
|
557
|
+
| `sm` | 0.5rem | `gap-2` | Compact layouts |
|
|
558
|
+
| `md` | 1rem | `gap-4` | Default spacing (cards, form rows) |
|
|
559
|
+
| `lg` | 1.5rem | `gap-6` | Section spacing |
|
|
560
|
+
| `xl` | 2rem | `gap-8` | Major sections |
|
|
561
|
+
| `2xl` | 3rem | `gap-12` | Page sections |
|
|
562
|
+
|
|
563
|
+
### Spacing Guidelines
|
|
564
|
+
|
|
565
|
+
```tsx
|
|
566
|
+
// Form fields — use md gap
|
|
567
|
+
<Stack gap="md">
|
|
568
|
+
<FormField label="Name"><Input /></FormField>
|
|
569
|
+
<FormField label="Email"><Input /></FormField>
|
|
570
|
+
</Stack>
|
|
571
|
+
|
|
572
|
+
// Button groups — use sm gap
|
|
573
|
+
<Stack direction="horizontal" gap="sm">
|
|
574
|
+
<Button variant="secondary">Cancel</Button>
|
|
575
|
+
<Button variant="primary">Save</Button>
|
|
576
|
+
</Stack>
|
|
577
|
+
|
|
578
|
+
// Page sections — use xl or 2xl gap
|
|
579
|
+
<Stack gap="xl">
|
|
580
|
+
<section>Hero content</section>
|
|
581
|
+
<section>Features</section>
|
|
582
|
+
</Stack>
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### Brand Spacing Rules
|
|
586
|
+
|
|
587
|
+
- **Grid spacing 50% tighter than defaults** — prefer `sm` over `md`, `md` over `lg`
|
|
588
|
+
- **Card headline-to-body gap** — use 100% of body text line height
|
|
589
|
+
- **Even margins** — equal top and left margins create natural squares
|
|
590
|
+
|
|
591
|
+
## Design Rules
|
|
592
|
+
|
|
593
|
+
Critical rules to maintain brand consistency:
|
|
594
|
+
|
|
595
|
+
### Color Usage
|
|
596
|
+
|
|
597
|
+
| Rule | Description |
|
|
598
|
+
| ------------------------ | ------------------------------------------------------------------------------ |
|
|
599
|
+
| **10/90 Rule** | 10% color, 90% grayscale — colors look best when used sparingly |
|
|
600
|
+
| **No colored text** | All text must be grayscale only — never use Sunflower or other colors for text |
|
|
601
|
+
| **Sunflower is primary** | When only one color can be used, use Sunflower (#FFBE26) |
|
|
602
|
+
|
|
603
|
+
### Typography
|
|
604
|
+
|
|
605
|
+
| Rule | Description |
|
|
606
|
+
| ----------------------- | ------------------------------------------------------------- |
|
|
607
|
+
| **-5% letter spacing** | All text above 10pt uses -5% tracking (built into components) |
|
|
608
|
+
| **Libre Baskerville** | Only for hero headings ≥60pt |
|
|
609
|
+
| **Work Sans Regular** | Everything else — no Bold, Medium, or Light weights allowed |
|
|
610
|
+
| **Grayscale text only** | Prioritize black (#1A1A1A), use gray only for hierarchy |
|
|
611
|
+
|
|
612
|
+
### Design Checklist
|
|
613
|
+
|
|
614
|
+
Before shipping, verify:
|
|
615
|
+
|
|
616
|
+
- [ ] Following 10/90 color vs grayscale ratio
|
|
617
|
+
- [ ] All text is grayscale (no colored text)
|
|
618
|
+
- [ ] Text is left-aligned
|
|
619
|
+
- [ ] Body text max 65 characters wide
|
|
620
|
+
- [ ] Using light gray backgrounds, not pure white
|
|
621
|
+
|
|
622
|
+
## Related Resources
|
|
623
|
+
|
|
624
|
+
- **Storybook Documentation**: Interactive component examples at https://engrate.github.io/eg-components
|
|
625
|
+
- **Design Guidelines**: See `.github/skills/engrate-designer/SKILL.md` for brand and design tokens
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@engrate/components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Engrate Component Library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs.js",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
},
|
|
21
21
|
"./styles.css": "./dist/styles.css",
|
|
22
22
|
"./fonts/*": "./dist/fonts/*",
|
|
23
|
-
"./skills/engrate-
|
|
23
|
+
"./skills/engrate-component-user.md": "./dist/skills/engrate-component-user.md"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"dev": "storybook dev -p 6006",
|
|
27
|
-
"build": "tsc -p tsconfig.app.json && vite build && mkdir -p dist/skills && cp
|
|
27
|
+
"build": "tsc -p tsconfig.app.json && vite build && mkdir -p dist/skills && cp SKILL.md dist/skills/engrate-component-user.md",
|
|
28
28
|
"test": "vitest run",
|
|
29
29
|
"test:watch": "vitest",
|
|
30
30
|
"test:coverage": "vitest run --coverage",
|