uidex 0.0.1 → 0.1.1

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.
Files changed (39) hide show
  1. package/README.md +249 -214
  2. package/claude/audit-command.md +16 -0
  3. package/claude/rules.md +88 -0
  4. package/dist/core/index.cjs +3217 -0
  5. package/dist/core/index.cjs.map +1 -0
  6. package/dist/core/index.d.cts +331 -0
  7. package/dist/core/index.d.ts +331 -0
  8. package/dist/core/index.global.js +3199 -0
  9. package/dist/core/index.global.js.map +1 -0
  10. package/dist/core/index.js +3174 -0
  11. package/dist/core/index.js.map +1 -0
  12. package/dist/core/style.css +964 -0
  13. package/dist/index.cjs +3288 -0
  14. package/dist/index.cjs.map +1 -0
  15. package/dist/index.d.cts +74 -0
  16. package/dist/index.d.ts +74 -0
  17. package/dist/index.js +3251 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/playwright/index.cjs +72 -0
  20. package/dist/playwright/index.cjs.map +1 -0
  21. package/dist/playwright/index.d.cts +62 -0
  22. package/dist/playwright/index.d.ts +62 -0
  23. package/dist/playwright/index.js +39 -0
  24. package/dist/playwright/index.js.map +1 -0
  25. package/dist/playwright/reporter.cjs +88 -0
  26. package/dist/playwright/reporter.cjs.map +1 -0
  27. package/dist/playwright/reporter.d.cts +24 -0
  28. package/dist/playwright/reporter.d.ts +24 -0
  29. package/dist/playwright/reporter.js +57 -0
  30. package/dist/playwright/reporter.js.map +1 -0
  31. package/dist/react/index.cjs +3288 -0
  32. package/dist/react/index.cjs.map +1 -0
  33. package/dist/react/index.d.cts +74 -0
  34. package/dist/react/index.d.ts +74 -0
  35. package/dist/react/index.js +3251 -0
  36. package/dist/react/index.js.map +1 -0
  37. package/dist/scripts/cli.cjs +1167 -0
  38. package/package.json +106 -7
  39. package/uidex.schema.json +93 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # uidex
2
2
 
3
- A React library for highlighting and annotating components. Perfect for building tutorials, onboarding experiences, or debugging tools.
3
+ A framework-agnostic library for highlighting and annotating UI elements. Works with React, vanilla JS, or any framework. Includes a build-time scanner, inspect mode, Playwright integration, and Claude Code tooling.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,14 +8,61 @@ A React library for highlighting and annotating components. Perfect for building
8
8
  npm install uidex
9
9
  ```
10
10
 
11
- ## Requirements
11
+ ## Quick Start
12
12
 
13
- - React 18 or higher
14
- - React DOM 18 or higher
13
+ ```bash
14
+ # 1. Initialize config
15
+ npx uidex init
16
+
17
+ # 2. Add data-uidex attributes to your elements
18
+ # <button data-uidex="submit-btn">Submit</button>
19
+
20
+ # 3. Run the scanner
21
+ npx uidex scan
22
+ ```
23
+
24
+ ### React
25
+
26
+ ```tsx
27
+ import './uidex.gen';
28
+ import { UidexDevtools } from 'uidex';
29
+
30
+ function App() {
31
+ return (
32
+ <>
33
+ <button data-uidex="submit-btn">Submit</button>
34
+ <UidexDevtools />
35
+ </>
36
+ );
37
+ }
38
+ ```
39
+
40
+ ### Vanilla JS
41
+
42
+ ```js
43
+ import './uidex.gen';
44
+ import { createUidexUI } from 'uidex/core';
45
+
46
+ const ui = createUidexUI();
47
+ ui.mount();
48
+
49
+ // Cleanup
50
+ ui.destroy();
51
+ ```
52
+
53
+ ### Script Tag
54
+
55
+ ```html
56
+ <script src="https://unpkg.com/uidex/dist/core/index.global.js"></script>
57
+ <script>
58
+ const ui = UidexCore.createUidexUI({ components: { ... } });
59
+ ui.mount();
60
+ </script>
61
+ ```
15
62
 
16
63
  ## Configuration
17
64
 
18
- Create a `.uidex.json` file in your project root to customize default settings:
65
+ `npx uidex init` creates a `.uidex.json` file:
19
66
 
20
67
  ```json
