@publicplan/kern-react-kit 1.3.1 → 1.3.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/dist/index.cjs +235 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +24 -0
- package/dist/index.d.cts +52 -44
- package/dist/index.d.ts +52 -44
- package/dist/index.js +235 -188
- package/dist/index.js.map +1 -1
- package/dist/skills/kern-react-kit/SKILL.md +343 -0
- package/dist/skills/kern-react-kit/references/COMPONENTS.md +686 -0
- package/dist/skills/kern-react-kit/references/REFERENCE.md +316 -0
- package/dist/skills/skills.index.json +10 -0
- package/package.json +10 -4
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kern-react-kit
|
|
3
|
+
description: |
|
|
4
|
+
A production-ready React component library providing accessible, composable UI components
|
|
5
|
+
for building consistent user interfaces. Use this skill when integrating @publicplan/kern-react-kit
|
|
6
|
+
into React/TypeScript projects, building component-based UIs with accessibility-first design,
|
|
7
|
+
or implementing design systems with EUPL-licensed components.
|
|
8
|
+
license: EUPL-1.2
|
|
9
|
+
compatibility: |
|
|
10
|
+
Designed for coding agents operating on JavaScript/TypeScript repositories.
|
|
11
|
+
Compatible with React 18.2+ and React 19.1+. No network requirements for skill loading.
|
|
12
|
+
metadata:
|
|
13
|
+
author: publicplan
|
|
14
|
+
package: "@publicplan/kern-react-kit"
|
|
15
|
+
repository: https://github.com/publicplan-internal/kern-components-public-part
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Kern React Kit Skill
|
|
19
|
+
|
|
20
|
+
A composable, accessible React component library for professional UI development.
|
|
21
|
+
|
|
22
|
+
## When to Use This Skill
|
|
23
|
+
|
|
24
|
+
Use **kern-react-kit** when:
|
|
25
|
+
- Building React applications that need production-grade UI components
|
|
26
|
+
- Implementing design systems with accessibility (WCAG 2.1 AA) standards
|
|
27
|
+
- Creating forms, layouts, dialogs, tables, and complex interactive components
|
|
28
|
+
- Ensuring design consistency across multiple projects within an organization
|
|
29
|
+
- Working in TypeScript codebases that benefit from full type safety
|
|
30
|
+
|
|
31
|
+
## Key Principles
|
|
32
|
+
|
|
33
|
+
1. **Composability**: Components use composition patterns; avoid monolithic imports
|
|
34
|
+
2. **Accessibility**: All interactive components must follow WCAG 2.1 AA standards
|
|
35
|
+
3. **Type Safety**: Components export TypeScript interfaces for all props
|
|
36
|
+
4. **Theming**: CSS variables control styling; override via `--kern-*` custom properties
|
|
37
|
+
5. **No External Globals**: Each component is self-contained; no implicit side effects
|
|
38
|
+
|
|
39
|
+
## Public Import Rules
|
|
40
|
+
|
|
41
|
+
### ✅ Correct Imports
|
|
42
|
+
```typescript
|
|
43
|
+
// Main entry point (recommended)
|
|
44
|
+
import { Button, Card, Alert } from '@publicplan/kern-react-kit';
|
|
45
|
+
|
|
46
|
+
// Component-specific imports (also valid)
|
|
47
|
+
import { Button } from '@publicplan/kern-react-kit/Button';
|
|
48
|
+
|
|
49
|
+
// Type-only imports
|
|
50
|
+
import type { ButtonProps, CardProps } from '@publicplan/kern-react-kit';
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### ❌ Forbidden Imports
|
|
54
|
+
- **Do NOT** import from `dist/` directly in source code
|
|
55
|
+
- **Do NOT** import internal/private components (those not exported in `src/index.ts`)
|
|
56
|
+
- **Do NOT** import deep from component internals (e.g., `@publicplan/kern-react-kit/Button/internal`)
|
|
57
|
+
- **Do NOT** import styles outside the main entry point
|
|
58
|
+
|
|
59
|
+
### Library Exports
|
|
60
|
+
The public API includes (non-exhaustive):
|
|
61
|
+
- `Accordion`, `Alert`, `Badge`, `Body`, `Button`, `Card`, `Divider`, `Fieldset`
|
|
62
|
+
- `Grid`, `Heading`, `Icon`, `Label`, `Link`, `Lists`, `Loader`, `Progress`
|
|
63
|
+
- `Summary`, `Table`, `TaskList`, `ThemeProvider`, `Title`, `Dialog`, and more
|
|
64
|
+
- Input components: `TextInput`, `TextareaInput`, `CheckboxInput`, `RadioInput`, `SelectInput`,
|
|
65
|
+
`EmailInput`, `UrlInput`, `TelInput`, `DateInput`, `PasswordInput`, `NumberInput`, `FileInput`,
|
|
66
|
+
`CheckboxList`
|
|
67
|
+
|
|
68
|
+
See **references/COMPONENTS.md** for a more complete list and usage patterns.
|
|
69
|
+
|
|
70
|
+
## Styling & Theming
|
|
71
|
+
|
|
72
|
+
### CSS Custom Properties
|
|
73
|
+
All components respect `--kern-*` CSS variables. Key examples:
|
|
74
|
+
- `--kern-color-primary`, `--kern-color-secondary`
|
|
75
|
+
- `--kern-spacing-*` (unit-based spacing scale)
|
|
76
|
+
- `--kern-radius-*` (border radius scale)
|
|
77
|
+
- `--kern-shadow-*` (elevation shadows)
|
|
78
|
+
- `--kern-font-*` (typography scale)
|
|
79
|
+
|
|
80
|
+
### Overriding Styles
|
|
81
|
+
```tsx
|
|
82
|
+
import { Button } from '@publicplan/kern-react-kit';
|
|
83
|
+
import './my-button-styles.css'; // Your custom styles
|
|
84
|
+
|
|
85
|
+
// my-button-styles.css
|
|
86
|
+
:root {
|
|
87
|
+
--kern-color-primary: #your-color;
|
|
88
|
+
--kern-spacing-lg: 2rem;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Global Styles
|
|
93
|
+
Import the base stylesheet in your app entry point:
|
|
94
|
+
```typescript
|
|
95
|
+
import '@publicplan/kern-react-kit/index.css';
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### SCSS Variables
|
|
99
|
+
Component styling uses SCSS internally. Avoid relying on internal SCSS exports; use CSS variables instead.
|
|
100
|
+
|
|
101
|
+
## Composition Patterns
|
|
102
|
+
|
|
103
|
+
### Namespace Composition
|
|
104
|
+
Some components use namespace composition. Assign a component to a namespace export:
|
|
105
|
+
```typescript
|
|
106
|
+
import { Card, Button } from '@publicplan/kern-react-kit';
|
|
107
|
+
|
|
108
|
+
// Card is composed with sub-components like Media, Container, Header, Body, Footer
|
|
109
|
+
function MyLayout() {
|
|
110
|
+
return (
|
|
111
|
+
<Card style={{ maxWidth: '320px' }}>
|
|
112
|
+
<Card.Media src="https://placehold.co/600x400?text=MEDIA" alt="Card media" />
|
|
113
|
+
<Card.Container>
|
|
114
|
+
<Card.Header>
|
|
115
|
+
<Card.Preline>Preline</Card.Preline>
|
|
116
|
+
<Card.Title>Title</Card.Title>
|
|
117
|
+
<Card.Subline>Subline</Card.Subline>
|
|
118
|
+
</Card.Header>
|
|
119
|
+
<Card.Body>Content goes here</Card.Body>
|
|
120
|
+
<Card.Footer>
|
|
121
|
+
<Button variant="primary" text="Primäraktion" />
|
|
122
|
+
<Button variant="secondary" text="Aktion" />
|
|
123
|
+
</Card.Footer>
|
|
124
|
+
</Card.Container>
|
|
125
|
+
</Card>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Compound Components
|
|
131
|
+
Components like `Dialog`, `Accordion`, and `Table` use compound component patterns:
|
|
132
|
+
```typescript
|
|
133
|
+
import { Dialog, Accordion } from '@publicplan/kern-react-kit';
|
|
134
|
+
|
|
135
|
+
// Dialog compound pattern
|
|
136
|
+
<Dialog disableOverlayClose={false}>
|
|
137
|
+
<Dialog.Trigger>
|
|
138
|
+
<Button variant="primary" text="Open Dialog" />
|
|
139
|
+
</Dialog.Trigger>
|
|
140
|
+
<Dialog.Modal>
|
|
141
|
+
<Dialog.Header dialogTitle="Frage?" hasCloseButton />
|
|
142
|
+
<Dialog.Content>Are you sure?</Dialog.Content>
|
|
143
|
+
<Dialog.Footer>
|
|
144
|
+
<Dialog.Button variant="secondary" title="Abbrechen" />
|
|
145
|
+
<Dialog.Button variant="primary" title="Löschen" />
|
|
146
|
+
</Dialog.Footer>
|
|
147
|
+
</Dialog.Modal>
|
|
148
|
+
</Dialog>
|
|
149
|
+
|
|
150
|
+
// Accordion compound pattern
|
|
151
|
+
<Accordion.Root>
|
|
152
|
+
<Accordion.Summary title={{ title: 'Accordion 1', textWrapper: 'h2' }} />
|
|
153
|
+
<Accordion.Content>Details here</Accordion.Content>
|
|
154
|
+
</Accordion.Root>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Accessibility Requirements
|
|
158
|
+
|
|
159
|
+
### Mandatory Practices
|
|
160
|
+
1. **Interactive Components**: All buttons, links, inputs must have accessible names (`aria-label`, `aria-labelledby`, or text content)
|
|
161
|
+
2. **Forms**: Prefer labeled inputs using `TextInput`'s `label` prop or `Label` with explicit `htmlFor`
|
|
162
|
+
3. **Color Contrast**: Do not rely on color alone; use icons, text, or patterns for information
|
|
163
|
+
4. **Keyboard Navigation**: All interactive components support Tab, Enter, Escape, and arrow keys
|
|
164
|
+
5. **ARIA**: Use `aria-*` attributes for dynamic state (expanded, disabled, hidden, etc.)
|
|
165
|
+
6. **Icons in Alerts/Links**: Icons are `aria-hidden="true"` by default. If the icon conveys meaning, set `aria-hidden={false}` and provide `aria-label`.
|
|
166
|
+
|
|
167
|
+
### Testing Accessibility
|
|
168
|
+
```typescript
|
|
169
|
+
// Example vitest + vitest-axe test pattern
|
|
170
|
+
import { render } from '@testing-library/react';
|
|
171
|
+
import { axe, toHaveNoViolations } from 'vitest-axe';
|
|
172
|
+
import { Button } from '@publicplan/kern-react-kit';
|
|
173
|
+
|
|
174
|
+
expect.extend(toHaveNoViolations);
|
|
175
|
+
|
|
176
|
+
test('Button has no accessibility violations', async () => {
|
|
177
|
+
const { container } = render(<Button>Click me</Button>);
|
|
178
|
+
const results = await axe(container);
|
|
179
|
+
expect(results).toHaveNoViolations();
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Common Recipes
|
|
184
|
+
|
|
185
|
+
### Recipe 1: Form with Validation
|
|
186
|
+
```typescript
|
|
187
|
+
import { Fieldset, TextInput, CheckboxInput, Button } from '@publicplan/kern-react-kit';
|
|
188
|
+
import { useState } from 'react';
|
|
189
|
+
|
|
190
|
+
export function MyForm() {
|
|
191
|
+
const [errors, setErrors] = useState<Record<string, string>>({});
|
|
192
|
+
|
|
193
|
+
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
194
|
+
e.preventDefault();
|
|
195
|
+
const formData = new FormData(e.currentTarget);
|
|
196
|
+
const name = formData.get('name') as string;
|
|
197
|
+
|
|
198
|
+
if (!name) {
|
|
199
|
+
setErrors({ name: 'Der Name darf nicht leer sein' });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Submit logic
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<form onSubmit={handleSubmit}>
|
|
207
|
+
<Fieldset.Root>
|
|
208
|
+
<Fieldset.Legend>Ansprechpartner</Fieldset.Legend>
|
|
209
|
+
<Fieldset.Content>
|
|
210
|
+
<TextInput
|
|
211
|
+
id="name"
|
|
212
|
+
name="name"
|
|
213
|
+
label="Name"
|
|
214
|
+
error={errors.name}
|
|
215
|
+
aria-describedby={errors.name ? 'name-error' : undefined}
|
|
216
|
+
required
|
|
217
|
+
/>
|
|
218
|
+
<CheckboxInput
|
|
219
|
+
id="privacy"
|
|
220
|
+
name="privacy"
|
|
221
|
+
label="Ich akzeptiere die Datenschutzerklärung"
|
|
222
|
+
required
|
|
223
|
+
/>
|
|
224
|
+
</Fieldset.Content>
|
|
225
|
+
{errors.name && <Fieldset.Error id="name-error">{errors.name}</Fieldset.Error>}
|
|
226
|
+
</Fieldset.Root>
|
|
227
|
+
<Button type="submit" variant="primary" text="Submit" />
|
|
228
|
+
</form>
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Recipe 2: Card Layout with Grid
|
|
234
|
+
```typescript
|
|
235
|
+
import { Card, Grid, Button } from '@publicplan/kern-react-kit';
|
|
236
|
+
|
|
237
|
+
export function Dashboard() {
|
|
238
|
+
return (
|
|
239
|
+
<Grid>
|
|
240
|
+
<Grid.Row>
|
|
241
|
+
<Grid.Column width={4}>
|
|
242
|
+
<Card>
|
|
243
|
+
<Card.Container>
|
|
244
|
+
<Card.Header>
|
|
245
|
+
<Card.Title>Total Users</Card.Title>
|
|
246
|
+
</Card.Header>
|
|
247
|
+
<Card.Body>1,234</Card.Body>
|
|
248
|
+
<Card.Footer>
|
|
249
|
+
<Button variant="secondary" text="Details" />
|
|
250
|
+
</Card.Footer>
|
|
251
|
+
</Card.Container>
|
|
252
|
+
</Card>
|
|
253
|
+
</Grid.Column>
|
|
254
|
+
<Grid.Column width={4}>
|
|
255
|
+
<Card>
|
|
256
|
+
<Card.Container>
|
|
257
|
+
<Card.Header>
|
|
258
|
+
<Card.Title>Active Sessions</Card.Title>
|
|
259
|
+
</Card.Header>
|
|
260
|
+
<Card.Body>567</Card.Body>
|
|
261
|
+
<Card.Footer>
|
|
262
|
+
<Button variant="secondary" text="Details" />
|
|
263
|
+
</Card.Footer>
|
|
264
|
+
</Card.Container>
|
|
265
|
+
</Card>
|
|
266
|
+
</Grid.Column>
|
|
267
|
+
<Grid.Column width={4}>
|
|
268
|
+
<Card>
|
|
269
|
+
<Card.Container>
|
|
270
|
+
<Card.Header>
|
|
271
|
+
<Card.Title>Revenue</Card.Title>
|
|
272
|
+
</Card.Header>
|
|
273
|
+
<Card.Body>€45,678</Card.Body>
|
|
274
|
+
<Card.Footer>
|
|
275
|
+
<Button variant="secondary" text="Details" />
|
|
276
|
+
</Card.Footer>
|
|
277
|
+
</Card.Container>
|
|
278
|
+
</Card>
|
|
279
|
+
</Grid.Column>
|
|
280
|
+
</Grid.Row>
|
|
281
|
+
</Grid>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Recipe 3: Modal Dialog with Confirmation
|
|
287
|
+
```typescript
|
|
288
|
+
import { Dialog, Button } from '@publicplan/kern-react-kit';
|
|
289
|
+
|
|
290
|
+
export function ConfirmDialog({ onConfirm }: { onConfirm: () => void }) {
|
|
291
|
+
return (
|
|
292
|
+
<Dialog disableOverlayClose={false}>
|
|
293
|
+
<Dialog.Trigger>
|
|
294
|
+
<Button variant="primary" text="Delete Item" />
|
|
295
|
+
</Dialog.Trigger>
|
|
296
|
+
<Dialog.Modal>
|
|
297
|
+
<Dialog.Header dialogTitle="Confirm Deletion" hasCloseButton />
|
|
298
|
+
<Dialog.Content>
|
|
299
|
+
This action cannot be undone. Are you sure?
|
|
300
|
+
</Dialog.Content>
|
|
301
|
+
<Dialog.Footer>
|
|
302
|
+
<Dialog.Button variant="secondary" title="Cancel" />
|
|
303
|
+
<Dialog.Button
|
|
304
|
+
variant="primary"
|
|
305
|
+
title="Delete"
|
|
306
|
+
onClick={(e, context) => {
|
|
307
|
+
onConfirm();
|
|
308
|
+
context.closeDialog();
|
|
309
|
+
}}
|
|
310
|
+
/>
|
|
311
|
+
</Dialog.Footer>
|
|
312
|
+
</Dialog.Modal>
|
|
313
|
+
</Dialog>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Testing & Storybook
|
|
319
|
+
|
|
320
|
+
### Unit Tests
|
|
321
|
+
- Components are tested with **vitest** and **@testing-library/react**
|
|
322
|
+
- All tests live in `__tests__/components/`
|
|
323
|
+
- Run tests: `npm test` or `npm run test:watch` for development
|
|
324
|
+
|
|
325
|
+
### Storybook Stories
|
|
326
|
+
- Interactive documentation: `npm run storybook`
|
|
327
|
+
- All components have Storybook stories for isolated development and testing
|
|
328
|
+
- Stories are co-located with components (e.g., `Button.stories.tsx`)
|
|
329
|
+
|
|
330
|
+
### E2E Tests
|
|
331
|
+
- Playwright tests in `__tests__/e2e/`
|
|
332
|
+
- Run: `npm run test:e2e`
|
|
333
|
+
|
|
334
|
+
## Further Reference
|
|
335
|
+
|
|
336
|
+
For deeper technical details, see:
|
|
337
|
+
- **references/REFERENCE.md**: Installation, API stability, theming rules, and testing expectations
|
|
338
|
+
- **references/COMPONENTS.md**: Component catalog with import paths, prop interfaces, and usage examples
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
*Last updated: 2026-03-03*
|
|
343
|
+
*Package: @publicplan/kern-react-kit@1.0.1*
|