codebyplan 1.5.1 → 1.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/dist/cli.js +4462 -748
- package/package.json +5 -1
- package/templates/.gitkeep +0 -0
- package/templates/README.md +20 -0
- package/templates/agents/cbp-cc-executor.md +213 -0
- package/templates/agents/cbp-database-agent.md +229 -0
- package/templates/agents/cbp-improve-claude.md +245 -0
- package/templates/agents/cbp-improve-round.md +284 -0
- package/templates/agents/cbp-mechanical-edits.md +111 -0
- package/templates/agents/cbp-research.md +282 -0
- package/templates/agents/cbp-round-executor.md +604 -0
- package/templates/agents/cbp-security-agent.md +134 -0
- package/templates/agents/cbp-task-check.md +213 -0
- package/templates/agents/cbp-task-planner.md +582 -0
- package/templates/agents/cbp-test-e2e-agent.md +363 -0
- package/templates/agents/cbp-testing-qa-agent.md +400 -0
- package/templates/context/mcp-docs.md +139 -0
- package/templates/hooks/README.md +236 -0
- package/templates/hooks/cbp-auto-test-hooks.sh +44 -0
- package/templates/hooks/cbp-lint-format-on-edit.sh +159 -0
- package/templates/hooks/cbp-maestro-yaml-validate.sh +100 -0
- package/templates/hooks/cbp-mcp-migration-guard.sh +32 -0
- package/templates/hooks/cbp-mcp-round-sync.sh +79 -0
- package/templates/hooks/cbp-mcp-worktree-inject.sh +76 -0
- package/templates/hooks/cbp-notify.sh +68 -0
- package/templates/hooks/cbp-plugin-dispatch.sh +29 -0
- package/templates/hooks/cbp-pre-commit-quality-gate.sh +204 -0
- package/templates/hooks/cbp-statusline.sh +347 -0
- package/templates/hooks/cbp-subagent-statusline.sh +182 -0
- package/templates/hooks/cbp-test-coverage-gate.sh +144 -0
- package/templates/hooks/cbp-test-hooks.sh +320 -0
- package/templates/hooks/hooks.json +85 -0
- package/templates/hooks/validate-context-usage.sh +59 -0
- package/templates/hooks/validate-git-commit.sh +78 -0
- package/templates/hooks/validate-git-stash-deny.sh +32 -0
- package/templates/hooks/validate-structure-lengths.sh +57 -0
- package/templates/hooks/validate-structure-lib.sh +104 -0
- package/templates/hooks/validate-structure-patterns.sh +54 -0
- package/templates/hooks/validate-structure-scope.sh +33 -0
- package/templates/hooks/validate-structure-smoke.sh +95 -0
- package/templates/hooks/validate-structure-templates.sh +34 -0
- package/templates/hooks/validate-structure.sh +69 -0
- package/templates/rules/.gitkeep +0 -0
- package/templates/rules/README.md +47 -0
- package/templates/rules/context-file-loading.md +52 -0
- package/templates/rules/scope-vocabulary.md +64 -0
- package/templates/rules/todo-backend.md +109 -0
- package/templates/settings.project.base.json +55 -0
- package/templates/settings.user.base.json +25 -0
- package/templates/skills/cbp-build-cc-agent/SKILL.md +139 -0
- package/templates/skills/cbp-build-cc-agent/examples/read-only-reviewer.md +32 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-hooks.md +41 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-skills-preload.md +25 -0
- package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +153 -0
- package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +37 -0
- package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +18 -0
- package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +67 -0
- package/templates/skills/cbp-build-cc-agent/templates/agent.md +66 -0
- package/templates/skills/cbp-build-cc-claude-file/SKILL.md +178 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/minimal-project.md +33 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/monorepo-with-imports.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/imports.md +72 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/what-belongs.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/project-claude-md.md +48 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/user-claude-md.md +22 -0
- package/templates/skills/cbp-build-cc-memory/SKILL.md +201 -0
- package/templates/skills/cbp-build-cc-memory/examples/feedback-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/project-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/reference-memory.md +13 -0
- package/templates/skills/cbp-build-cc-memory/examples/user-memory.md +14 -0
- package/templates/skills/cbp-build-cc-memory/reference/memory-types.md +59 -0
- package/templates/skills/cbp-build-cc-memory/reference/when-to-save.md +62 -0
- package/templates/skills/cbp-build-cc-memory/templates/MEMORY-index.md +4 -0
- package/templates/skills/cbp-build-cc-memory/templates/memory-entry.md +15 -0
- package/templates/skills/cbp-build-cc-mode/SKILL.md +99 -0
- package/templates/skills/cbp-build-cc-rule/SKILL.md +176 -0
- package/templates/skills/cbp-build-cc-rule/examples/global-rule.md +19 -0
- package/templates/skills/cbp-build-cc-rule/examples/scoped-rule.md +41 -0
- package/templates/skills/cbp-build-cc-rule/reference/paths-patterns.md +48 -0
- package/templates/skills/cbp-build-cc-rule/templates/rule.md +32 -0
- package/templates/skills/cbp-build-cc-settings/SKILL.md +220 -0
- package/templates/skills/cbp-build-cc-settings/examples/hooks-config.json +64 -0
- package/templates/skills/cbp-build-cc-settings/examples/permissions-config.json +34 -0
- package/templates/skills/cbp-build-cc-settings/examples/sandbox-config.json +42 -0
- package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +104 -0
- package/templates/skills/cbp-build-cc-settings/reference/permission-rules.md +61 -0
- package/templates/skills/cbp-build-cc-settings/reference/scope-precedence.md +73 -0
- package/templates/skills/cbp-build-cc-settings/reference/settings-fields.md +166 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.json +23 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.local.json +10 -0
- package/templates/skills/cbp-build-cc-skill/SKILL.md +154 -0
- package/templates/skills/cbp-build-cc-skill/examples/dynamic-context.md +31 -0
- package/templates/skills/cbp-build-cc-skill/examples/fork-skill.md +22 -0
- package/templates/skills/cbp-build-cc-skill/examples/knowledge-skill.md +25 -0
- package/templates/skills/cbp-build-cc-skill/examples/task-skill.md +29 -0
- package/templates/skills/cbp-build-cc-skill/reference/cbp-quality.md +157 -0
- package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +35 -0
- package/templates/skills/cbp-build-cc-skill/reference/string-substitutions.md +60 -0
- package/templates/skills/cbp-build-cc-skill/scripts/validate-skill.sh +90 -0
- package/templates/skills/cbp-build-cc-skill/templates/skill.md +51 -0
- package/templates/skills/cbp-checkpoint-check/SKILL.md +156 -0
- package/templates/skills/cbp-checkpoint-complete/SKILL.md +109 -0
- package/templates/skills/cbp-checkpoint-create/SKILL.md +116 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +241 -0
- package/templates/skills/cbp-checkpoint-plan/SKILL.md +137 -0
- package/templates/skills/cbp-checkpoint-plan/reference/alternative-comparison-template.md +54 -0
- package/templates/skills/cbp-checkpoint-plan/reference/dep-decision-rubric.md +50 -0
- package/templates/skills/cbp-checkpoint-plan/reference/e2e-discovery-probe.md +57 -0
- package/templates/skills/cbp-checkpoint-plan/reference/gap-analysis-playbook.md +47 -0
- package/templates/skills/cbp-checkpoint-start/SKILL.md +84 -0
- package/templates/skills/cbp-checkpoint-update/SKILL.md +115 -0
- package/templates/skills/cbp-frontend-a11y/SKILL.md +109 -0
- package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +130 -0
- package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +122 -0
- package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +154 -0
- package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +111 -0
- package/templates/skills/cbp-frontend-design/SKILL.md +145 -0
- package/templates/skills/cbp-frontend-design/reference/nextjs-scss.md +118 -0
- package/templates/skills/cbp-frontend-design/reference/rn-expo.md +101 -0
- package/templates/skills/cbp-frontend-design/reference/tauri-react.md +82 -0
- package/templates/skills/cbp-frontend-ui/SKILL.md +262 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-label-maps.md +42 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-layout-patterns.md +105 -0
- package/templates/skills/cbp-frontend-ui/reference/variant-defaults.md +149 -0
- package/templates/skills/cbp-frontend-ux/SKILL.md +181 -0
- package/templates/skills/cbp-git-branch-feat-create/SKILL.md +115 -0
- package/templates/skills/cbp-git-commit/SKILL.md +278 -0
- package/templates/skills/cbp-git-worktree-create/SKILL.md +226 -0
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +145 -0
- package/templates/skills/cbp-merge-main/SKILL.md +228 -0
- package/templates/skills/cbp-round-check/SKILL.md +104 -0
- package/templates/skills/cbp-round-end/SKILL.md +183 -0
- package/templates/skills/cbp-round-end/reference/findings-presentation.md +44 -0
- package/templates/skills/cbp-round-end/reference/inline-fallback.md +35 -0
- package/templates/skills/cbp-round-execute/SKILL.md +211 -0
- package/templates/skills/cbp-round-execute/reference/inline-fallback.md +59 -0
- package/templates/skills/cbp-round-input/SKILL.md +165 -0
- package/templates/skills/cbp-round-start/SKILL.md +222 -0
- package/templates/skills/cbp-round-update/SKILL.md +163 -0
- package/templates/skills/cbp-session-end/SKILL.md +187 -0
- package/templates/skills/cbp-session-start/SKILL.md +155 -0
- package/templates/skills/cbp-ship/SKILL.md +332 -0
- package/templates/skills/cbp-ship/reference/changesets-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/eas-cli-overview.md +60 -0
- package/templates/skills/cbp-ship/reference/gh-cli-overview.md +135 -0
- package/templates/skills/cbp-ship/reference/gh-cli-shipment-commands.md +283 -0
- package/templates/skills/cbp-ship/reference/npm-publish-monorepo.md +252 -0
- package/templates/skills/cbp-ship/reference/npm-publish-oidc-trusted.md +157 -0
- package/templates/skills/cbp-ship/reference/npm-publish-overview.md +171 -0
- package/templates/skills/cbp-ship/reference/preflight-checklist.md +88 -0
- package/templates/skills/cbp-ship/reference/railway-nestjs-deployment.md +169 -0
- package/templates/skills/cbp-ship/reference/railway-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/railway-troubleshooting.md +168 -0
- package/templates/skills/cbp-ship/reference/release-please-overview.md +99 -0
- package/templates/skills/cbp-ship/reference/surface-expo-eas.md +155 -0
- package/templates/skills/cbp-ship/reference/surface-npm.md +180 -0
- package/templates/skills/cbp-ship/reference/surface-railway.md +152 -0
- package/templates/skills/cbp-ship/reference/surface-supabase.md +178 -0
- package/templates/skills/cbp-ship/reference/surface-tauri.md +138 -0
- package/templates/skills/cbp-ship/reference/surface-vercel.md +124 -0
- package/templates/skills/cbp-ship/reference/surface-vscode-ext.md +144 -0
- package/templates/skills/cbp-ship/reference/surfaces.md +60 -0
- package/templates/skills/cbp-ship/reference/testflight-automation.md +215 -0
- package/templates/skills/cbp-ship/reference/testflight-internal-vs-external.md +69 -0
- package/templates/skills/cbp-ship/reference/testflight-overview.md +98 -0
- package/templates/skills/cbp-ship/reference/versioning.md +116 -0
- package/templates/skills/cbp-ship/scripts/detect-surfaces.sh +217 -0
- package/templates/skills/cbp-ship/scripts/verify-expo-eas.sh +35 -0
- package/templates/skills/cbp-ship/scripts/verify-npm.sh +21 -0
- package/templates/skills/cbp-ship/scripts/verify-railway.sh +41 -0
- package/templates/skills/cbp-ship/scripts/verify-supabase.sh +19 -0
- package/templates/skills/cbp-ship/scripts/verify-tauri.sh +24 -0
- package/templates/skills/cbp-ship/scripts/verify-vercel.sh +32 -0
- package/templates/skills/cbp-ship/scripts/verify-vscode-ext.sh +25 -0
- package/templates/skills/cbp-ship/templates/eas.json +66 -0
- package/templates/skills/cbp-ship/templates/railway.toml +15 -0
- package/templates/skills/cbp-ship/templates/release-please-config.json +17 -0
- package/templates/skills/cbp-ship/templates/vercel.json +19 -0
- package/templates/skills/cbp-ship/templates/vscodeignore +21 -0
- package/templates/skills/cbp-ship/templates/workflow-changesets.yml +41 -0
- package/templates/skills/cbp-ship/templates/workflow-eas-submit.yml +53 -0
- package/templates/skills/cbp-ship/templates/workflow-npm-publish.yml +36 -0
- package/templates/skills/cbp-ship/templates/workflow-release-please.yml +21 -0
- package/templates/skills/cbp-ship/templates/workflow-tauri-release.yml +69 -0
- package/templates/skills/cbp-ship/templates/workflow-vsce-publish.yml +31 -0
- package/templates/skills/cbp-ship-configure/SKILL.md +296 -0
- package/templates/skills/cbp-ship-configure/reference/expo-mobile.md +204 -0
- package/templates/skills/cbp-ship-configure/reference/npm-package.md +165 -0
- package/templates/skills/cbp-ship-configure/reference/railway-backend.md +199 -0
- package/templates/skills/cbp-ship-configure/reference/supabase.md +200 -0
- package/templates/skills/cbp-ship-configure/reference/tauri-desktop.md +181 -0
- package/templates/skills/cbp-ship-configure/reference/vercel.md +117 -0
- package/templates/skills/cbp-ship-configure/reference/vscode-ext.md +155 -0
- package/templates/skills/cbp-ship-main/SKILL.md +65 -0
- package/templates/skills/cbp-supabase-branch-check/SKILL.md +337 -0
- package/templates/skills/cbp-supabase-branch-check/reference/dag-steps.md +29 -0
- package/templates/skills/cbp-supabase-migrate/SKILL.md +314 -0
- package/templates/skills/cbp-supabase-migrate/reference/advisor-triage.md +70 -0
- package/templates/skills/cbp-supabase-migrate/reference/cli-fallback.md +87 -0
- package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +58 -0
- package/templates/skills/cbp-supabase-setup/SKILL.md +239 -0
- package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +121 -0
- package/templates/skills/cbp-supabase-setup/reference/cli-fallback.md +109 -0
- package/templates/skills/cbp-task-check/SKILL.md +166 -0
- package/templates/skills/cbp-task-complete/SKILL.md +206 -0
- package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +48 -0
- package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +56 -0
- package/templates/skills/cbp-task-create/SKILL.md +167 -0
- package/templates/skills/cbp-task-start/SKILL.md +239 -0
- package/templates/skills/cbp-task-testing/SKILL.md +277 -0
- package/templates/skills/cbp-todo/SKILL.md +111 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# React Native + Expo — Stack Reference
|
|
2
|
+
|
|
3
|
+
Loaded by `frontend-design` Phase 2 when the host app uses React Native + Expo.
|
|
4
|
+
|
|
5
|
+
## Tokens
|
|
6
|
+
|
|
7
|
+
Single source of truth — read before writing any component. Paths below assume an RN/Expo app under `<app>/` (typical convention is `apps/mobile/`); adjust for your repo structure:
|
|
8
|
+
|
|
9
|
+
| Path pattern | Purpose |
|
|
10
|
+
|--------------|---------|
|
|
11
|
+
| `<app>/src/design-system/tokens.ts` | Colours, spacing scale, type scale, radii — TypeScript module |
|
|
12
|
+
| `<app>/src/design-system/index.ts` | Re-exports of typed components (`<Text>`, `<Button>`, `<Card>`, etc.) |
|
|
13
|
+
|
|
14
|
+
If your project maintains a generated tokens catalogue (a markdown listing of every token with its references), keep it under your repo's docs tree and read it before editing tokens.
|
|
15
|
+
|
|
16
|
+
Always import tokens from the design-system module. Hardcoded colours / spacing in `StyleSheet.create` are a hard fail.
|
|
17
|
+
|
|
18
|
+
## StyleSheet.create vs inline
|
|
19
|
+
|
|
20
|
+
- **`StyleSheet.create`** for static styles known at module load. The platform memoizes — cheaper than inline.
|
|
21
|
+
- **Inline `style={...}`** only for values that genuinely depend on props or runtime state. Three or more dynamic styles → extract a `useMemo` or computed style.
|
|
22
|
+
- **Never object-spread inside `style`** in render hot paths — creates a new object every render and busts memoization downstream.
|
|
23
|
+
|
|
24
|
+
## Layout primitives
|
|
25
|
+
|
|
26
|
+
| Primitive | Use for |
|
|
27
|
+
|-----------|---------|
|
|
28
|
+
| `Flex` (custom wrapper if present) or `View` with `flex-direction` | All layout |
|
|
29
|
+
| `useSafeAreaInsets()` from `react-native-safe-area-context` | Top / bottom padding to clear notches and gesture areas |
|
|
30
|
+
| `ScrollView` / `FlatList` / `SectionList` | Lists — pick `FlatList` for >20 items, virtualisation matters |
|
|
31
|
+
| `useWindowDimensions()` | Responsive logic — never `Dimensions.get` (doesn't update on rotate) |
|
|
32
|
+
|
|
33
|
+
## Mandatory rules to load alongside this reference
|
|
34
|
+
|
|
35
|
+
- `rules/react-native-render-purity.md` — render functions must be pure; no side effects
|
|
36
|
+
- `rules/expo-router-navigation-methods.md` — `router.push` vs `router.replace` vs `router.back` semantics
|
|
37
|
+
- `rules/tab-screen-form-state.md` — tab-screen state lifecycle
|
|
38
|
+
- `rules/maestro-merged-a11y-labels.md` — Maestro flattens nested Text — accessibility labels must work on the merged surface
|
|
39
|
+
- `rules/hermes-bundle-grep-false-negative.md` — verifying symbols in Hermes bytecode
|
|
40
|
+
- `rules/auth-listener-lifecycle-cases.md` — auth-listener edge cases when changing UI that touches session state
|
|
41
|
+
|
|
42
|
+
## Floating panel close-on-deselect
|
|
43
|
+
|
|
44
|
+
Modals, action sheets, dropdowns, popovers, and bottom-sheets that respond to a parent's selection state MUST close when the parent is deselected:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
const [showSheet, setShowSheet] = useState(false);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!isSelected) setShowSheet(false);
|
|
51
|
+
}, [isSelected]);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Add this `useEffect` at the moment the panel state is introduced — never as a follow-up. Unit tests MUST cover open-on-toggle, close-on-deselect, no-state-persist-across-cycles. Same pattern as the cross-stack rule in parent SKILL.md Phase 6.
|
|
55
|
+
|
|
56
|
+
## Typography
|
|
57
|
+
|
|
58
|
+
The design-system exports typed `<Text>` variants (`<Heading>`, `<BodyText>`, `<Caption>`, etc.). Never use bare `<Text>` in app code — always the variant. Variant choices are part of the type scale; introducing a new variant means updating the design-system module, not adding a one-off `fontSize` prop.
|
|
59
|
+
|
|
60
|
+
## Motion
|
|
61
|
+
|
|
62
|
+
- `react-native-reanimated` for any non-trivial motion (gestures, scroll-driven, layout animations)
|
|
63
|
+
- `LayoutAnimation` for cheap layout transitions (list insert/remove)
|
|
64
|
+
- Avoid `Animated` (legacy API) for new work
|
|
65
|
+
- Respect `useReducedMotion()` — system-level accessibility setting
|
|
66
|
+
|
|
67
|
+
## Accessibility
|
|
68
|
+
|
|
69
|
+
- Every interactive element needs `accessibilityRole` and `accessibilityLabel`
|
|
70
|
+
- For Text-on-Text composition, the merged label rule applies (see `maestro-merged-a11y-labels.md`)
|
|
71
|
+
- Test labels in Maestro before assuming they work — the rendered tree differs from the JSX tree
|
|
72
|
+
|
|
73
|
+
## Theming and dark mode
|
|
74
|
+
|
|
75
|
+
If the design-system supports light/dark, use `useColorScheme()` + the typed token accessor. Never branch on a string at the component level — branch in the token resolver.
|
|
76
|
+
|
|
77
|
+
## Platform-specific code
|
|
78
|
+
|
|
79
|
+
`Platform.OS === 'ios'` branches are last resort. Prefer:
|
|
80
|
+
- `*.ios.tsx` / `*.android.tsx` file split for substantial divergence
|
|
81
|
+
- Style merging via design-system tokens for visual differences
|
|
82
|
+
- The platform-specific ergonomic adjustments (haptics, gesture, haptic feedback) wrapped in design-system hooks
|
|
83
|
+
|
|
84
|
+
## Common defects this stack produces
|
|
85
|
+
|
|
86
|
+
- Hardcoded `#fff` / `#000` instead of `tokens.color.background` / `tokens.color.foreground`
|
|
87
|
+
- Padding values not on the spacing scale (e.g. `padding: 13` when scale is 4 / 8 / 12 / 16 / 24)
|
|
88
|
+
- Inline-style object that creates a new reference every render
|
|
89
|
+
- Missing `accessibilityRole` on a `<Pressable>`
|
|
90
|
+
- Forgetting `useSafeAreaInsets()` — content under the notch / gesture bar
|
|
91
|
+
- Bare `<Text>` instead of the typed variant
|
|
92
|
+
- `setState` inside render (impure render — see render-purity rule)
|
|
93
|
+
|
|
94
|
+
## Greenfield screen
|
|
95
|
+
|
|
96
|
+
When adding a brand-new top-level screen:
|
|
97
|
+
|
|
98
|
+
1. Pick the aesthetic direction per Phase 3 of the parent skill — match the rest of the mobile app's vibe
|
|
99
|
+
2. Use the typed component imports from `apps/mobile/src/design-system/`
|
|
100
|
+
3. Wrap in the standard screen scaffold (header / safe-area / scroll behaviour) — find the nearest sibling screen and match its scaffold exactly
|
|
101
|
+
4. Add a Maestro flow if the screen is part of a critical path (per `rules/maestro-coverage-required.md`)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Tauri + React — Stack Reference
|
|
2
|
+
|
|
3
|
+
Loaded by `frontend-design` Phase 2 when the host app is Tauri (Rust shell + React WebView frontend). Applies to `workbyplan` (`apps/desktop`), `codebyplan` (`apps/desktop`), and any future Tauri app.
|
|
4
|
+
|
|
5
|
+
## Tokens
|
|
6
|
+
|
|
7
|
+
| Path pattern | Purpose |
|
|
8
|
+
|--------------|---------|
|
|
9
|
+
| `apps/desktop/src/styles/tokens.scss` (or equivalent) | Colours, spacing, type — desktop-specific where the web tokens don't fit |
|
|
10
|
+
| `packages/design-tokens/` | Shared with web if the repo has a sibling Next.js app |
|
|
11
|
+
|
|
12
|
+
Tauri apps often need their own token layer because desktop chrome (window controls, drag regions, native-feel sizing) doesn't map cleanly onto web tokens. Read the desktop token file first; fall back to shared tokens for non-chrome elements.
|
|
13
|
+
|
|
14
|
+
## Layout primitives
|
|
15
|
+
|
|
16
|
+
Tauri renders React inside a native WebView, so the layout vocabulary is web (CSS Grid, Flexbox, SCSS Modules) — but the constraints are desktop:
|
|
17
|
+
|
|
18
|
+
| Constraint | Implication |
|
|
19
|
+
|------------|-------------|
|
|
20
|
+
| Window resize | Layout must respond to small (~600×400) and large (~2560×1440) windows |
|
|
21
|
+
| No mobile breakpoints | Skip RN-style breakpoint logic; design for desktop sizes |
|
|
22
|
+
| Pointer + keyboard primary | Touch is rare; hover states matter; keyboard navigation is required |
|
|
23
|
+
| Native menus + window controls | Don't reinvent in HTML — use the Tauri menu API |
|
|
24
|
+
| Drag regions | Use `data-tauri-drag-region` attribute on the title-bar surface, not synthetic mouse events |
|
|
25
|
+
|
|
26
|
+
## Mandatory rules to load alongside this reference
|
|
27
|
+
|
|
28
|
+
- `rules/eslint-fix-scope.md` — same as web stack
|
|
29
|
+
- `rules/lint-warnings-greenfield.md` — same as web stack
|
|
30
|
+
- `rules/over-engineering-avoidance.md` — desktop apps tempt premature abstraction (custom theming engines, plugin systems) before there's product justification
|
|
31
|
+
|
|
32
|
+
## Split-layer CSS components
|
|
33
|
+
|
|
34
|
+
Tauri uses web CSS, so the split-layer contract from `reference/nextjs-scss.md` applies — outer container holds background / borders / grid placement; inner content holds flex / alignment / textAlign. Function naming `*ContainerCSS()` and `*ContentAlignmentCSS()` conveys layer intent. A merged `*StyleToCSS()` is a red flag.
|
|
35
|
+
|
|
36
|
+
## Floating panel close-on-deselect
|
|
37
|
+
|
|
38
|
+
Same pattern as parent SKILL.md Phase 6 — applies to context menus, dropdowns, sidebars that respond to selection state.
|
|
39
|
+
|
|
40
|
+
## Typography
|
|
41
|
+
|
|
42
|
+
Desktop apps have more vertical space than mobile but less than a desktop browser tab — type scales need to be denser than a marketing site, less dense than a CLI / IDE. Pair a UI-grade body font (system stack `-apple-system, "Segoe UI", system-ui` is acceptable here, even encouraged for native feel) with a distinctive display font for hero / headline surfaces only.
|
|
43
|
+
|
|
44
|
+
## Motion
|
|
45
|
+
|
|
46
|
+
CSS transitions for state changes (hover, focus, active). Avoid heavy JS motion libraries — Tauri WebView is performant but desktop users notice jank more than web users. Reserve animations for:
|
|
47
|
+
- Window state transitions (minimize, restore)
|
|
48
|
+
- Modal / panel reveal
|
|
49
|
+
- List item enter/exit
|
|
50
|
+
|
|
51
|
+
## Native shell integration
|
|
52
|
+
|
|
53
|
+
Things that should NOT be done in CSS / React:
|
|
54
|
+
|
|
55
|
+
- Window chrome drawing — use `tauri.conf.json` window decorations
|
|
56
|
+
- Dock / system tray icons — Tauri APIs
|
|
57
|
+
- Notification toasts — system notification API, not a React component
|
|
58
|
+
- File-system pickers — Tauri dialog plugin
|
|
59
|
+
|
|
60
|
+
## Accessibility
|
|
61
|
+
|
|
62
|
+
WebView accessibility tree maps to platform AT (VoiceOver, NVDA, etc.) — same `aria-*` rules as web. Plus:
|
|
63
|
+
- Keyboard navigation MUST work without mouse (every action needs a shortcut or tab path)
|
|
64
|
+
- Focus rings must be visible — `outline: 2px solid` is fine; never `outline: none` without a `:focus-visible` replacement
|
|
65
|
+
- Window controls must be reachable via keyboard
|
|
66
|
+
|
|
67
|
+
## Common defects this stack produces
|
|
68
|
+
|
|
69
|
+
- Reinventing window chrome in HTML when the Tauri config supports it
|
|
70
|
+
- Designing only for the "default" window size and breaking when the user resizes
|
|
71
|
+
- Using mobile breakpoints (e.g. `@media (max-width: 768px)`) — irrelevant for desktop apps
|
|
72
|
+
- Skipping keyboard navigation because "users have a mouse"
|
|
73
|
+
- Heavy bundle size from web-first libraries that don't pull their weight in a desktop context
|
|
74
|
+
|
|
75
|
+
## Greenfield desktop screen
|
|
76
|
+
|
|
77
|
+
When adding a new top-level screen:
|
|
78
|
+
|
|
79
|
+
1. Read the design from Figma if provided — extract tokens (colour, spacing, type scale) NOT pixel measurements; see parent SKILL.md Phase 1 "Design source images" for the procedure
|
|
80
|
+
2. Decide the resize behaviour up-front: fluid, breakpointed, or fixed-with-scroll
|
|
81
|
+
3. Wire keyboard shortcuts in the same round (don't defer)
|
|
82
|
+
4. Test the screen at three window sizes: minimum, default, maximum
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
---
|
|
2
|
+
scope: org-shared
|
|
3
|
+
name: cbp-frontend-ui
|
|
4
|
+
description: Visual quality self-review pass invoked twice per round — once by round-executor Step 3.8 (phase 'style_only', no screenshots) for token/spacing/typography/color/cohesion, once by /cbp-round-execute Step 5b (phase 'screenshot_review', with e2e screenshots) for rendered-output review and baseline regressions. Default phase 'full' runs everything for back-compat.
|
|
5
|
+
effort: xhigh
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Frontend UI (Post-Implementation Visual Self-Review)
|
|
9
|
+
|
|
10
|
+
Invoked twice per round in non-`claude_only` profiles:
|
|
11
|
+
|
|
12
|
+
1. `round-executor` Step 3.8 — `phase: 'style_only'`, no e2e screenshots. Reviews token/spacing/typography/color/cohesion against the just-written code.
|
|
13
|
+
2. `/cbp-round-execute` Step 5b — `phase: 'screenshot_review'`, with screenshots from `test-e2e-agent`. Reviews rendered output and detects baseline regressions.
|
|
14
|
+
|
|
15
|
+
Default `phase: 'full'` runs everything (back-compat for any caller not yet migrated). Inline counterpart of the up-front `frontend-design` skill — `frontend-design` decides direction before code; `frontend-ui` reviews and polishes after code.
|
|
16
|
+
|
|
17
|
+
## When this skill fires
|
|
18
|
+
|
|
19
|
+
Round-executor invokes when the round's `files_changed` contains ANY of:
|
|
20
|
+
|
|
21
|
+
- `*.tsx`, `*.jsx` (React, RN, RN-Web components)
|
|
22
|
+
- `*.scss`, `*.css`, `*.module.{scss,css}`
|
|
23
|
+
- Files under design-system / token folders, app-level styles
|
|
24
|
+
- New page / screen / route / component files
|
|
25
|
+
|
|
26
|
+
Same trigger condition as Step 2.7's `frontend-design` pre-implementation pass. If none match, skip — proceed to Step 4 (Quality Checks).
|
|
27
|
+
|
|
28
|
+
## Input Contract
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
input:
|
|
32
|
+
task_number: number
|
|
33
|
+
round_number: number
|
|
34
|
+
phase: 'full' | 'style_only' | 'screenshot_review' # Default 'full'. Phase Gate at Workflow start routes execution.
|
|
35
|
+
files_changed: [{path, action}]
|
|
36
|
+
context:
|
|
37
|
+
checkpoint_goal: string
|
|
38
|
+
round_requirements: string
|
|
39
|
+
e2e_screenshots: # Required for phase 'screenshot_review' or 'full' (when present); empty / omitted for 'style_only'. Sourced from round.context.e2e_output.screenshots (populated by test-e2e-agent at /cbp-round-execute Step 5).
|
|
40
|
+
- test_name: string
|
|
41
|
+
path: string # Repo-relative or absolute path to PNG
|
|
42
|
+
page_or_screen: string
|
|
43
|
+
viewport: 'desktop' | 'mobile' | 'tablet' | 'device'
|
|
44
|
+
is_new: bool # No baseline existed (new screen)
|
|
45
|
+
baseline_diff_pct: number | null # Pixel-diff % vs Playwright baseline
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Output Contract
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
output:
|
|
52
|
+
status: 'completed'
|
|
53
|
+
findings:
|
|
54
|
+
- category: 'tokens' | 'spacing' | 'typography' | 'color' | 'layout' | 'cohesion' | 'rendered_visual' | 'baseline_regression'
|
|
55
|
+
severity: 'critical' | 'warning' | 'suggestion'
|
|
56
|
+
file: string # Source file OR screenshot path (for rendered_visual / baseline_regression)
|
|
57
|
+
line: number | null # null when finding originates from a screenshot
|
|
58
|
+
issue: string
|
|
59
|
+
suggestion: string
|
|
60
|
+
screenshot: string | null # Path to screenshot this finding was derived from (if any)
|
|
61
|
+
files_changed:
|
|
62
|
+
- path: string
|
|
63
|
+
action: 'modified'
|
|
64
|
+
fix_for: string # Which finding this fix addresses
|
|
65
|
+
screenshot_review:
|
|
66
|
+
reviewed: number # Count of e2e_screenshots reviewed
|
|
67
|
+
baseline_regressions: number # Count with baseline_diff_pct > threshold
|
|
68
|
+
new_screens_reviewed: number # Count with is_new == true
|
|
69
|
+
summary:
|
|
70
|
+
total_issues: number
|
|
71
|
+
critical: number
|
|
72
|
+
warnings: number
|
|
73
|
+
suggestions: number
|
|
74
|
+
auto_fixed: number
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The executor writes the output to `round.context.frontend_ui_review` and merges `files_changed` into the round's `files_changed` list.
|
|
78
|
+
|
|
79
|
+
## Reference Material
|
|
80
|
+
|
|
81
|
+
Pattern references this skill consults during review (folded from former standalone skills):
|
|
82
|
+
|
|
83
|
+
- `reference/ui-layout-patterns.md` — navbar height, focus-visible, z-index layering, fluid heights, logo overflow
|
|
84
|
+
- `reference/variant-defaults.md` — `createResolver`, `SIZE_VARIANTS`, `COLOR_VARIANTS`, `CUSTOM_VARIANTS`, lightweight variant maps
|
|
85
|
+
- `reference/ui-label-maps.md` — humanising DB column names + enum values for user-facing UI
|
|
86
|
+
|
|
87
|
+
## Workflow
|
|
88
|
+
|
|
89
|
+
### Phase Gate (preamble)
|
|
90
|
+
|
|
91
|
+
Read `input.phase` (default `'full'` when absent). The gate routes which phases run:
|
|
92
|
+
|
|
93
|
+
| Phase value | Phases that run |
|
|
94
|
+
|-------------|----------------|
|
|
95
|
+
| `'full'` (default) | All phases — 1, 2, 2.5, 3, 4, 5, 6, **6.5** (when `e2e_screenshots[]` non-empty), 7, 8 |
|
|
96
|
+
| `'style_only'` | Phases 1, 2, 2.5, 3, 4, 5, 6, 7, 8 (Phase 6.5 is SKIPPED regardless of `e2e_screenshots[]`) |
|
|
97
|
+
| `'screenshot_review'` | Phases 1 (read changed files only — needed for design-source comparison), **6.5**, 7, 8 (Phase 8 is a no-op for `rendered_visual` / `baseline_regression` — those categories are never auto-fixed) |
|
|
98
|
+
|
|
99
|
+
When `phase === 'screenshot_review'` and `e2e_screenshots[]` is empty, return immediately with `status: 'completed'` and an empty `findings[]` — caller asked for screenshot review but provided no screenshots.
|
|
100
|
+
|
|
101
|
+
When `phase === 'style_only'` and `files_changed[]` contains no UI files (no `*.tsx`, `*.scss`, `*.css`, design-token folders), return immediately with `status: 'completed'` and an empty `findings[]`.
|
|
102
|
+
|
|
103
|
+
### Phase 1: Read Changed Files
|
|
104
|
+
|
|
105
|
+
Read all `.tsx`, `.scss`, and `variants.ts` files from `files_changed`.
|
|
106
|
+
|
|
107
|
+
### Phase 2: Design Token Compliance
|
|
108
|
+
|
|
109
|
+
For each SCSS file:
|
|
110
|
+
- Check that colors use semantic tokens (`$color-brand-*`, `$color-highlight-*`), never raw hex/rgb
|
|
111
|
+
- Check spacing uses fluid tokens (`fluid()`, `$spacing-*`), never hardcoded px for layout
|
|
112
|
+
- Check typography uses type scale tokens (`$font-size-*`, `$font-weight-*`)
|
|
113
|
+
- Check z-index uses layering tokens, never arbitrary numbers — see `reference/ui-layout-patterns.md` "Z-Index Layers"
|
|
114
|
+
|
|
115
|
+
For each TSX file:
|
|
116
|
+
- Check inline styles are not used (should be SCSS modules)
|
|
117
|
+
- Check className uses styles from module imports
|
|
118
|
+
|
|
119
|
+
### Phase 2.5: Design Source Comparison
|
|
120
|
+
|
|
121
|
+
When changed files belong to a page that has design source PNGs at a project-known design-sources path (e.g. `docs/design/`, `docs/development/product/sources/design/`):
|
|
122
|
+
|
|
123
|
+
1. **Read** the design source PNG for the relevant page/component
|
|
124
|
+
2. **Compare** the implemented component structure against the design source
|
|
125
|
+
3. **Flag as critical** any of these mismatches:
|
|
126
|
+
- Wrong control shape (e.g. pill vs flat button, toggle vs stepper)
|
|
127
|
+
- Wrong background color (e.g. grey when design shows white)
|
|
128
|
+
- Missing dividers or separators shown in design
|
|
129
|
+
- Wrong column placement (e.g. controls in label column instead of action column)
|
|
130
|
+
- Wrong row/grid structure (e.g. stacked when design shows inline)
|
|
131
|
+
4. Add findings to output with `category: 'cohesion'` and `severity: 'critical'`
|
|
132
|
+
|
|
133
|
+
If no design source PNGs exist for the changed pages, skip this phase.
|
|
134
|
+
|
|
135
|
+
### Phase 3: Spacing Consistency
|
|
136
|
+
|
|
137
|
+
- Verify consistent spacing patterns within components (same spacing system)
|
|
138
|
+
- Check padding/margin consistency across sibling elements
|
|
139
|
+
- Verify fluid spacing is used for layout, em-based for typography-adjacent
|
|
140
|
+
|
|
141
|
+
### Phase 4: Typography Review
|
|
142
|
+
|
|
143
|
+
- Check font-family assignments use design tokens
|
|
144
|
+
- Verify heading hierarchy (h1 > h2 > h3 in size)
|
|
145
|
+
- Check line-height and letter-spacing use tokens
|
|
146
|
+
- Verify responsive typography uses fluid values
|
|
147
|
+
|
|
148
|
+
### Phase 5: Color Usage
|
|
149
|
+
|
|
150
|
+
- Check color semantics (brand vs highlight vs accent vs interactive)
|
|
151
|
+
- Verify hover/focus states use correct color variants — see `reference/ui-layout-patterns.md` "Focus-Visible" and `reference/variant-defaults.md` "COLOR_VARIANTS"
|
|
152
|
+
- Check dark mode compatibility if applicable
|
|
153
|
+
- Verify sufficient contrast ratios (reference WCAG)
|
|
154
|
+
|
|
155
|
+
### Phase 6: Visual Cohesion
|
|
156
|
+
|
|
157
|
+
- Check that new components match visual patterns of existing components
|
|
158
|
+
- Verify consistent border-radius, shadow, and transition usage
|
|
159
|
+
- Check animation patterns follow existing conventions
|
|
160
|
+
- For variant components: verify `variants.ts` follows the resolver patterns in `reference/variant-defaults.md` (no duplicate defaults, correct layer ordering)
|
|
161
|
+
- For DB-sourced strings rendered in JSX (snake_case enums, trigger types, status codes): verify `LABELS` const maps are used per `reference/ui-label-maps.md`
|
|
162
|
+
|
|
163
|
+
### Phase 6.5: Rendered-Output Visual Review (from E2E screenshots)
|
|
164
|
+
|
|
165
|
+
**Runs only if `e2e_screenshots[]` is non-empty.** This is the critical step that closes the loop — e2e tests proved behavior works; this step checks what the screen actually looks like.
|
|
166
|
+
|
|
167
|
+
For each screenshot in `e2e_screenshots[]`:
|
|
168
|
+
|
|
169
|
+
1. **Read the PNG via the Read tool** (Claude multimodal — the PNG is shown to the model directly). Do not use Bash to inspect bytes.
|
|
170
|
+
2. **Check baseline regression** (`baseline_diff_pct != null`):
|
|
171
|
+
- If `baseline_diff_pct > 0.1%`: emit finding `{category: 'baseline_regression', severity: 'critical', file: {path}, screenshot: {path}, issue: 'Pixel diff vs committed baseline: {diff_pct}%', suggestion: 'Inspect the diff PNG (same folder, -diff suffix). Either fix the regression or, if intentional, run `playwright test --update-snapshots` and commit the new baseline.'}`
|
|
172
|
+
- Do NOT auto-update baselines. The user must explicitly approve via QA.
|
|
173
|
+
3. **Semantic review of rendered output** (both new screens and existing):
|
|
174
|
+
- **Text overflow / truncation** — text clipped, ellipsis in unintended places, buttons cut off
|
|
175
|
+
- **Unstyled elements** — unbranded default fonts, missing styles (flash of unstyled content captured), default blue links
|
|
176
|
+
- **Missing imagery / broken images** — placeholder icons, broken-image glyphs, avatar fallback unstyled
|
|
177
|
+
- **Contrast failures** — text barely visible against background (WCAG fail)
|
|
178
|
+
- **Layout breaks** — overlapping elements, pushed-off-canvas content, unintended scrollbars, empty whitespace where content should be
|
|
179
|
+
- **Loading-state artifacts** — spinner visible in final-state screenshot (data didn't load in time or empty-state is wrong)
|
|
180
|
+
- **Error-boundary leaks** — "Something went wrong" / red error banners that shouldn't be there
|
|
181
|
+
- **Design-source mismatch** (if a design-source PNG exists for the page) — compare rendered to designed
|
|
182
|
+
4. **Emit findings** with `category: 'rendered_visual'`, the screenshot path in `screenshot`, and `line: null`. Severity: `critical` for broken state (overflow, missing images, error banners, contrast fails), `warning` for cosmetic misalignment, `suggestion` for minor polish.
|
|
183
|
+
5. **Cross-viewport consistency**: if the same `page_or_screen` appears at multiple viewports (desktop + mobile), verify responsive behavior is correct (nothing cropped at mobile, desktop isn't mobile-sized). Emit `{category: 'layout', severity: 'warning', …}` on mismatch.
|
|
184
|
+
|
|
185
|
+
Populate `screenshot_review` totals.
|
|
186
|
+
|
|
187
|
+
**Do not attempt to auto-fix `rendered_visual` or `baseline_regression` findings** — they feed into user QA and the fix loop, because the root cause is typically in app code/data, not in the SCSS.
|
|
188
|
+
|
|
189
|
+
### Phase 7: Aggregate Findings
|
|
190
|
+
|
|
191
|
+
Categorize all issues by severity:
|
|
192
|
+
- **Critical**: Hardcoded colors/spacing, missing tokens, broken layout
|
|
193
|
+
- **Warning**: Inconsistent spacing, non-standard patterns
|
|
194
|
+
- **Suggestion**: Minor visual improvements, optional enhancements
|
|
195
|
+
|
|
196
|
+
### Phase 8: Auto-Fix In-Scope Findings
|
|
197
|
+
|
|
198
|
+
For every finding in `category` ∈ {`tokens`, `spacing`, `typography`, `color`, `layout`, `cohesion`} — critical, warning, and suggestion — apply the fix directly when the target file is in `files_changed`:
|
|
199
|
+
|
|
200
|
+
#### Pre-Edit Scope Gate (MANDATORY)
|
|
201
|
+
|
|
202
|
+
Before any Write/Edit:
|
|
203
|
+
|
|
204
|
+
1. Build `allowed = new Set(input.files_changed.map(f => f.path))`.
|
|
205
|
+
2. If the target path is in `allowed`, proceed to apply the fix.
|
|
206
|
+
3. If the target path is NOT in `allowed`, do NOT edit. Instead:
|
|
207
|
+
- Emit the proposed fix as a `findings[]` entry with the appropriate severity and a `suggestion` describing the change verbatim.
|
|
208
|
+
- Set `auto_fixed = false` for that finding.
|
|
209
|
+
- Increment `summary.out_of_scope_fixes`.
|
|
210
|
+
|
|
211
|
+
The skill's auto-fix capability is for in-scope polish, not opportunistic sweeps of unrelated files. The scope gate prevents the round's diff from absorbing visual changes outside the round's contract.
|
|
212
|
+
|
|
213
|
+
**Specifically forbidden** (always out of scope, never edited regardless of `files_changed`):
|
|
214
|
+
|
|
215
|
+
- `.claude/**` — managed infrastructure under user-level governance
|
|
216
|
+
- Project test infrastructure (e.g., `playwright.config.*`, `e2e/**`) — governed by `test-e2e-agent`
|
|
217
|
+
- DB migrations (e.g., `supabase/migrations/**`) — governed by `database-agent`
|
|
218
|
+
- Vendor mirrors and read-only reference trees
|
|
219
|
+
|
|
220
|
+
#### In-Scope Auto-Fix Procedure
|
|
221
|
+
|
|
222
|
+
For findings whose target file IS in `allowed`:
|
|
223
|
+
|
|
224
|
+
1. Read the file at the reported line
|
|
225
|
+
2. Apply the fix (replace hardcoded hex with token, swap px for fluid spacing, improve visual consistency, refine typography, enhance cohesion)
|
|
226
|
+
3. Track in `files_changed` with `fix_for` referencing the finding
|
|
227
|
+
|
|
228
|
+
Go beyond fixing violations — actively improve visual quality. If spacing could be better, improve it. If a component looks inconsistent with siblings, align it. Deliver polished UI, not just compliant UI.
|
|
229
|
+
|
|
230
|
+
**Do not auto-fix** findings with `category` ∈ {`rendered_visual`, `baseline_regression`} — these surface through QA and the fix loop because the root cause is typically in app state/data, not styling.
|
|
231
|
+
|
|
232
|
+
**Do not modify** component logic or behavior — only visual/design work.
|
|
233
|
+
|
|
234
|
+
## Completion Criteria
|
|
235
|
+
|
|
236
|
+
- All changed SCSS/TSX files reviewed
|
|
237
|
+
- Token compliance checked
|
|
238
|
+
- Spacing consistency verified
|
|
239
|
+
- **All `e2e_screenshots` reviewed** (when provided) — rendered output checked for overflow, unstyled elements, missing imagery, contrast, layout breaks, loading/error artifacts, design-source fidelity
|
|
240
|
+
- Baseline regressions surfaced (never auto-accepted)
|
|
241
|
+
- Critical/warning issues auto-fixed where possible (styling only, in-scope only)
|
|
242
|
+
- Findings categorized by severity
|
|
243
|
+
|
|
244
|
+
## Failure Modes
|
|
245
|
+
|
|
246
|
+
| Condition | Status | What to populate |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| No UI files changed AND `e2e_screenshots[]` is empty | `completed` | Empty `findings[]`, `summary.total_issues: 0`, `screenshot_review: {reviewed: 0, ...}` — caller decided to invoke; return clean |
|
|
249
|
+
| Screenshot path in `e2e_screenshots[]` cannot be read (missing file, corrupt PNG) | `completed` | Add `{category: 'rendered_visual', severity: 'warning', file: {path}, issue: 'Screenshot unreadable — visual review skipped for this state'}` and continue with the remaining screenshots |
|
|
250
|
+
| Design source PNG referenced but missing | `completed` | Skip Phase 2.5 for that page; note in finding with `category: 'cohesion', severity: 'suggestion'` that design source should be added |
|
|
251
|
+
| Auto-fix attempt introduces a syntax error in an SCSS/TSX file | `completed` | Revert the auto-fix, keep the finding as a non-fixed entry, do NOT silently leave the file broken |
|
|
252
|
+
|
|
253
|
+
## Integration
|
|
254
|
+
|
|
255
|
+
- **Loaded twice per round** (non-`claude_only` profiles):
|
|
256
|
+
1. `round-executor` Step 3.8 with `phase: 'style_only'` and empty `e2e_screenshots[]` — reviews the just-written code's tokens/spacing/typography/color/cohesion (mandatory when files_changed contains UI / styling files)
|
|
257
|
+
2. `/cbp-round-execute` Step 5b with `phase: 'screenshot_review'` and screenshots from `round.context.e2e_output.screenshots` — runs Phase 6.5 only (rendered-output review + baseline regressions). Skipped when no e2e ran (`claude_only` / `backend` / `has_ui_work === false`).
|
|
258
|
+
- **Also invoked by**: `/cbp-checkpoint-check` (TASK-2 deliverable, future) with screenshots from a whole-checkpoint e2e run
|
|
259
|
+
- **Consumes**: `e2e_screenshots[]` from `round.context.e2e_output.screenshots` (populated by `test-e2e-agent` at `/cbp-round-execute` Step 5)
|
|
260
|
+
- **Output written to**: `round.context.frontend_ui_review` — when invoked twice per round, the second invocation merges with the first
|
|
261
|
+
- **User-QA construction (downstream)**: this skill emits `findings[]` only — it does NOT construct user_qa items. `/cbp-round-end` Step 3b reads `round.context.frontend_ui_review.findings[]` and aggregates baseline-regression + rendered-visual-critical entries into the round's `user_qa[]`. Single source of truth for the user_qa schema lives at round-end.
|
|
262
|
+
- **Paired with**: `frontend-design` (pre-implementation aesthetic decision), `frontend-ux` (interaction-quality self-review, also Step 3.8)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# UI Label Maps
|
|
2
|
+
|
|
3
|
+
Pattern for humanizing DB column names, enum values, and trigger types when displayed in user-facing JSX.
|
|
4
|
+
|
|
5
|
+
When displaying database column names, enum values, trigger types, or status codes in user-facing JSX, define a `LABELS` const map in the same component file (or a shared labels module).
|
|
6
|
+
|
|
7
|
+
## Pattern
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const TRIGGER_LABELS: Record<string, string> = {
|
|
11
|
+
port_changed: "Port Changed",
|
|
12
|
+
repo_created: "Repo Created",
|
|
13
|
+
tech_stack_changed: "Tech Stack Changed",
|
|
14
|
+
port_conflict_detected: "Port Conflict",
|
|
15
|
+
created: "Created",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function formatTriggerLabel(trigger: string | null | undefined): string {
|
|
19
|
+
if (!trigger) return "Event";
|
|
20
|
+
return TRIGGER_LABELS[trigger] ?? trigger;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## When to Apply
|
|
25
|
+
|
|
26
|
+
- Rendering DB enum columns in JSX (status, type, action, trigger)
|
|
27
|
+
- Displaying changed_field arrays in audit log UIs
|
|
28
|
+
- Showing column names from JSONB context fields
|
|
29
|
+
- ANY snake_case string sourced from DB that a user will see
|
|
30
|
+
|
|
31
|
+
## Anti-Pattern
|
|
32
|
+
|
|
33
|
+
NEVER render `{event.trigger}` directly when trigger is a snake_case enum. Users see "PORT_CHANGED" with no context.
|
|
34
|
+
|
|
35
|
+
## Shared vs Local Maps
|
|
36
|
+
|
|
37
|
+
- **Local** (in component file): map is used in 1 component, fewer than ~10 entries
|
|
38
|
+
- **Shared** (`apps/web/src/lib/labels/`): map is used in 2+ components OR has 10+ entries
|
|
39
|
+
|
|
40
|
+
## Source
|
|
41
|
+
|
|
42
|
+
CHK-077 TASK-3 Round 2 required adding `TRIGGER_LABELS` + `FIELD_LABELS` maps to `TaskDetail.tsx` after testing-qa flagged raw snake_case in the event timeline.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# UI Layout Patterns
|
|
2
|
+
|
|
3
|
+
Navbar layout patterns, focus-visible accessibility conventions, and z-index layering. Ensures consistent navbar implementation and proper focus-visible accessibility across all client projects.
|
|
4
|
+
|
|
5
|
+
Apply when working with Navbar components, focus-visible styles, or z-index layering in `.scss` files.
|
|
6
|
+
|
|
7
|
+
## 1. Navbar Height is Fluid
|
|
8
|
+
|
|
9
|
+
```scss
|
|
10
|
+
// layout/_variables.scss
|
|
11
|
+
$navbar-height: fluid(3.5rem, 4.5rem); // 56px -> 72px responsive
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
All navbar molecules use the layout variable:
|
|
15
|
+
|
|
16
|
+
```scss
|
|
17
|
+
@use '../../../../styles/layout' as layout;
|
|
18
|
+
.desktop { height: layout.$navbar-height; }
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 2. Logo Sizing Based on Navbar
|
|
22
|
+
|
|
23
|
+
Logo size derives from navbar height:
|
|
24
|
+
|
|
25
|
+
```scss
|
|
26
|
+
$_logo-nav-size: calc(#{layout.$navbar-height} * 0.6);
|
|
27
|
+
|
|
28
|
+
.logo {
|
|
29
|
+
&--nav { font-size: $_logo-nav-size; }
|
|
30
|
+
&--nav-mobile { height: layout.$navbar-height; font-size: $_logo-nav-size; }
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 3. Logo Overflow
|
|
35
|
+
|
|
36
|
+
Logo can overflow navbar with absolute positioning:
|
|
37
|
+
|
|
38
|
+
```scss
|
|
39
|
+
.logo {
|
|
40
|
+
&--nav {
|
|
41
|
+
position: absolute;
|
|
42
|
+
top: 50%;
|
|
43
|
+
transform: translateY(-50%);
|
|
44
|
+
z-index: calc(layout.z-index('navbar') + 1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.desktop {
|
|
49
|
+
position: relative; // Positioning context
|
|
50
|
+
overflow: visible; // Allow overflow
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 4. Navbar Variants
|
|
55
|
+
|
|
56
|
+
| Variant | Component | Height | Notes |
|
|
57
|
+
|---------|-----------|--------|-------|
|
|
58
|
+
| Desktop | Desktop molecule | $navbar-height | Logo overflows |
|
|
59
|
+
| Mobile (collapsed) | MobileOpen | $navbar-height | Logo inside |
|
|
60
|
+
| Mobile (expanded) | MobileClose | 100vh | Full-screen overlay |
|
|
61
|
+
|
|
62
|
+
## 5. Z-Index Layers
|
|
63
|
+
|
|
64
|
+
```scss
|
|
65
|
+
layout.z-index('navbar') // Base navbar layer
|
|
66
|
+
layout.z-index('navbar') + 1 // Logo (above navbar)
|
|
67
|
+
layout.z-index('overlay') // Mobile menu overlay
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 6. Focus-Visible: Always Use the Mixin
|
|
71
|
+
|
|
72
|
+
NEVER write inline `:focus-visible` styles. Always use accessibility module mixins:
|
|
73
|
+
|
|
74
|
+
```scss
|
|
75
|
+
@use '../../styles/accessibility' as a11y;
|
|
76
|
+
|
|
77
|
+
// CORRECT
|
|
78
|
+
.button { @include a11y.focus-visible; }
|
|
79
|
+
|
|
80
|
+
// WRONG
|
|
81
|
+
.button { &:focus-visible { outline: 2px solid #00a7b3; } }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 7. Available Focus Mixins
|
|
85
|
+
|
|
86
|
+
| Mixin | Use Case |
|
|
87
|
+
|-------|----------|
|
|
88
|
+
| `focus-visible` | Standard (2px solid, 2px offset) |
|
|
89
|
+
| `focus-visible-offset($offset)` | Custom offset |
|
|
90
|
+
| `focus-visible-inset` | Inset outline (-2px offset) |
|
|
91
|
+
|
|
92
|
+
## 8. Border-Radius Affects Focus Outline
|
|
93
|
+
|
|
94
|
+
Add `border-radius` for rounded focus outline:
|
|
95
|
+
|
|
96
|
+
```scss
|
|
97
|
+
.logo {
|
|
98
|
+
border-radius: 4px;
|
|
99
|
+
@include a11y.focus-visible;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## 9. Focus vs Hover Colors
|
|
104
|
+
|
|
105
|
+
Use `:focus-visible` (not `:focus`) — shows only on keyboard navigation. Different colors for hover (`$hover-active`) vs focus (`$focus-outline`).
|