21
68
  {
@@ -34,297 +81,285 @@ Create a `.uidex.json` file in your project root to customize default settings:
34
81
  "error": "#ef4444",
35
82
  "info": "#6366f1"
36
83
  },
37
- "disabled": false
84
+ "scanner": {
85
+ "rootDir": "src",
86
+ "include": ["**/*.tsx", "**/*.jsx"],
87
+ "exclude": ["**/*.test.*", "**/*.spec.*"],
88
+ "outputPath": "src/uidex.gen.ts"
89
+ }
38
90
  }
39
91
  ```
40
92
 
41
- ### Using the Config Provider
93
+ ## Scanner
42
94
 
43
- Wrap your app with `AnnotateProvider` to apply configuration:
95
+ The scanner finds `data-uidex` attributes in your source files and generates a typed registry.
44
96
 
45
- ```tsx
46
- import { AnnotateProvider } from 'uidex';
47
- import config from './.uidex.json';
48
-
49
- function App() {
50
- return (
51
- <AnnotateProvider config={config}>
52
- {/* Your app */}
53
- </AnnotateProvider>
54
- );
55
- }
97
+ ```bash
98
+ npx uidex scan # Generate registry
99
+ npx uidex scan --check # Validate UIDEX_PAGE.md coverage
56
100
  ```
57
101
 
58
- ### Named Colors
102
+ Add it to your build:
59
103
 
60
- Use named colors from your config:
61
-
62
- ```tsx
63
- <Annotate label="Error" color="error">
64
- <button>Delete</button>
65
- </Annotate>
104
+ ```json
105
+ {
106
+ "scripts": {
107
+ "prebuild": "npx uidex scan",
108
+ "build": "next build"
109
+ }
110
+ }
66
111
  ```
67
112
 
68
- ## Usage
69
-
70
- ### Annotate Component
71
-
72
- Wrap any component with `Annotate` to add hover-based highlighting:
113
+ ### Annotating Components
73
114
 
74
115
  ```tsx
75
- import { Annotate } from 'uidex';
116
+ <nav data-uidex="main-nav">
117
+ <a href="/">Home</a>
118
+ </nav>
76
119
 
77
- function App() {
78
- return (
79
- <Annotate label="Submit Button" color="#10b981">
80
- <button>Submit</button>
81
- </Annotate>
82
- );
83
- }
120
+ /** @uidex cta-button - Primary call-to-action button */
121
+ <button data-uidex="cta-button">Click Me</button>
84
122
  ```
85
123
 
86
- #### Props
124
+ ### Generated Output
87
125
 
88
- | Prop | Type | Default | Description |
89
- |------|------|---------|-------------|
90
- | `children` | `ReactNode` | required | The content to wrap |
91
- | `label` | `string` | - | Label text shown on hover |
92
- | `color` | `string` | `#3b82f6` | Highlight color (hex or named color) |
93
- | `borderStyle` | `'solid' \| 'dashed' \| 'dotted'` | `'solid'` | Border style |
94
- | `borderWidth` | `number` | `2` | Border width in pixels |
95
- | `showLabel` | `boolean` | `true` | Whether to show the label |
96
- | `labelPosition` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `'top-left'` | Label position |
97
- | `disabled` | `boolean` | `false` | Disable highlighting |
98
- | `className` | `string` | - | Additional CSS class |
99
- | `style` | `CSSProperties` | - | Additional inline styles |
100
- | `onHover` | `(isHovered: boolean) => void` | - | Callback on hover state change |
101
-
102
- ### HighlightOverlay Component
103
-
104
- For more control, use `HighlightOverlay` with a ref to any element:
126
+ The scanner generates `src/uidex.gen.ts` (gitignored) with:
105
127
 
