@loworbitstudio/visor 0.6.0 → 0.9.0

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
@@ -21,6 +21,8 @@ npx visor init
21
21
  | `visor doctor` | Check your Visor installation health |
22
22
  | `visor diff` | See what's changed since you last updated |
23
23
  | `visor suggest --for <context>` | Get component suggestions for a use case |
24
+ | `visor migrate token-substitution [path]` | Apply the §3.1 V7-primitive → Visor-semantic substitution table (dry-run by default; use `--apply` to commit) |
25
+ | `visor check design <path>` | Scan frontend code for Borealis design anti-patterns (deterministic, no LLM) |
24
26
 
25
27
  ## Target platforms
26
28
 
@@ -40,6 +42,103 @@ preserving your existing deps and comments, and runs `flutter pub get` via
40
42
  When the Flutter CLI can't be found, `add` finishes writing files and warns
41
43
  so you can run `flutter pub get` yourself.
42
44
 
45
+ ## visor check design
46
+
47
+ Deterministic static analysis for Borealis design anti-patterns. No LLM required. Scans `.tsx`, `.jsx`, `.ts`, `.js`, `.css`, and `.module.css` files.
48
+
49
+ ```bash
50
+ # Human-readable terminal output
51
+ npx visor check design ./src
52
+
53
+ # JSON output for programmatic consumers (e.g. /lo-audit-design)
54
+ npx visor check design ./src --json
55
+
56
+ # Errors only (skip warnings)
57
+ npx visor check design ./src --errors-only
58
+
59
+ # Advisory mode — report without failing CI
60
+ npx visor check design ./src --no-fail
61
+ ```
62
+
63
+ ### Output schema (--json)
64
+
65
+ ```json
66
+ {
67
+ "success": true,
68
+ "errors": [
69
+ {
70
+ "file": "src/components/Button.tsx",
71
+ "line": 12,
72
+ "rule": "hardcoded-hex",
73
+ "severity": "error",
74
+ "message": "Hardcoded hex color \"#1a2b3c\" bypasses the Borealis token system.",
75
+ "fix": "Replace with the appropriate semantic token: var(--color-surface), var(--color-text-primary), etc."
76
+ }
77
+ ],
78
+ "warnings": [],
79
+ "summary": {
80
+ "errorCount": 1,
81
+ "warningCount": 0,
82
+ "filesScanned": 14
83
+ }
84
+ }
85
+ ```
86
+
87
+ ### Exit codes
88
+
89
+ | Code | Meaning |
90
+ |------|---------|
91
+ | `0` | No violations (or `--no-fail` mode) |
92
+ | `1` | One or more error-severity findings |
93
+
94
+ ### Rules
95
+
96
+ #### Error rules — Borealis non-negotiables
97
+
98
+ | Rule | What it catches | Fix |
99
+ |------|-----------------|-----|
100
+ | `tier-1-token-direct-usage` | Direct use of `--primitive-*`, `--raw-*`, `--palette-*` tokens in component code | Replace with the equivalent Tier-2 semantic token |
101
+ | `hardcoded-hex` | Raw hex color literals (`#fff`, `#1a2b3c`) in source files | Use `var(--color-surface)`, `var(--color-text-primary)`, etc. |
102
+ | `hardcoded-px` | Hardcoded pixel values in spacing/sizing properties (`margin`, `padding`, `width`, `height`, `gap`) | Use `var(--space-1)`, `var(--space-4)`, etc. |
103
+ | `missing-dark-mode-block` | CSS files without a dark mode block | Add `@media (prefers-color-scheme: dark) { … }` or `[data-theme="dark"] { … }` |
104
+ | `missing-hover-transition` | CSS files with `:hover` but no `transition` property | Add `transition: color 150ms ease, background 150ms ease` to base styles |
105
+ | `div-as-input` | `<div onClick>` without `role=` — div masquerading as interactive element | Use `<button>` or add `role="button"` + `tabIndex={0}` |
106
+ | `setstate-hover` | `useState` used to track hover state (or `onMouseEnter`/`onMouseLeave` with setState) | Delete the hover state variable; use CSS `:hover` instead |
107
+ | `missing-aria-pressed` | Toggle buttons with active/selected/open props but no `aria-pressed` | Add `aria-pressed={isActive}` to the button element |
108
+
109
+ #### Warn rules — general anti-patterns
110
+
111
+ | Rule | What it catches | Fix |
112
+ |------|-----------------|-----|
113
+ | `banned-fonts` | Inter, Roboto, Arial, system-ui font references | Use `var(--font-sans)` or the project's designated font token |
114
+ | `purple-gradient-on-white` | Purple gradient patterns — generic SaaS visual cliché | Replace with brand token gradients |
115
+ | `pure-black-untinted` | `#000`, `#000000`, `black` keyword — flat pure black | Use `var(--color-text-primary)` or a near-black tinted token |
116
+ | `bounce-easing` | Overshoot cubic-bezier values or `bounce` easing keyword | Use `ease`, `ease-out`, or `cubic-bezier(0.4, 0, 0.2, 1)` |
117
+ | `sub-44px-touch-target` | Interactive elements with explicit dimensions below 44px | Minimum 44×44px touch target per WCAG 2.5.5 |
118
+ | `line-length-over-75ch` | `max-width` over 75ch on text containers | Cap at 65–75ch for optimal reading comfort |
119
+ | `gradient-text` | `background-clip: text` / `-webkit-text-fill-color: transparent` gradient text | Use a solid semantic text color token; reserve for hero headings only |
120
+ | `excessive-card-nesting` | Card/Panel/Box components nested 3+ levels deep | Flatten layout; use spacing, dividers, or type scale for hierarchy |
121
+
122
+ ### Per-project rule toggles
123
+
124
+ Create a `.visorrc.json` in the root of the directory being scanned:
125
+
126
+ ```json
127
+ {
128
+ "disabledRules": ["gradient-text", "bounce-easing"]
129
+ }
130
+ ```
131
+
132
+ Rules in `disabledRules` are skipped entirely — useful when a project intentionally deviates from a specific rule.
133
+
134
+ ### CI integration
135
+
136
+ ```yaml
137
+ # GitHub Actions example
138
+ - name: Design anti-pattern check
139
+ run: npx visor check design ./src --json
140
+ ```
141
+
43
142
  ## Documentation
