@mieweb/ui 0.7.3-dev.7 → 0.7.3-dev.8

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 CHANGED
@@ -60,6 +60,20 @@ Heavy or specialized dependencies are kept in separate entry points so they don'
60
60
  > tables. The `@mieweb/ui/ag-grid` entry remains available for existing
61
61
  > consumers but will be removed in a future major release.
62
62
 
63
+ ### AI Agent Rules
64
+
65
+ Working with AI coding agents (Copilot, Claude Code, Cursor, …)? Install
66
+ @mieweb/ui's agent rules into your repo so agents use library components
67
+ (DataVis NITRO for tables, `Button`/`Badge`/`Modal`/… instead of raw HTML):
68
+
69
+ ```bash
70
+ npx @mieweb/ui init-agent
71
+ ```
72
+
73
+ This writes `.github/instructions/mieweb-ui.instructions.md` (auto-applied by
74
+ VS Code Copilot) and a marked block in `AGENTS.md` (the cross-tool convention).
75
+ Idempotent — rerun after upgrading to refresh the rules. See [agent/](agent/).
76
+
63
77
  ## Quick Start
64
78
 
65
79
  ### Option 1: With Tailwind CSS (Recommended)
@@ -0,0 +1,20 @@
1
+ # agent/ — AI Agent Rules Shipped with @mieweb/ui
2
+
3
+ Rules that teach AI coding agents (Copilot, Claude Code, Cursor, Codex, …) to
4
+ use `@mieweb/ui` components — most importantly, **DataVis NITRO for all
5
+ tables** — instead of inventing their own UI.
6
+
7
+ Agents don't read files inside `node_modules`, so consumers install the rules
8
+ into their repo with:
9
+
10
+ ```bash
11
+ npx @mieweb/ui init-agent
12
+ ```
13
+
14
+ | File | Purpose |
15
+ | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
16
+ | [mieweb-ui.instructions.md](mieweb-ui.instructions.md) | The rules template. Copied verbatim to the consumer's `.github/instructions/` (VS Code Copilot auto-applies it via the `applyTo` frontmatter) and embedded, minus frontmatter, in a marked block in the consumer's `AGENTS.md` (the cross-tool convention). |
17
+ | [init-agent.mjs](init-agent.mjs) | The `mieweb-ui` bin. Idempotent — rerun after upgrading `@mieweb/ui` to refresh both targets. |
18
+
19
+ Rule content is sourced from [lessons/component-policy.md](../lessons/component-policy.md);
20
+ keep the two in sync when policy changes.
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `npx @mieweb/ui init-agent`
4
+ *
5
+ * Installs @mieweb/ui's AI-agent rules into the consuming repository:
6
+ * 1. `.github/instructions/mieweb-ui.instructions.md` — auto-applied by
7
+ * VS Code Copilot (and compatible tools) to matching files.
8
+ * 2. A marked block in `AGENTS.md` — read by Claude Code, Cursor, Codex,
9
+ * and other agents that follow the AGENTS.md convention.
10
+ *
11
+ * Idempotent: rerun after upgrading @mieweb/ui to refresh both targets.
12
+ */
13
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
14
+ import { dirname, join, resolve } from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+
17
+ const command = process.argv[2];
18
+ if (command !== 'init-agent') {
19
+ console.log('Usage: npx @mieweb/ui init-agent');
20
+ process.exit(command ? 1 : 0);
21
+ }
22
+
23
+ const here = dirname(fileURLToPath(import.meta.url));
24
+ const pkg = JSON.parse(readFileSync(join(here, '..', 'package.json'), 'utf8'));
25
+ const template = readFileSync(join(here, 'mieweb-ui.instructions.md'), 'utf8');
26
+ const targetRoot = resolve(process.cwd());
27
+
28
+ // --- 1. VS Code instructions file --------------------------------------
29
+ const instructionsDir = join(targetRoot, '.github', 'instructions');
30
+ const instructionsPath = join(instructionsDir, 'mieweb-ui.instructions.md');
31
+ mkdirSync(instructionsDir, { recursive: true });
32
+ writeFileSync(instructionsPath, template);
33
+ console.log(`✔ wrote .github/instructions/mieweb-ui.instructions.md`);
34
+
35
+ // --- 2. AGENTS.md marked block ------------------------------------------
36
+ const BEGIN = '<!-- mieweb-ui:begin -->';
37
+ const END = '<!-- mieweb-ui:end -->';
38
+ // Same rules, minus the VS Code-specific frontmatter.
39
+ const body = template.replace(/^---\n[\s\S]*?\n---\n+/, '');
40
+ const block = `${BEGIN}\n${body.trimEnd()}\n${END}`;
41
+
42
+ const agentsPath = join(targetRoot, 'AGENTS.md');
43
+ if (!existsSync(agentsPath)) {
44
+ writeFileSync(agentsPath, `${block}\n`);
45
+ console.log('✔ created AGENTS.md');
46
+ } else {
47
+ const current = readFileSync(agentsPath, 'utf8');
48
+ const start = current.indexOf(BEGIN);
49
+ const end = start === -1 ? -1 : current.indexOf(END, start + BEGIN.length);
50
+ let updated;
51
+ if (start !== -1 && end !== -1) {
52
+ updated = current.slice(0, start) + block + current.slice(end + END.length);
53
+ console.log('✔ refreshed @mieweb/ui block in AGENTS.md');
54
+ } else {
55
+ updated = `${current.trimEnd()}\n\n${block}\n`;
56
+ console.log('✔ appended @mieweb/ui block to AGENTS.md');
57
+ }
58
+ writeFileSync(agentsPath, updated);
59
+ }
60
+
61
+ console.log(`\n@mieweb/ui@${pkg.version} agent rules installed.`);
@@ -0,0 +1,169 @@
1
+ ---
2
+ applyTo: '**/*.{ts,tsx,js,jsx}'
3
+ ---
4
+
5
+ <!-- Generated by `npx @mieweb/ui init-agent`. Do not edit by hand — rerun the command after upgrading @mieweb/ui to refresh. -->
6
+
7
+ # @mieweb/ui — Rules for AI Agents
8
+
9
+ This project uses the `@mieweb/ui` component library. Follow these rules for ALL UI work. Browse the full catalog at https://ui.mieweb.org (Storybook).
10
+
11
+ ## Rule 1: Tables start with DataVis NITRO
12
+
13
+ When asked to create a table, data grid, or any tabular data view:
14
+
15
+ - **Always start with `DataVisNitroGrid` from `@mieweb/ui/datavis`.** It is the default for every table — propose it first, every time.
16
+ - If the human **explicitly insists** on a plain, simple table after you propose DataVis NITRO, fall back to the `Table` component from `@mieweb/ui` (`Table` + `TableHeader`/`TableBody`/`TableRow`/`TableCell`). Do not choose `Table` on your own.
17
+ - **`AGGrid` is deprecated.** Never import from `@mieweb/ui/ag-grid` in new code.
18
+ - **Never hand-roll a data grid** from raw `<table>`, `<div>` grids, or a third-party grid library.
19
+
20
+ ```tsx
21
+ import { DataVisNitroSource, DataVisNitroGrid } from '@mieweb/ui/datavis';
22
+ // Peer deps: npm install @mieweb/datavis datavis-ace
23
+ ```
24
+
25
+ ## Rule 2: Buttons belong in a ButtonGroup
26
+
27
+ - **Two or more adjacent buttons → always wrap them in `ButtonGroup`.** Never lay out sibling buttons with ad-hoc flex/gap divs.
28
+ - **A single button with a long or unpredictable label** (sentence-like labels, translated text, user-provided data — e.g. "Permanently delete this record") **→ also wrap it in a `ButtonGroup`.** The default `orientation="auto"` measures labels and controls text ellipsis/stacking so long labels never truncate silently.
29
+ - A single button with a short, fixed label ("Save", "OK") may stand alone.
30
+ - **Icon-only buttons** → `<Button size="icon" aria-label="...">`. The `aria-label` is required.
31
+
32
+ ```tsx
33
+ import { Button, ButtonGroup } from '@mieweb/ui';
34
+
35
+ // Multiple buttons
36
+ <ButtonGroup split>
37
+ <Button variant="ghost">Back</Button>
38
+ <Button variant="secondary">Cancel</Button>
39
+ <Button variant="danger">Permanently delete this record</Button>
40
+ </ButtonGroup>
41
+
42
+ // Single button, long/dynamic label
43
+ <ButtonGroup>
44
+ <Button>{t('orders.submitForPriorAuthorization')}</Button>
45
+ </ButtonGroup>
46
+ ```
47
+
48
+ ## Rule 3: Use an existing @mieweb/ui component before writing your own
49
+
50
+ Before writing any UI element, check whether `@mieweb/ui` already provides it. It ships 126+ components, including:
51
+
52
+ | Category | Components |
53
+ | ---------- | ------------------------------------------------------------------------------------------------------------- |
54
+ | Actions | `Button`, `ButtonGroup` (see Rule 2), `Dropdown`, `CommandPalette`, `QuickAction` |
55
+ | Forms | `Input`, `Textarea`, `Select`, `Checkbox`, `Radio`, `Switch`, `Slider`, `PhoneInput`, `DateInput` |
56
+ | Display | `Table` (only if the human insists — see Rule 1), `Badge`, `Avatar`, `Card`, `CountBadge`, `Text`, `Timeline` |
57
+ | Feedback | `Alert`, `Toast`, `Spinner`, `Skeleton`, `Progress`, `LoadingPage`, `ErrorPage` |
58
+ | Navigation | `Tabs`, `Breadcrumb`, `Pagination`, `Sidebar`, `AppHeader`, `PageHeader`, `StepIndicator` |
59
+ | Overlays | `Modal`, `Tooltip`, `DropzoneOverlay` |
60
+ | Media | `AudioPlayer`, `AudioRecorder`, `RecordButton`, `DocumentScanner` |
61
+ | Messaging | `MessageBubble`, `MessageList`, `MessageComposer` |
62
+ | Grids | `DataVisNitroGrid` (default for all tables) — `AGGrid` is **deprecated** |
63
+
64
+ Raw HTML that duplicates a component is a violation, even if it looks right:
65
+
66
+ ```tsx
67
+ // ❌ Violations
68
+ <button onClick={save}>Save</button>
69
+ <span className="rounded-full bg-blue-100 px-2 py-1 text-xs">Active</span>
70
+ <div className="rounded-lg border p-4 shadow">...</div>
71
+ <table>...</table>
72
+
73
+ // ✅ Compliant
74
+ <Button onClick={save}>Save</Button>
75
+ <Badge>Active</Badge>
76
+ <Card><CardContent>...</CardContent></Card>
77
+ <DataVisNitroGrid ... />
78
+ ```
79
+
80
+ ## Rule 4: Use composition slots, not custom markup
81
+
82
+ Components ship structural sub-components — use them instead of bespoke divs inside a component:
83
+
84
+ - `Modal` → `ModalHeader` / `ModalBody` / `ModalFooter`
85
+ - `Card` → `CardHeader` / `CardContent`
86
+ - `Table` → `TableHeader` / `TableBody` / `TableRow` / `TableCell`
87
+
88
+ ```tsx
89
+ // ❌ <Modal open={open}><div className="p-4 border-b font-bold">Title</div>...</Modal>
90
+ // ✅
91
+ <Modal open={open} onClose={close}>
92
+ <ModalHeader>Title</ModalHeader>
93
+ <ModalBody>...</ModalBody>
94
+ <ModalFooter>...</ModalFooter>
95
+ </Modal>
96
+ ```
97
+
98
+ ## Rule 5: Use variants and sizes, not className hacks
99
+
100
+ If a component has a prop for it, use the prop. Never restyle a component with utility classes to imitate an existing variant.
101
+
102
+ ```tsx
103
+ // ❌ <Button className="bg-red-600 text-white hover:bg-red-700">Delete</Button>
104
+ // ✅ <Button variant="danger">Delete</Button>
105
+ // ❌ <Button className="text-xs px-2 py-1">Save</Button>
106
+ // ✅ <Button size="sm">Save</Button>
107
+ ```
108
+
109
+ Button variants: `primary`, `secondary`, `ghost`, `outline`, `danger`, `link`. Sizes: `sm`, `md`, `lg`, `icon`.
110
+
111
+ ## Rule 6: Never hardcode colors
112
+
113
+ Use design tokens so multi-brand theming (mieweb, bluehive, webchart, enterprise-health, …) keeps working:
114
+
115
+ - ❌ `bg-blue-500`, `text-[#1a73e8]`, `style={{ color: 'red' }}`
116
+ - ✅ semantic tokens: `bg-primary-600`, `text-muted-foreground`, `border-border`, `bg-background`
117
+ - ✅ charts: `var(--mieweb-chart-1)` … `var(--mieweb-chart-5)`
118
+
119
+ ## Rule 7: Theme through the brand system, never global CSS
120
+
121
+ - Wrap the app in `ThemeProvider`; use `@mieweb/ui/brands` (`generateBrandCSS`, `brands`) for brand switching.
122
+ - **No global resets or element-selector overrides** (`button { … }`, `* { … }`). Styles stay component-scoped and minimal.
123
+
124
+ ## Rule 8: Feedback states use library components
125
+
126
+ - Loading: `Spinner` (inline), `Skeleton` (content placeholder), `LoadingPage` (full page). Never a hand-rolled CSS spinner.
127
+ - Outcomes: `Alert` (inline), `Toast` (transient — announces via aria-live for free). Never a bespoke alert div.
128
+ - Errors/empty pages: `ErrorPage`. Progress: `Progress`.
129
+
130
+ ## Rule 9: Accessibility is not optional
131
+
132
+ - Every interactive element needs an accessible name (`aria-label`, `aria-labelledby`, or visible text).
133
+ - Use semantic HTML (`nav`, `main`, `button`) — never a clickable `div`.
134
+ - Dynamic updates (modals, alerts, notifications) must be announced — prefer `Toast`/`Alert`, which handle aria-live.
135
+ - Preserve logical tab order and visible focus indicators; never remove focus outlines.
136
+
137
+ ## Rule 10: Internationalization and RTL
138
+
139
+ - **Externalize all user-facing text** — no hardcoded English strings in JSX. Use the project's i18n function (`t('…')`).
140
+ - **Use RTL-safe logical classes**: `ms-*`/`me-*`, `ps-*`/`pe-*`, `start-*`/`end-*`, `text-start`/`text-end` — never `ml-*`/`mr-*`, `pl-*`/`pr-*`, `left-*`/`right-*`, `text-left`/`text-right`.
141
+ - Localize dates, numbers, and currency via `Intl` APIs, not string formatting.
142
+
143
+ ## Rule 11: Forms
144
+
145
+ - Always use library fields (`Input`, `Textarea`, `Select`, `Checkbox`, `Radio`, `Switch`, `Slider`) with a properly associated `<label>`.
146
+ - Dates → `DateInput` / `DateRangePicker`, never raw `type="date"`. Phones → `PhoneInput`. URLs → `WebsiteInput`.
147
+
148
+ ## Rule 12: Imports and Tailwind setup
149
+
150
+ ```tsx
151
+ // Most components: named imports from the main barrel
152
+ import { Button, Input, Card, Modal, Badge } from '@mieweb/ui';
153
+
154
+ // Heavy add-ons live behind subpath entries (install their peer deps):
155
+ import { DataVisNitroGrid } from '@mieweb/ui/datavis'; // tables/grids
156
+ import { generateBrandCSS, brands } from '@mieweb/ui/brands'; // branding
157
+ ```
158
+
159
+ Never import from `@mieweb/ui/ag-grid` (deprecated).
160
+
161
+ Tailwind: on Tailwind 4, add an `@source` for `@mieweb/ui` so library classes are generated; on Tailwind 3, use the `@mieweb/ui/tailwind-preset` preset and `miewebUISafelist`. Do not invent purge/content configs.
162
+
163
+ ## Rule 13: Deprecations are law
164
+
165
+ If JSDoc, the console, or the docs mark something deprecated (`AGGrid` today), do not use it in new code and do not suppress the warning. Use the documented replacement.
166
+
167
+ ## Rule 14: When no component exists
168
+
169
+ First verify it truly doesn't exist — check https://ui.mieweb.org (Storybook) rather than guessing. Then build it locally, but in `@mieweb/ui` style: Tailwind utility classes with the library's design tokens, ARIA labels on interactive elements, and externalized user-facing text. Prefer composing existing primitives (`Card`, `Text`, `Badge`) over new bespoke markup. If the pattern is generic, propose contributing it upstream to `@mieweb/ui`.