106
- ```tsx
107
- import { useRef } from 'react';
108
- import { HighlightOverlay } from 'uidex';
128
+ - `components` — map of id to file locations
129
+ - `componentIds` array of all ids
130
+ - `ComponentId` union type of all ids
131
+ - `pages` — from `UIDEX_PAGE.md` files (directory-based component association)
132
+ - `features` — from `UIDEX_FEATURE.md` files (explicit component association)
133
+ - Auto-registration calls
109
134
 
110
- function App() {
111
- const buttonRef = useRef<HTMLButtonElement>(null);
135
+ ### Monorepo Support
112
136
 
113
- return (
114
- <>
115
- <button ref={buttonRef}>Click me</button>
116
- <HighlightOverlay
117
- targetRef={buttonRef}
118
- label="Action Button"
119
- color="#f59e0b"
120
- visible={true}
121
- />
122
- </>
123
- );
137
+ Use `sources` for multiple scan roots:
138
+
139
+ ```json
140
+ {
141
+ "scanner": {
142
+ "sources": [
143
+ { "rootDir": "src", "include": ["**/*.tsx"] },
144
+ { "rootDir": "../packages/ui/src", "include": ["**/*.tsx"], "prefix": "@myorg/ui" }
145
+ ],
146
+ "exclude": ["**/*.test.*"],
147
+ "outputPath": "src/uidex.gen.ts"
148
+ }
124
149
  }
125
150
  ```
126
151
 
127
- ### Hooks
152
+ ## Components
128
153
 
129
- #### useHighlight
154
+ ### UidexDevtools (React)
130
155
 
131
- Simple state management for highlight visibility:
156
+ Floating devtools panel with component list, pages, features, and inspect mode.
132
157
 
133
158
  ```tsx
134
- import { useHighlight } from 'uidex';
159
+ import { UidexDevtools } from 'uidex';
135
160
 
136
- function App() {
137
- const { isHighlighted, highlight, unhighlight, toggle } = useHighlight();
138
-
139
- return (
140
- <div>
141
- <button onClick={toggle}>Toggle Highlight</button>
142
- {isHighlighted && <div>Highlighted!</div>}
143
- </div>
144
- );
145
- }
161
+ <UidexDevtools
162
+ buttonPosition="bottom-right"
163
+ onSelect={(id) => console.log(id)}
164
+ />
146
165
  ```
147
166
 
148
- #### useAnnotation
167
+ | Prop | Type | Default | Description |
168
+ |------|------|---------|-------------|
169
+ | `components` | `UidexMap` | registry | Components map |
170
+ | `config` | `UidexConfig` | - | Styling configuration |
171
+ | `buttonPosition` | `ButtonPosition` | `'bottom-right'` | Initial button position |
172
+ | `disabled` | `boolean` | `false` | Disable devtools |
173
+ | `onSelect` | `(id: string) => void` | - | Selection callback |
174
+ | `inspectShortcut` | `KeyboardShortcut \| false` | `Shift+Cmd+U` | Inspect mode shortcut |
149
175
 
150
- Combines a ref with highlight state:
176
+ ### UidexOverlay (React)
177
+
178
+ Standalone overlay for highlighting a single element.
151
179
 
152
180
  ```tsx
153
- import { useAnnotation, HighlightOverlay } from 'uidex';
181
+ import { UidexOverlay } from 'uidex';
154
182
 