44
143
 
45
144
  Full docs at [visor.loworbit.studio](https://visor.loworbit.studio).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.4.0",
3
- "generated_at": "2026-04-29T19:23:27.559Z",
3
+ "generated_at": "2026-05-12T02:11:40.680Z",
4
4
  "components": {
5
5
  "accessibility-specimen": {
6
6
  "changeType": "current",
@@ -44,6 +44,12 @@
44
44
  "breakingChange": false,
45
45
  "migrationNote": null
46
46
  },
47
+ "bento-grid": {
48
+ "changeType": "current",
49
+ "files": [],
50
+ "breakingChange": false,
51
+ "migrationNote": null
52
+ },
47
53
  "breadcrumb": {
48
54
  "changeType": "current",
49
55
  "files": [],
@@ -92,6 +98,12 @@
92
98
  "breakingChange": false,
93
99
  "migrationNote": null
94
100
  },
101
+ "chip": {
102
+ "changeType": "current",
103
+ "files": [],
104
+ "breakingChange": false,
105
+ "migrationNote": null
106
+ },
95
107
  "code-block": {
96
108
  "changeType": "current",
97
109
  "files": [],
@@ -272,6 +284,12 @@
272
284
  "breakingChange": false,
273
285
  "migrationNote": null
274
286
  },
287
+ "marquee": {
288
+ "changeType": "current",
289
+ "files": [],
290
+ "breakingChange": false,
291
+ "migrationNote": null
292
+ },
275
293
  "menubar": {
276
294
  "changeType": "current",
277
295
  "files": [],
@@ -284,6 +302,12 @@
284
302
  "breakingChange": false,
285
303
  "migrationNote": null
286
304
  },
305
+ "name-roster": {
306
+ "changeType": "current",
307
+ "files": [],
308
+ "breakingChange": false,
309
+ "migrationNote": null
310
+ },
287
311
  "navbar": {
288
312
  "changeType": "current",
289
313
  "files": [],
@@ -422,6 +446,18 @@
422
446
  "breakingChange": false,
423
447
  "migrationNote": null
424
448
  },
449
+ "stat-hero": {
450
+ "changeType": "current",
451
+ "files": [],
452
+ "breakingChange": false,
453
+ "migrationNote": null
454
+ },
455
+ "station-spectrum": {
456
+ "changeType": "current",
457
+ "files": [],
458
+ "breakingChange": false,
459
+ "migrationNote": null
460
+ },
425
461
  "status-badge": {
426
462
  "changeType": "current",
427
463
  "files": [],