@loworbitstudio/visor 0.7.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 +99 -0
- package/dist/CHANGELOG.json +37 -1
- package/dist/index.js +1365 -300
- package/dist/registry.json +183 -2
- package/dist/visor-manifest.json +741 -5
- package/package.json +2 -2
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).
|
package/dist/CHANGELOG.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.4.0",
|
|
3
|
-
"generated_at": "2026-05-
|
|
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": [],
|