155
- function App() {
156
- const { ref, isHighlighted, toggle } = useAnnotation();
183
+ <UidexOverlay
184
+ target={element}
185
+ label="Button"
186
+ color="#3b82f6"
187
+ />
188
+ ```
157
189
 
158
- return (
159
- <>
160
- <div ref={ref}>Target element</div>
161
- <button onClick={toggle}>Toggle</button>
162
- <HighlightOverlay targetRef={ref} visible={isHighlighted} label="Target" />
163
- </>
164
- );
165
- }
190
+ | Prop | Type | Default | Description |
191
+ |------|------|---------|-------------|
192
+ | `target` | `HTMLElement \| null` | required | Element to highlight |
193
+ | `label` | `string` | - | Label text |
194
+ | `color` | `string` | - | Border color (hex or named) |
195
+ | `borderStyle` | `BorderStyle` | `'solid'` | `solid`, `dashed`, or `dotted` |
196
+ | `borderWidth` | `number` | `2` | Border width in px |
197
+ | `showLabel` | `boolean` | `true` | Show label |
198
+ | `labelPosition` | `LabelPosition` | `'top-left'` | Label position |
199
+ | `colors` | `Record<string, string>` | - | Named colors map |
200
+
201
+ ### createUidexUI (Vanilla JS)
202
+
203
+ ```js
204
+ import { createUidexUI } from 'uidex/core';
205
+
206
+ const ui = createUidexUI({
207
+ components: { ... },
208
+ pages: [ ... ],
209
+ features: [ ... ],
210
+ config: { defaults: { color: '#3b82f6' } },
211
+ buttonPosition: 'bottom-right',
212
+ inspectShortcut: { key: 'u', shiftKey: true, metaKey: true },
213
+ onSelect: (id) => console.log(id),
214
+ });
215
+
216
+ ui.mount();
217
+ ui.destroy();
166
218
  ```
167
219
 
168
- #### useAnnotateConfig
220
+ ## Inspect Mode
169
221
 
170
- Access the current configuration:
222
+ Press **Shift+Cmd+U** (Shift+Ctrl+U on Windows/Linux) to enter inspect mode. Hover over elements to highlight them, click to select. Press **Escape** to exit.
171
223
 
172
- ```tsx
173
- import { useAnnotateConfig } from 'uidex';
224
+ Disable or customize the shortcut:
174
225
 
175
- function MyComponent() {
176
- const config = useAnnotateConfig();
226
+ ```tsx
227
+ // Disable
228
+ <UidexDevtools inspectShortcut={false} />
177
229
 
178
- console.log(config.defaults?.color); // Current default color
179
- console.log(config.colors?.primary); // Named color value
180
- }
230
+ // Custom shortcut
231
+ <UidexDevtools inspectShortcut={{ key: 'i', ctrlKey: true }} />
181
232
  ```
182
233
 
183
- ## Build-Time Scanner
234
+ ## Playwright Integration
184
235
 
185
- The `uidex-scan` CLI tool scans your source files for `data-uidex` attributes and generates a TypeScript registry file. This enables type-safe access to all annotations in your codebase.
236
+ Test your annotated components with type-safe locators and coverage reporting.
186
237
 
187
- ### Setup
238
+ ### Test Fixture
188
239
 
189
- Add scanner configuration to your `.uidex.json`:
240
+ ```ts
241
+ import { test, expect } from 'uidex/playwright';
190
242
 
191
- ```json
192
- {
193
- "$schema": "./node_modules/uidex/uidex.schema.json",
194
- "scanner": {
195
- "include": ["**/*.tsx"],
196
- "exclude": ["**/*.test.*", "**/*.spec.*", "**/generated/**"],
197
- "outputPath": "src/generated/annotations.ts",
198
- "rootDir": "src"
199
- }
200
- }
243
+ test('submit button works', async ({ uidex }) => {
244
+ await uidex('submit-btn').click();
245
+ await uidex('success-message').waitFor();
246
+ });
201
247
  ```
202
248
 
203
- Note: The `include` and `exclude` patterns are relative to `rootDir`. If `rootDir` is `src`, use patterns like `**/*.tsx` (not `src/**/*.tsx`).
249
+ ### Coverage Reporter
204
250
 
205
- ### Monorepo Support
251
+ Track which `data-uidex` components are covered by tests:
206
252
 
207
- For monorepos with multiple packages, use the `sources` array to scan multiple directories:
253
+ ```ts
254
+ // playwright.config.ts
255
+ import UidexCoverageReporter from 'uidex/playwright/reporter';
256
+ import { componentIds } from './src/uidex.gen.test';
208
257
 
209
- ```json
210
- {
211
- "$schema": "./node_modules/uidex/uidex.schema.json",
212
- "scanner": {
213
- "sources": [
214
- {
215
- "rootDir": "src",
216
- "include": ["**/*.tsx"]
217
- },
218
- {
219
- "rootDir": "../packages/ui/src",
220
- "include": ["**/*.tsx"],
221
- "prefix": "@myorg/ui"
222
- },
223
- {
224
- "rootDir": "../packages/components/src",
225
- "include": ["**/*.tsx"],
226
- "exclude": ["**/internal/**"],
227
- "prefix": "@myorg/components"
228
- }
229
- ],
230
- "exclude": ["**/*.test.*", "**/*.spec.*", "**/generated/**"],
231
- "outputPath": "src/generated/annotations.ts"
232
- }
233
- }
258
+ export default defineConfig({
259
+ reporter: [
260
+ ['html'],
261
+ [UidexCoverageReporter, { componentIds }],
262
+ ],
263
+ });
234
264
  ```
235
265
 
236
- Each source can have:
237
- - `rootDir` - Directory to scan (can be relative path like `../packages/ui`)
238
- - `include` - Glob patterns for files to include
239
- - `exclude` - Additional exclude patterns for this source only
240
- - `prefix` - Optional prefix for file paths in output (e.g., `@myorg/ui/Button.tsx`)
241
-
242
- The `exclude` at the top level applies globally to all sources.
266
+ Outputs `uidex-coverage.json` with covered/uncovered components and percentage.
243
267
 
244
- ### Usage
268
+ ### Scaffold Tests
245
269
 
246
- Run the scanner as part of your build process:
247
-
248
- ```json
249
- // package.json
250
- {
251
- "scripts": {
252
- "prebuild": "npx uidex-scan",
253
- "build": "next build"
254
- }
255
- }
256
- ```
257
-
258
- Or run it directly:
270
+ Generate test stubs from your pages and features:
259
271
 
260
272
  ```bash
261
- npx uidex-scan
273
+ npx uidex scaffold [dir]
262
274
  ```
263
275
 
264
- ### Adding Annotations
265
-
266
- Add `data-uidex` attributes to your JSX elements:
276
+ ## Claude Code Integration
267
277
 
268
- ```tsx
269
- <nav data-uidex="main-nav">
270
- <a href="/">Home</a>
271
- </nav>
278
+ Set up Claude Code with uidex-aware rules, a `/uidex-audit` skill, and a post-edit hook that validates coverage:
272
279
 
273
- <button data-uidex="cta-button">Click Me</button>
280
+ ```bash
281
+ npx uidex claude init # Add rules + skill + hooks
282
+ npx uidex claude teardown # Remove everything
274
283
  ```
275
284
 
276
- ### Generated Output
277
-
278
- The scanner generates a TypeScript file with all discovered annotations:
285
+ Manage individually:
279
286
 
280
- ```typescript
281
- // Auto-generated by uidex scanner
282
- // Do not edit this file manually
283
-
284
- export const annotations = {
285
- "cta-button": [{ filePath: "src/pages/Home.tsx", line: 12 }],
286
- "main-nav": [{ filePath: "src/components/Header.tsx", line: 5 }]
287
- } as const;
288
-
289
- export const annotationIds = ["cta-button", "main-nav"] as const;
287
+ ```bash
288
+ npx uidex claude rules add|remove # .claude/rules/uidex.md
289
+ npx uidex claude skill add|remove # .claude/commands/uidex-audit.md
290
+ npx uidex claude hooks add|remove # PostToolUse hook in .claude/settings.json
291
+ ```
290
292
 
291
- export type AnnotationId = typeof annotationIds[number];
293
+ ## Theming
294
+
295
+ All UI renders inside a Shadow DOM with CSS custom properties. Override any token at `:root`:
296
+
297
+ ```css
298
+ :root {
299
+ --uidex-color-primary: #2e2e2e;
300
+ --uidex-color-bg: #ffffff;
301
+ --uidex-color-bg-elevated: #f5f5f5;
302
+ --uidex-color-text: #1f2937;
303
+ --uidex-color-text-strong: #111827;
304
+ --uidex-color-text-muted: #6b7280;
305
+ --uidex-color-surface-hover: #f3f4f6;
306
+ --uidex-color-surface-active: #e5e7eb;
307
+ --uidex-color-border: #d1d5db;
308
+ --uidex-color-border-light: #e5e7eb;
309
+ }
292
310
  ```
293
311
 
294
- ### Using Generated Types
312
+ 33 tokens available across colors, shadows, border-radius, z-index, typography, and transitions. The default theme is dark monochromatic with zero border-radius and monospace typography.
295
313
 
296
- Import the generated types for type-safe annotation access:
314
+ ## Package Exports
297
315
 
298
- ```tsx
299
- import { annotations, AnnotationId } from './generated/annotations';
316
+ | Import | Description |
317
+ |--------|-------------|
318
+ | `uidex` | React components (re-exports `uidex/react`) |
319
+ | `uidex/core` | Vanilla JS classes (`createUidexUI`, `Overlay`, `Inspector`) |
320
+ | `uidex/react` | React wrappers (`UidexDevtools`, `UidexOverlay`) |
321
+ | `uidex/playwright` | Test fixture and helpers |
322
+ | `uidex/playwright/reporter` | Coverage reporter |
323
+ | `uidex/styles.css` | Standalone CSS (optional, auto-injected via Shadow DOM) |
300
324
 
301
- function highlightElement(id: AnnotationId) {
302
- const locations = annotations[id];
303
- console.log(`Found at: ${locations[0].filePath}:${locations[0].line}`);
304
- }
325
+ ## CLI Reference
305
326
 
306
- // Type error: "invalid-id" is not a valid AnnotationId
307
- highlightElement("invalid-id");
327
+ ```
328
+ npx uidex Initialize project (alias for init)
329
+ npx uidex init Create .uidex.json and update .gitignore
330
+ npx uidex scan Run component scanner
331
+ npx uidex scan --check Validate UIDEX_PAGE.md coverage
332
+ npx uidex scaffold [dir] Generate Playwright test stubs
333
+ npx uidex claude init Set up Claude Code integration
334
+ npx uidex claude teardown Remove Claude Code integration
308
335
  ```
309
336
 
310
337
  ## TypeScript
311
338
 
312
- This package is written in TypeScript and includes full type definitions. All types are exported:
339
+ Full type definitions included:
313
340
 
314
- ```tsx
341
+ ```ts
315
342
  import type {
316
- AnnotateProps,
317
- AnnotateProviderProps,
343
+ UidexConfig,
344
+ UidexDefaults,
345
+ UidexMap,
346
+ UidexLocation,
347
+ UidexPage,
348
+ UidexFeature,
318
349
  BorderStyle,
319
- HighlightOverlayProps,
320
350
  LabelPosition,
321
- ReactAnnotateConfig,
322
- ReactAnnotateDefaults,
323
- UseAnnotationOptions,
324
- UseHighlightOptions,
351
+ ButtonPosition,
352
+ KeyboardShortcut,
325
353
  } from 'uidex';
326
354
  ```
327
355
 
356
+ ## Examples
357
+
358
+ See `examples/` for working demos:
359
+
360
+ - `examples/next-app/` — Next.js App Router
361
+ - `examples/vite-app/` — Vite + React
362
+
328
363
  ## License
329
364
 
330
365
  MIT
@@ -0,0 +1,16 @@
1
+ Run `npx uidex scan --check` and fix all reported issues:
2
+
3
+ 1. **Uncovered components** (components missing UIDEX_PAGE.md coverage):
4
+ - Create a `UIDEX_PAGE.md` in the nearest feature directory
5
+ - Include a heading, brief description, and acceptance criteria
6
+
7
+ 2. **Orphaned UIDEX_PAGE.md files** (docs with no components underneath):
8
+ - If the components were removed, delete the UIDEX_PAGE.md
9
+ - If components are missing `data-uidex` attributes, add them
10
+
11
+ 3. **Review interactive elements** without `data-uidex` attributes:
12
+ - Scan modified files for buttons, inputs, links, and other interactive elements
13
+ - Add `data-uidex="kebab-id"` attributes where missing
14
+ - Add `/** @uidex id - description */` JSDoc above each annotated element
15
+
16
+ After fixing all issues, run `npx uidex scan` to regenerate the component registry.
@@ -0,0 +1,88 @@
1
+ # uidex conventions
2
+
3
+ This project uses [uidex](https://github.com/soel/uidex) for UI element tracking and documentation.
4
+
5
+ ## data-uidex attributes
6
+
7
+ - Every user-facing interactive element MUST have a `data-uidex="kebab-id"` attribute.
8
+ - IDs should be descriptive and kebab-cased: `data-uidex="submit-btn"`, `data-uidex="user-avatar"`.
9
+ - When creating new components with interactive elements, always add `data-uidex` attributes.
10
+ - When modifying components, preserve existing `data-uidex` attributes. If you rename or remove an element, update or remove its attribute accordingly.
11
+
12
+ ## @uidex JSDoc comments
13
+
14
+ Add a JSDoc comment above annotated elements describing their purpose:
15
+
16
+ ```tsx
17
+ /** @uidex submit-btn - Primary action button for form submission */
18
+ <button data-uidex="submit-btn">Submit</button>
19
+ ```
20
+
21
+ Multi-line format for longer descriptions:
22
+
23
+ ```tsx
24
+ /**
25
+ * @uidex user-profile-card
26
+ * Displays user avatar, name, and role.
27
+ * Shown in the sidebar and team directory.
28
+ */
29
+ <div data-uidex="user-profile-card">...</div>
30
+ ```
31
+
32
+ ## UIDEX_PAGE.md files
33
+
34
+ Page docs describe a route/view. Components in the directory are automatically associated.
35
+
36
+ - Each page directory should have a `UIDEX_PAGE.md` with acceptance criteria.
37
+ - When adding components to a directory that lacks a `UIDEX_PAGE.md`, create one.
38
+ - When removing all components from a directory, remove its `UIDEX_PAGE.md`.
39
+
40
+ ```markdown
41
+ # Page Name
42
+
43
+ Brief description of the page.
44
+
45
+ ## Acceptance
46
+ - User can do X
47
+ - Y is displayed when Z
48
+ ```
49
+
50
+ ## UIDEX_FEATURE.md files
51
+
52
+ Feature docs describe a cross-cutting feature. Components are explicitly listed via frontmatter.
53
+
54
+ - Use `UIDEX_FEATURE.md` for features that span multiple pages (e.g., auth, billing).
55
+ - List associated component IDs in the `components:` frontmatter.
56
+
57
+ ```markdown
58
+ ---
59
+ components:
60
+ - login-form
61
+ - signup-btn
62
+ ---
63
+ # Feature Name
64
+
65
+ Brief description of the feature.
66
+
67
+ ## Acceptance
68
+ - User can do X
69
+ - Y is displayed when Z
70
+ ```
71
+
72
+ ## Component registry
73
+
74
+ For a project-wide view of all components, pages, and features, read the generated registry file (default: `src/uidex.gen.ts`). This file is kept up to date by the scanner.
75
+
76
+ ## Scanner
77
+
78
+ After adding, removing, or renaming `data-uidex` attributes, run:
79
+
80
+ ```bash
81
+ npx uidex scan
82
+ ```
83
+
84
+ To validate that all components have UIDEX_PAGE.md coverage:
85
+
86
+ ```bash
87
+ npx uidex scan --check
88
+ ```