@loykin/designkit 0.0.1-dev.1 → 0.0.1-dev.3
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 +230 -97
- package/dist/index.cjs +606 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +163 -3
- package/dist/index.d.ts +163 -3
- package/dist/index.js +604 -18
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -77
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
React page template library. Provides ready-to-use page layouts for admin and dashboard applications.
|
|
4
4
|
|
|
5
|
+
For AI-assisted implementation in consuming applications, see the
|
|
6
|
+
[DesignKit Consumer Agent Guide](docs/consumer-guide.md).
|
|
7
|
+
|
|
5
8
|
## Installation
|
|
6
9
|
|
|
7
10
|
```bash
|
|
8
|
-
npm install @loykin/designkit
|
|
11
|
+
npm install @loykin/designkit
|
|
9
12
|
```
|
|
10
13
|
|
|
11
|
-
Requires React 19 and Tailwind CSS v4. UI components are based on [shadcn/ui](https://ui.shadcn.com) — if your app has shadcn set up, theming integrates automatically via shared CSS variables (`--primary`, `--background`, `--radius`, etc.).
|
|
14
|
+
Requires React 19 and Tailwind CSS v4. UI components are based on [shadcn/ui](https://ui.shadcn.com) — if your app has shadcn set up, theming integrates automatically via shared CSS variables (`--primary`, `--background`, `--radius`, etc.).
|
|
12
15
|
|
|
13
16
|
Import the styles in your global CSS:
|
|
14
17
|
|
|
@@ -17,29 +20,24 @@ Import the styles in your global CSS:
|
|
|
17
20
|
@import "@loykin/designkit/styles";
|
|
18
21
|
```
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
The styles file includes pre-built Tailwind utility classes — no `@source` configuration required. You can also import the stylesheet from your app entry, as shown below.
|
|
21
24
|
|
|
22
25
|
## Quick Start
|
|
23
26
|
|
|
24
27
|
```tsx
|
|
25
|
-
import { DataBodyTemplate,
|
|
28
|
+
import { DataBodyTemplate, PageTopBar, Button } from '@loykin/designkit'
|
|
26
29
|
import '@loykin/designkit/styles'
|
|
27
30
|
|
|
28
|
-
type User = { id: string; name: string; email: string }
|
|
29
|
-
|
|
30
|
-
const columns: DataGridColumnDef<User>[] = [
|
|
31
|
-
{ id: 'name', accessorKey: 'name', header: 'Name' },
|
|
32
|
-
{ id: 'email', accessorKey: 'email', header: 'Email' },
|
|
33
|
-
]
|
|
34
|
-
|
|
35
31
|
export function UsersPage() {
|
|
36
32
|
return (
|
|
37
33
|
<DataBodyTemplate
|
|
38
34
|
topBar={<PageTopBar left="Admin / Users" />}
|
|
39
35
|
title="Users"
|
|
36
|
+
description="Manage your team members."
|
|
37
|
+
actions={<Button>Add User</Button>}
|
|
40
38
|
>
|
|
41
39
|
<DataBodyTemplate.Body>
|
|
42
|
-
|
|
40
|
+
{/* your content */}
|
|
43
41
|
</DataBodyTemplate.Body>
|
|
44
42
|
</DataBodyTemplate>
|
|
45
43
|
)
|
|
@@ -52,7 +50,7 @@ export function UsersPage() {
|
|
|
52
50
|
|
|
53
51
|
### DataBodyTemplate
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
General-purpose page shell. Accepts `.Body`, `.Tab`, and `.Section` child slots which determine the layout mode automatically.
|
|
56
54
|
|
|
57
55
|
```tsx
|
|
58
56
|
<DataBodyTemplate
|
|
@@ -70,33 +68,33 @@ The general-purpose page shell. Accepts three kinds of child slots — `.Body`,
|
|
|
70
68
|
| `topBar` | `ReactNode` | Top breadcrumb bar. Pass `<PageTopBar left="..." />` or omit. |
|
|
71
69
|
| `title` | `ReactNode` | Page title |
|
|
72
70
|
| `description` | `ReactNode` | Subtitle below the title |
|
|
73
|
-
| `actions` | `ReactNode` | Page-level actions (Add, Export, etc.) next to the title
|
|
71
|
+
| `actions` | `ReactNode` | Page-level actions (Add, Export, etc.) next to the title |
|
|
74
72
|
| `toolbarLeft` / `toolbarRight` | `ReactNode` | Toolbar slots above the content area |
|
|
75
73
|
| `theme` | `CSSProperties` | Inline CSS variable overrides |
|
|
76
74
|
| `className` | `string` | Class applied to the page root |
|
|
77
75
|
|
|
78
76
|
#### DataBodyTemplate.Body
|
|
79
77
|
|
|
80
|
-
Single-pane content.
|
|
78
|
+
Single-pane content. Use for full-height layouts.
|
|
81
79
|
|
|
82
80
|
```tsx
|
|
83
81
|
<DataBodyTemplate title="Users">
|
|
84
82
|
<DataBodyTemplate.Body>
|
|
85
|
-
|
|
83
|
+
{/* your content */}
|
|
86
84
|
</DataBodyTemplate.Body>
|
|
87
85
|
</DataBodyTemplate>
|
|
88
86
|
```
|
|
89
87
|
|
|
90
|
-
> Passing children directly without
|
|
88
|
+
> Passing children directly without a slot wrapper also renders as a body, but `.Body` makes the intent explicit.
|
|
91
89
|
|
|
92
90
|
#### DataBodyTemplate.Tab
|
|
93
91
|
|
|
94
|
-
Creates a tabbed page layout.
|
|
92
|
+
Creates a tabbed page layout.
|
|
95
93
|
|
|
96
94
|
```tsx
|
|
97
95
|
<DataBodyTemplate title="Users">
|
|
98
96
|
<DataBodyTemplate.Tab id="list" label="List" count={42}>
|
|
99
|
-
|
|
97
|
+
{/* list content */}
|
|
100
98
|
</DataBodyTemplate.Tab>
|
|
101
99
|
<DataBodyTemplate.Tab id="settings" label="Settings">
|
|
102
100
|
<SettingsForm />
|
|
@@ -106,7 +104,7 @@ Creates a tabbed page layout. Add multiple `.Tab` children to enable the tab bar
|
|
|
106
104
|
|
|
107
105
|
#### DataBodyTemplate.Section
|
|
108
106
|
|
|
109
|
-
Settings-style layout with left navigation and right content panel.
|
|
107
|
+
Settings-style layout with left navigation and right content panel.
|
|
110
108
|
|
|
111
109
|
```tsx
|
|
112
110
|
<DataBodyTemplate title="Settings">
|
|
@@ -129,12 +127,22 @@ Settings-style layout with left navigation and right content panel. Add multiple
|
|
|
129
127
|
|
|
130
128
|
Groups content within a tab or section. The `layout` prop controls the visual structure.
|
|
131
129
|
|
|
132
|
-
| layout | Use case |
|
|
130
|
+
| layout | Use case |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `horizontal` | Label on left, input on right (settings form) |
|
|
133
|
+
| `stacked` | Label above, input below |
|
|
134
|
+
| `inline` | Table-style rows (detail view) |
|
|
135
|
+
| `split` | Left list + right detail |
|
|
136
|
+
|
|
137
|
+
| Prop | Type | Description |
|
|
133
138
|
|---|---|---|
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
139
|
+
| `layout` | `GroupLayout` | Visual structure — see table above |
|
|
140
|
+
| `variant` | `'card' \| 'plain' \| 'bordered'` | Wrapper style (defaults per layout) |
|
|
141
|
+
| `title` | `ReactNode` | Group heading |
|
|
142
|
+
| `description` | `ReactNode` | Subtitle below the heading |
|
|
143
|
+
| `actions` | `ReactNode` | Action slot next to the heading |
|
|
144
|
+
| `danger` | `boolean` | Renders title in destructive color |
|
|
145
|
+
| `className` | `string` | Class applied to the group root element |
|
|
138
146
|
|
|
139
147
|
```tsx
|
|
140
148
|
<DataBodyTemplate.Tab id="settings" label="Settings">
|
|
@@ -151,7 +159,7 @@ Groups content within a tab or section. The `layout` prop controls the visual st
|
|
|
151
159
|
|
|
152
160
|
#### DataBodyTemplate.Field
|
|
153
161
|
|
|
154
|
-
Read-only key-value display.
|
|
162
|
+
Read-only key-value display.
|
|
155
163
|
|
|
156
164
|
```tsx
|
|
157
165
|
<DataBodyTemplate.Group layout="inline" title="Identity">
|
|
@@ -162,7 +170,7 @@ Read-only key-value display. Use with `Group layout="inline"` for detail pages.
|
|
|
162
170
|
|
|
163
171
|
#### DataBodyTemplate.Summary
|
|
164
172
|
|
|
165
|
-
|
|
173
|
+
Pinned summary area below the header, above tabs.
|
|
166
174
|
|
|
167
175
|
```tsx
|
|
168
176
|
<DataBodyTemplate title="Overview">
|
|
@@ -175,49 +183,170 @@ A pinned summary area below the header, above tabs.
|
|
|
175
183
|
|
|
176
184
|
---
|
|
177
185
|
|
|
178
|
-
###
|
|
186
|
+
### DashboardBodyTemplate
|
|
179
187
|
|
|
180
|
-
|
|
188
|
+
Dashboard page shell. Provides the chrome — top bar, variable bar, panel grid area — while the app owns panel content and the data engine.
|
|
181
189
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
Requires [`@loykin/dashboardkit`](https://github.com/loykin/dashboardkit) 0.0.6 or newer for the grid and variable system:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npm install @loykin/dashboardkit@^0.0.6 react-grid-layout
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Also import DashboardKit's grid CSS in your app:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
import '@loykin/dashboardkit/styles'
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
For rounded design systems, tune DashboardKit's resize handle variables so the
|
|
203
|
+
handle stays inside the clipped panel corner:
|
|
204
|
+
|
|
205
|
+
```css
|
|
206
|
+
.layout-dashboard .react-grid-item:not(.react-grid-placeholder) {
|
|
207
|
+
--dk-resize-handle-size: clamp(20px, calc(var(--radius) * 1.6), 40px);
|
|
208
|
+
--dk-resize-handle-inset: clamp(4px, calc(var(--radius) * 0.45), 16px);
|
|
209
|
+
--dk-resize-handle-mark-size: clamp(6px, calc(var(--radius) * 0.55), 12px);
|
|
210
|
+
--dk-resize-handle-color: rgba(0, 0, 0, 0.35);
|
|
211
|
+
--dk-resize-handle-mark-radius: min(var(--radius), var(--dk-resize-handle-mark-size));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.dark .layout-dashboard .react-grid-item:not(.react-grid-placeholder) {
|
|
215
|
+
--dk-resize-handle-color: rgba(255, 255, 255, 0.4);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
189
218
|
|
|
190
219
|
```tsx
|
|
191
|
-
import
|
|
220
|
+
import React, { useState, useMemo } from 'react'
|
|
221
|
+
import { DashboardBodyTemplate, DashboardPanel, PageTopBar } from '@loykin/designkit'
|
|
222
|
+
import { createDashboardEngine, definePanel } from '@loykin/dashboardkit'
|
|
223
|
+
import { useLoadDashboard, useVariable, DashboardGrid } from '@loykin/dashboardkit/react'
|
|
224
|
+
import type { PanelViewerProps } from '@loykin/dashboardkit'
|
|
225
|
+
|
|
226
|
+
// Register panel types once at module level
|
|
227
|
+
const engine = createDashboardEngine()
|
|
228
|
+
engine.registerPanel(definePanel({
|
|
229
|
+
id: 'stat',
|
|
230
|
+
name: 'Stat',
|
|
231
|
+
optionsSchema: {},
|
|
232
|
+
viewer({ data, loading }: PanelViewerProps<unknown, unknown>) {
|
|
233
|
+
if (loading) return null
|
|
234
|
+
return <div className="text-2xl font-bold">{String(data ?? '—')}</div>
|
|
235
|
+
},
|
|
236
|
+
}))
|
|
237
|
+
|
|
238
|
+
export function MyDashboard() {
|
|
239
|
+
useLoadDashboard(engine, config)
|
|
240
|
+
const envVar = useVariable(engine, 'env')
|
|
241
|
+
const variables = useMemo(() => ({ env: (envVar.value as string) ?? 'production' }), [envVar.value])
|
|
242
|
+
const [editable, setEditable] = useState(false)
|
|
192
243
|
|
|
193
|
-
|
|
244
|
+
return (
|
|
245
|
+
<DashboardBodyTemplate
|
|
246
|
+
topBar={<PageTopBar left="My Dashboard" right={/* controls */} />}
|
|
247
|
+
variableBar={/* <VariableSelect> components */}
|
|
248
|
+
>
|
|
249
|
+
<DashboardGrid engine={engine} editable={editable}>
|
|
250
|
+
{({ panelType, config, data, rawData, loading, error, ref }) => {
|
|
251
|
+
const Viewer = engine.getPanelPlugin(panelType)?.viewer as React.FC<PanelViewerProps<unknown, unknown>> | undefined
|
|
252
|
+
return (
|
|
253
|
+
<DashboardPanel
|
|
254
|
+
ref={ref}
|
|
255
|
+
title={config.title}
|
|
256
|
+
loading={loading}
|
|
257
|
+
error={error ?? undefined}
|
|
258
|
+
editable={editable}
|
|
259
|
+
style={{ height: '100%' }}
|
|
260
|
+
>
|
|
261
|
+
{Viewer && (
|
|
262
|
+
<Viewer
|
|
263
|
+
panel={config} options={config.options}
|
|
264
|
+
data={data} rawData={rawData}
|
|
265
|
+
width={0} height={0}
|
|
266
|
+
loading={loading} error={error}
|
|
267
|
+
variables={variables}
|
|
268
|
+
/>
|
|
269
|
+
)}
|
|
270
|
+
</DashboardPanel>
|
|
271
|
+
)
|
|
272
|
+
}}
|
|
273
|
+
</DashboardGrid>
|
|
274
|
+
</DashboardBodyTemplate>
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
```
|
|
194
278
|
|
|
195
|
-
|
|
196
|
-
{ id: 'name', accessorKey: 'name', header: 'Name' },
|
|
197
|
-
{ id: 'email', accessorKey: 'email', header: 'Email' },
|
|
198
|
-
]
|
|
279
|
+
**DashboardBodyTemplate props:**
|
|
199
280
|
|
|
200
|
-
|
|
281
|
+
| Prop | Type | Description |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| `topBar` | `ReactNode` | Top bar — breadcrumb, edit/refresh controls |
|
|
284
|
+
| `variableBar` | `ReactNode` | Variable dropdown strip between top bar and panels |
|
|
285
|
+
| `title` | `ReactNode` | Dashboard title (omit if topBar covers it) |
|
|
286
|
+
| `description` | `ReactNode` | Subtitle |
|
|
287
|
+
| `toolbar` | `ReactNode` | Toolbar slot next to the title |
|
|
288
|
+
| `theme` | `CSSProperties` | Inline CSS variable overrides |
|
|
289
|
+
| `className` | `string` | Class applied to the page root |
|
|
290
|
+
| `contentClassName` | `string` | Class applied to the panel grid area |
|
|
291
|
+
|
|
292
|
+
**DashboardPanel props:**
|
|
293
|
+
|
|
294
|
+
Panel card component. Wrap your panel viewer in `DashboardPanel` for consistent chrome across all panels.
|
|
295
|
+
|
|
296
|
+
| Prop | Type | Description |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| `title` | `string` | Panel title |
|
|
299
|
+
| `description` | `string` | Panel subtitle |
|
|
300
|
+
| `loading` | `boolean` | Shows loading spinner overlay |
|
|
301
|
+
| `error` | `string` | Shows error state, hides children |
|
|
302
|
+
| `editable` | `boolean` | Shows drag handle and edit ring |
|
|
303
|
+
| `headerRight` | `ReactNode` | Action slot in panel header — hidden until hover |
|
|
304
|
+
| `transparent` | `boolean` | Removes card border and background |
|
|
305
|
+
| `ref` | forwarded | Attach `DashboardGrid`'s `ref` for viewport virtualization |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### WorkbenchBodyTemplate
|
|
310
|
+
|
|
311
|
+
Resizable editor/workbench shell for products like panel editors, SQL editors, log explorers, and data workspaces. The template owns the pane chrome and resize handles; the app owns editor, preview, inspector, schema, and result content.
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import { WorkbenchBodyTemplate, PageTopBar, Button } from '@loykin/designkit'
|
|
315
|
+
|
|
316
|
+
export function SqlEditorPage() {
|
|
201
317
|
return (
|
|
202
|
-
<
|
|
203
|
-
<
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
</DataBodyTemplate>
|
|
318
|
+
<WorkbenchBodyTemplate
|
|
319
|
+
topBar={<PageTopBar left="Data / Query editor" />}
|
|
320
|
+
title="SQL editor"
|
|
321
|
+
headerRight={<Button variant="outline" size="sm">Run</Button>}
|
|
322
|
+
leftPane={<SchemaBrowser />}
|
|
323
|
+
mainPane={<SqlEditor />}
|
|
324
|
+
bottomPane={<ResultsGrid />}
|
|
325
|
+
resizable
|
|
326
|
+
/>
|
|
212
327
|
)
|
|
213
328
|
}
|
|
214
329
|
```
|
|
215
330
|
|
|
331
|
+
**WorkbenchBodyTemplate props:**
|
|
332
|
+
|
|
333
|
+
| Prop | Type | Description |
|
|
334
|
+
|---|---|---|
|
|
335
|
+
| `topBar` | `ReactNode` | Top bar above the workbench |
|
|
336
|
+
| `title` / `description` | `ReactNode` | Header copy above the panes |
|
|
337
|
+
| `headerRight` / `actions` | `ReactNode` | Header action slots |
|
|
338
|
+
| `leftPane` / `rightPane` | `ReactNode` | Optional side panes |
|
|
339
|
+
| `mainPane` | `ReactNode` | Primary editor or preview area |
|
|
340
|
+
| `bottomPane` | `ReactNode` | Optional result, query, or logs pane |
|
|
341
|
+
| `resizable` | `boolean` | Enables pane drag handles |
|
|
342
|
+
| `leftPaneCollapsed` / `rightPaneCollapsed` / `bottomPaneCollapsed` | `boolean` | Hides optional panes while preserving the template layout model |
|
|
343
|
+
| `leftPaneWidth` / `rightPaneWidth` / `bottomPaneHeight` | `number` | Initial pane sizes in pixels |
|
|
344
|
+
|
|
216
345
|
---
|
|
217
346
|
|
|
218
347
|
### FormWizardBodyTemplate
|
|
219
348
|
|
|
220
|
-
Multi-step input wizard.
|
|
349
|
+
Multi-step input wizard. Wraps each step's `content` in a `<form>` element automatically.
|
|
221
350
|
|
|
222
351
|
```tsx
|
|
223
352
|
import { useState } from 'react'
|
|
@@ -244,7 +373,7 @@ export function OnboardingPage() {
|
|
|
244
373
|
}
|
|
245
374
|
```
|
|
246
375
|
|
|
247
|
-
For per-step validation with `react-hook-form
|
|
376
|
+
For per-step validation with `react-hook-form`:
|
|
248
377
|
|
|
249
378
|
```tsx
|
|
250
379
|
onNext={async () => {
|
|
@@ -253,13 +382,13 @@ onNext={async () => {
|
|
|
253
382
|
}}
|
|
254
383
|
```
|
|
255
384
|
|
|
256
|
-
The `variant` prop switches between `'plain'` (default) and `'card'
|
|
385
|
+
The `variant` prop switches between `'plain'` (default) and `'card'`.
|
|
257
386
|
|
|
258
387
|
---
|
|
259
388
|
|
|
260
389
|
### LoginBodyTemplate
|
|
261
390
|
|
|
262
|
-
Authentication page shell.
|
|
391
|
+
Authentication page shell.
|
|
263
392
|
|
|
264
393
|
```tsx
|
|
265
394
|
import { LoginBodyTemplate } from '@loykin/designkit'
|
|
@@ -286,39 +415,46 @@ export function SignInPage() {
|
|
|
286
415
|
| Prop | Type | Default | Description |
|
|
287
416
|
|---|---|---|---|
|
|
288
417
|
| `layout` | `'centered' \| 'split'` | `'centered'` | Centered card or split-panel with brand side |
|
|
289
|
-
| `card` | `'card' \| 'plain'` | `'plain'` | Wrap
|
|
290
|
-
| `cardWidth` | `'sm' \| 'md' \| 'lg'` | `'md'` |
|
|
418
|
+
| `card` | `'card' \| 'plain'` | `'plain'` | Wrap form content in a card border |
|
|
419
|
+
| `cardWidth` | `'sm' \| 'md' \| 'lg'` | `'md'` | Form card width |
|
|
291
420
|
| `bg` | `'default' \| 'subtle' \| 'none'` | `'default'` | Background style |
|
|
292
|
-
| `side` | `'left' \| 'right'` | `'left'` |
|
|
421
|
+
| `side` | `'left' \| 'right'` | `'left'` | Brand panel side (split layout only) |
|
|
293
422
|
| `brand` | `ReactNode` | built-in | Custom brand/logo panel content |
|
|
294
423
|
|
|
295
424
|
---
|
|
296
425
|
|
|
297
426
|
## UI Components
|
|
298
427
|
|
|
299
|
-
Base components for use within page templates.
|
|
300
|
-
|
|
301
428
|
```tsx
|
|
302
429
|
import {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
430
|
+
Avatar, AvatarFallback, AvatarImage,
|
|
431
|
+
Badge,
|
|
432
|
+
Button,
|
|
433
|
+
Card, CardContent, CardHeader, CardTitle,
|
|
434
|
+
Checkbox,
|
|
435
|
+
DropdownMenu,
|
|
306
436
|
EmptyState,
|
|
307
|
-
|
|
437
|
+
Input,
|
|
438
|
+
Label,
|
|
439
|
+
NavigationMenu,
|
|
440
|
+
Popover,
|
|
441
|
+
ScrollArea,
|
|
442
|
+
Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
|
|
443
|
+
Separator,
|
|
308
444
|
Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger,
|
|
445
|
+
Sidebar,
|
|
446
|
+
Skeleton,
|
|
447
|
+
Slider,
|
|
448
|
+
Switch,
|
|
449
|
+
Table,
|
|
450
|
+
Tabs, TabsList, TabsTrigger, TabsContent,
|
|
309
451
|
Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,
|
|
310
|
-
Avatar, AvatarFallback, AvatarImage,
|
|
311
|
-
Separator, Skeleton,
|
|
312
|
-
Breadcrumb, DropdownMenu, NavigationMenu,
|
|
313
|
-
Popover, ScrollArea, Sidebar, Table,
|
|
314
452
|
PageTopBar,
|
|
315
453
|
} from '@loykin/designkit'
|
|
316
454
|
```
|
|
317
455
|
|
|
318
456
|
### EmptyState
|
|
319
457
|
|
|
320
|
-
Displays empty data, no search results, or error states.
|
|
321
|
-
|
|
322
458
|
```tsx
|
|
323
459
|
import { EmptyState } from '@loykin/designkit'
|
|
324
460
|
import { Users } from 'lucide-react'
|
|
@@ -335,13 +471,7 @@ import { Users } from 'lucide-react'
|
|
|
335
471
|
|
|
336
472
|
## Theming
|
|
337
473
|
|
|
338
|
-
Designkit maps shadcn/ui CSS variables
|
|
339
|
-
|
|
340
|
-
For additional control, override `--dk-*` variables directly in `globals.css`.
|
|
341
|
-
|
|
342
|
-
### Customization scope
|
|
343
|
-
|
|
344
|
-
CSS variables are the customization layer. The library is opinionated about structure and ships its own UI components — visual appearance is controlled entirely through tokens.
|
|
474
|
+
Designkit maps shadcn/ui CSS variables onto its own `--dk-*` tokens. Changing your shadcn theme automatically updates all designkit components.
|
|
345
475
|
|
|
346
476
|
| What | How |
|
|
347
477
|
|---|---|
|
|
@@ -351,48 +481,53 @@ CSS variables are the customization layer. The library is opinionated about stru
|
|
|
351
481
|
|
|
352
482
|
```css
|
|
353
483
|
:root {
|
|
354
|
-
--dk-radius: 0.375rem;
|
|
355
|
-
--dk-primary: oklch(0.52 0.2 250);
|
|
356
|
-
|
|
357
484
|
--dk-density: 1; /* 0.85 compact / 1 default / 1.15 comfortable */
|
|
358
485
|
--dk-page-padding-x: 1.5rem;
|
|
359
486
|
--dk-page-padding-y: 1rem;
|
|
360
487
|
--dk-panel-gap: 1rem;
|
|
361
|
-
--dk-toolbar-height: 2.75rem;
|
|
362
488
|
}
|
|
363
489
|
```
|
|
364
490
|
|
|
365
|
-
|
|
491
|
+
Per-page override via `className`:
|
|
366
492
|
|
|
367
493
|
```css
|
|
368
|
-
.layout-
|
|
369
|
-
--dk-
|
|
370
|
-
--dk-density: 1.15;
|
|
494
|
+
.layout-dashboard {
|
|
495
|
+
--dk-density: 0.85;
|
|
371
496
|
}
|
|
372
497
|
```
|
|
373
498
|
|
|
374
499
|
```tsx
|
|
375
|
-
<
|
|
376
|
-
...
|
|
377
|
-
</DataBodyTemplate>
|
|
500
|
+
<DashboardBodyTemplate className="layout-dashboard" ...>
|
|
378
501
|
```
|
|
379
502
|
|
|
380
|
-
Or
|
|
503
|
+
Or via `theme` prop:
|
|
381
504
|
|
|
382
505
|
```tsx
|
|
383
506
|
<DataBodyTemplate
|
|
384
|
-
theme={{ '--dk-
|
|
507
|
+
theme={{ '--dk-density': '1.15' } as React.CSSProperties}
|
|
385
508
|
title="Settings"
|
|
386
509
|
>
|
|
387
|
-
...
|
|
388
|
-
</DataBodyTemplate>
|
|
389
510
|
```
|
|
390
511
|
|
|
391
512
|
---
|
|
392
513
|
|
|
514
|
+
## Using with gridkit
|
|
515
|
+
|
|
516
|
+
If your app also uses `@loykin/gridkit`, import its styles **after** designkit:
|
|
517
|
+
|
|
518
|
+
```css
|
|
519
|
+
@import "tailwindcss";
|
|
520
|
+
@import "@loykin/designkit/styles";
|
|
521
|
+
@import "@loykin/gridkit/styles"; /* must come last — uses @layer gridkit */
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
gridkit registers a named `@layer gridkit`. Importing it before `tailwindcss` or `designkit/styles` causes layer ordering conflicts where utility overrides resolve incorrectly.
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
393
528
|
## Playground
|
|
394
529
|
|
|
395
|
-
|
|
530
|
+
Interactive development tool to preview templates and generate code.
|
|
396
531
|
|
|
397
532
|
```bash
|
|
398
533
|
git clone https://github.com/loykin/designkit
|
|
@@ -401,8 +536,6 @@ pnpm install
|
|
|
401
536
|
pnpm dev
|
|
402
537
|
```
|
|
403
538
|
|
|
404
|
-
Open `http://localhost:5173` to browse templates and export code.
|
|
405
|
-
|
|
406
539
|
---
|
|
407
540
|
|
|
408
541
|
## License
|