@su-record/vibe 2.8.52 → 2.9.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.
- package/.env.example +37 -37
- package/CLAUDE.md +169 -169
- package/LICENSE +21 -21
- package/README.ko.md +43 -128
- package/README.md +43 -128
- package/agents/architect-low.md +41 -41
- package/agents/architect-medium.md +59 -59
- package/agents/architect.md +80 -80
- package/agents/build-error-resolver.md +115 -115
- package/agents/compounder.md +261 -261
- package/agents/diagrammer.md +178 -178
- package/agents/docs/api-documenter.md +99 -99
- package/agents/docs/changelog-writer.md +93 -93
- package/agents/e2e-tester.md +294 -294
- package/agents/event/event-comms.md +78 -78
- package/agents/event/event-content.md +68 -68
- package/agents/event/event-image.md +95 -95
- package/agents/event/event-ops.md +84 -84
- package/agents/event/event-scheduler.md +69 -69
- package/agents/event/event-speaker.md +86 -86
- package/agents/explorer-low.md +42 -42
- package/agents/explorer-medium.md +59 -59
- package/agents/explorer.md +48 -48
- package/agents/implementer-low.md +43 -43
- package/agents/implementer-medium.md +52 -52
- package/agents/implementer.md +54 -54
- package/agents/junior-mentor.md +141 -141
- package/agents/planning/requirements-analyst.md +84 -84
- package/agents/planning/ux-advisor.md +83 -83
- package/agents/qa/acceptance-tester.md +86 -86
- package/agents/qa/edge-case-finder.md +93 -93
- package/agents/qa/qa-coordinator.md +131 -131
- package/agents/refactor-cleaner.md +143 -143
- package/agents/research/best-practices-agent.md +199 -199
- package/agents/research/codebase-patterns-agent.md +157 -157
- package/agents/research/framework-docs-agent.md +188 -188
- package/agents/research/security-advisory-agent.md +213 -213
- package/agents/review/architecture-reviewer.md +107 -107
- package/agents/review/complexity-reviewer.md +116 -116
- package/agents/review/data-integrity-reviewer.md +88 -88
- package/agents/review/git-history-reviewer.md +103 -103
- package/agents/review/performance-reviewer.md +86 -86
- package/agents/review/python-reviewer.md +150 -150
- package/agents/review/rails-reviewer.md +139 -139
- package/agents/review/react-reviewer.md +144 -144
- package/agents/review/security-reviewer.md +80 -80
- package/agents/review/simplicity-reviewer.md +140 -140
- package/agents/review/test-coverage-reviewer.md +116 -116
- package/agents/review/typescript-reviewer.md +127 -127
- package/agents/searcher.md +54 -54
- package/agents/simplifier.md +120 -120
- package/agents/tester.md +49 -49
- package/agents/ui/ui-a11y-auditor.md +93 -93
- package/agents/ui/ui-antipattern-detector.md +102 -102
- package/agents/ui/ui-dataviz-advisor.md +69 -69
- package/agents/ui/ui-design-system-gen.md +57 -57
- package/agents/ui/ui-industry-analyzer.md +49 -49
- package/agents/ui/ui-layout-architect.md +65 -65
- package/agents/ui/ui-stack-implementer.md +68 -68
- package/agents/ui/ux-compliance-reviewer.md +81 -81
- package/agents/ui-previewer.md +258 -258
- package/commands/vibe.analyze.md +379 -379
- package/commands/vibe.docs.md +32 -32
- package/commands/vibe.event.md +163 -163
- package/commands/vibe.figma.md +69 -69
- package/commands/vibe.review.md +686 -686
- package/commands/vibe.run.md +2276 -2276
- package/commands/vibe.spec.md +1195 -1195
- package/commands/vibe.spec.review.md +609 -609
- package/commands/vibe.trace.md +259 -259
- package/commands/vibe.utils.md +413 -413
- package/commands/vibe.verify.md +510 -510
- package/dist/cli/collaborator.js +52 -52
- package/dist/cli/commands/config.js +9 -9
- package/dist/cli/commands/evolution.js +12 -12
- package/dist/cli/commands/figma.js +20 -20
- package/dist/cli/commands/info.js +53 -53
- package/dist/cli/commands/init.js +5 -5
- package/dist/cli/commands/remove.js +14 -14
- package/dist/cli/commands/sentinel.js +27 -27
- package/dist/cli/commands/skills.js +5 -5
- package/dist/cli/commands/slack.js +10 -10
- package/dist/cli/commands/stats.js +6 -6
- package/dist/cli/commands/telegram.js +12 -12
- package/dist/cli/detect.js +32 -32
- package/dist/cli/index.js +51 -51
- package/dist/cli/llm/claude-commands.js +16 -16
- package/dist/cli/llm/config.js +18 -18
- package/dist/cli/llm/gemini-commands.js +16 -16
- package/dist/cli/llm/gpt-commands.js +19 -19
- package/dist/cli/llm/help.js +21 -21
- package/dist/cli/postinstall/cursor-agents.js +32 -32
- package/dist/cli/postinstall/cursor-rules.js +83 -83
- package/dist/cli/postinstall/cursor-skills.js +743 -743
- package/dist/cli/postinstall/main.d.ts.map +1 -1
- package/dist/cli/postinstall/main.js +40 -66
- package/dist/cli/postinstall/main.js.map +1 -1
- package/dist/cli/setup/Provisioner.js +42 -42
- package/dist/infra/lib/CostAccumulator.d.ts +58 -0
- package/dist/infra/lib/CostAccumulator.d.ts.map +1 -0
- package/dist/infra/lib/CostAccumulator.js +131 -0
- package/dist/infra/lib/CostAccumulator.js.map +1 -0
- package/dist/infra/lib/DeepInit.js +24 -24
- package/dist/infra/lib/IterationTracker.js +11 -11
- package/dist/infra/lib/PythonParser.js +108 -108
- package/dist/infra/lib/ReviewRace.js +96 -96
- package/dist/infra/lib/SkillFrontmatter.js +28 -28
- package/dist/infra/lib/SkillQualityGate.js +9 -9
- package/dist/infra/lib/SkillRepository.js +159 -159
- package/dist/infra/lib/TokenBudgetTracker.d.ts +13 -0
- package/dist/infra/lib/TokenBudgetTracker.d.ts.map +1 -1
- package/dist/infra/lib/TokenBudgetTracker.js +44 -3
- package/dist/infra/lib/TokenBudgetTracker.js.map +1 -1
- package/dist/infra/lib/UltraQA.js +99 -99
- package/dist/infra/lib/autonomy/AuditStore.js +41 -41
- package/dist/infra/lib/autonomy/ConfirmationStore.js +30 -30
- package/dist/infra/lib/autonomy/EventOutbox.js +38 -38
- package/dist/infra/lib/autonomy/PolicyEngine.d.ts +3 -3
- package/dist/infra/lib/autonomy/PolicyEngine.js +18 -18
- package/dist/infra/lib/autonomy/SecuritySentinel.js +1 -1
- package/dist/infra/lib/autonomy/SuggestionStore.js +33 -33
- package/dist/infra/lib/embedding/VectorStore.js +22 -22
- package/dist/infra/lib/evolution/AgentAnalyzer.js +10 -10
- package/dist/infra/lib/evolution/DescriptionOptimizer.js +21 -21
- package/dist/infra/lib/evolution/GenerationRegistry.js +36 -36
- package/dist/infra/lib/evolution/InsightStore.js +90 -90
- package/dist/infra/lib/evolution/ParityTester.js +57 -57
- package/dist/infra/lib/evolution/RollbackManager.js +5 -5
- package/dist/infra/lib/evolution/SkillBenchmark.js +23 -23
- package/dist/infra/lib/evolution/SkillEvalRunner.js +50 -50
- package/dist/infra/lib/evolution/SkillGapDetector.js +10 -10
- package/dist/infra/lib/evolution/UsageTracker.js +28 -28
- package/dist/infra/lib/gemini/orchestration.js +5 -5
- package/dist/infra/lib/gpt/orchestration.js +4 -4
- package/dist/infra/lib/memory/KnowledgeGraph.js +4 -4
- package/dist/infra/lib/memory/MemorySearch.js +57 -57
- package/dist/infra/lib/memory/MemoryStorage.js +181 -181
- package/dist/infra/lib/memory/ObservationStore.js +28 -28
- package/dist/infra/lib/memory/ReflectionStore.js +30 -30
- package/dist/infra/lib/memory/SessionRAGRetriever.js +7 -7
- package/dist/infra/lib/memory/SessionRAGStore.js +225 -225
- package/dist/infra/lib/memory/SessionSummarizer.js +9 -9
- package/dist/infra/orchestrator/AgentManager.js +12 -12
- package/dist/infra/orchestrator/AgentRegistry.js +65 -65
- package/dist/infra/orchestrator/MultiLlmResearch.js +8 -8
- package/dist/infra/orchestrator/SwarmOrchestrator.test.js +16 -16
- package/dist/infra/orchestrator/parallelResearch.js +24 -24
- package/dist/tools/convention/analyzeComplexity.test.js +115 -115
- package/dist/tools/convention/validateCodeQuality.test.js +104 -104
- package/dist/tools/memory/createMemoryTimeline.js +10 -10
- package/dist/tools/memory/getMemoryGraph.js +12 -12
- package/dist/tools/memory/getSessionContext.js +9 -9
- package/dist/tools/memory/linkMemories.js +14 -14
- package/dist/tools/memory/listMemories.js +4 -4
- package/dist/tools/memory/recallMemory.js +4 -4
- package/dist/tools/memory/saveMemory.js +4 -4
- package/dist/tools/memory/searchMemoriesAdvanced.js +23 -23
- package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
- package/dist/tools/semantic/astGrep.test.js +6 -6
- package/dist/tools/spec/prdParser.test.js +171 -171
- package/dist/tools/spec/specGenerator.js +169 -169
- package/dist/tools/spec/traceabilityMatrix.js +64 -64
- package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
- package/hooks/gemini-hooks.json +73 -73
- package/hooks/hooks.json +174 -174
- package/hooks/scripts/__tests__/keyword-detector.test.js +199 -199
- package/hooks/scripts/__tests__/pre-tool-guard.test.js +286 -286
- package/hooks/scripts/__tests__/sentinel-guard.test.js +210 -210
- package/hooks/scripts/auto-commit.js +97 -97
- package/hooks/scripts/auto-format.js +64 -64
- package/hooks/scripts/auto-test.js +81 -81
- package/hooks/scripts/code-check.js +268 -268
- package/hooks/scripts/codex-detect.js +46 -46
- package/hooks/scripts/codex-review-gate.js +80 -80
- package/hooks/scripts/command-log.js +32 -32
- package/hooks/scripts/context-save.js +353 -353
- package/hooks/scripts/evolution-engine.js +91 -91
- package/hooks/scripts/figma-extract.js +635 -477
- package/hooks/scripts/hud-status.js +321 -321
- package/hooks/scripts/keyword-detector.js +214 -214
- package/hooks/scripts/llm-orchestrate.js +572 -572
- package/hooks/scripts/post-edit.js +32 -32
- package/hooks/scripts/pr-test-gate.js +52 -52
- package/hooks/scripts/pre-tool-guard.js +214 -159
- package/hooks/scripts/prompt-dispatcher.js +185 -185
- package/hooks/scripts/sentinel-guard.js +131 -131
- package/hooks/scripts/session-start.js +177 -177
- package/hooks/scripts/skill-injector.js +83 -83
- package/hooks/scripts/stop-notify.js +209 -209
- package/hooks/scripts/utils.js +243 -243
- package/languages/csharp-unity.md +515 -515
- package/languages/gdscript-godot.md +470 -470
- package/languages/ruby-rails.md +489 -489
- package/languages/typescript-angular.md +433 -433
- package/languages/typescript-astro.md +416 -416
- package/languages/typescript-electron.md +406 -406
- package/languages/typescript-nestjs.md +524 -524
- package/languages/typescript-svelte.md +407 -407
- package/languages/typescript-tauri.md +365 -365
- package/package.json +101 -101
- package/skills/agents-md/SKILL.md +121 -121
- package/skills/agents-md/rubrics/what-to-keep.md +49 -49
- package/skills/agents-md/templates/agents-md.md +36 -36
- package/skills/arch-guard/SKILL.md +181 -181
- package/skills/arch-guard/agents/detector.md +48 -48
- package/skills/arch-guard/agents/reporter.md +48 -48
- package/skills/arch-guard/agents/rule-generator.md +49 -49
- package/skills/arch-guard/agents/violation-checker.md +51 -51
- package/skills/arch-guard/frameworks/clean-architecture.md +108 -108
- package/skills/arch-guard/frameworks/solid.md +102 -102
- package/skills/arch-guard/scripts/check-boundaries.js +90 -90
- package/skills/arch-guard/templates/arch-rules.json +47 -47
- package/skills/arch-guard/templates/violation-report.md +53 -53
- package/skills/brand-assets/SKILL.md +147 -147
- package/skills/brand-assets/rubrics/asset-checklist.md +98 -98
- package/skills/brand-assets/templates/brand-guide.md +161 -161
- package/skills/capability-loop/SKILL.md +168 -168
- package/skills/capability-loop/agents/capability-designer.md +61 -61
- package/skills/capability-loop/agents/failure-analyst.md +55 -55
- package/skills/capability-loop/agents/implementer.md +50 -50
- package/skills/capability-loop/agents/tester.md +53 -53
- package/skills/capability-loop/templates/capability-spec.md +118 -118
- package/skills/capability-loop/templates/failure-analysis.md +118 -118
- package/skills/characterization-test/SKILL.md +207 -207
- package/skills/characterization-test/agents/behavior-capturer.md +50 -50
- package/skills/characterization-test/agents/coverage-checker.md +54 -54
- package/skills/characterization-test/agents/reporter.md +50 -50
- package/skills/characterization-test/agents/test-writer.md +49 -49
- package/skills/characterization-test/rubrics/coverage-criteria.md +53 -53
- package/skills/characterization-test/templates/test-template.ts +101 -101
- package/skills/chub-usage/SKILL.md +139 -139
- package/skills/claude-md-guide/SKILL.md +351 -351
- package/skills/claude-md-guide/rubrics/anti-patterns.md +88 -88
- package/skills/claude-md-guide/templates/claude-md.md +54 -54
- package/skills/commerce-patterns/SKILL.md +64 -64
- package/skills/commerce-patterns/rubrics/checkout-flow.md +48 -48
- package/skills/commerce-patterns/templates/product-schema.md +85 -85
- package/skills/commit-push-pr/SKILL.md +77 -77
- package/skills/commit-push-pr/agents/change-analyzer.md +55 -55
- package/skills/commit-push-pr/agents/message-writer.md +50 -50
- package/skills/commit-push-pr/agents/pr-writer.md +58 -58
- package/skills/commit-push-pr/agents/reviewer.md +52 -52
- package/skills/commit-push-pr/rubrics/commit-message.md +73 -73
- package/skills/commit-push-pr/templates/pr-body.md +63 -63
- package/skills/context7-usage/SKILL.md +106 -106
- package/skills/context7-usage/rubrics/when-to-use.md +50 -50
- package/skills/create-prd/SKILL.md +90 -90
- package/skills/create-prd/agents/edge-case-finder.md +48 -48
- package/skills/create-prd/agents/prioritizer.md +60 -60
- package/skills/create-prd/agents/requirements-writer.md +48 -48
- package/skills/create-prd/agents/researcher.md +55 -55
- package/skills/create-prd/agents/reviewer.md +54 -54
- package/skills/create-prd/frameworks/jobs-to-be-done.md +96 -96
- package/skills/create-prd/frameworks/rice-scoring.md +97 -97
- package/skills/create-prd/orchestrator.md +70 -70
- package/skills/create-prd/rubrics/completeness.md +58 -58
- package/skills/create-prd/templates/prd.md +139 -139
- package/skills/design-audit/SKILL.md +152 -152
- package/skills/design-audit/agents/a11y-auditor.md +43 -43
- package/skills/design-audit/agents/performance-auditor.md +46 -46
- package/skills/design-audit/agents/responsive-auditor.md +46 -46
- package/skills/design-audit/agents/scorer.md +47 -47
- package/skills/design-audit/agents/slop-detector.md +47 -47
- package/skills/design-audit/frameworks/core-web-vitals.md +107 -107
- package/skills/design-audit/frameworks/wcag-checklist.md +64 -64
- package/skills/design-audit/orchestrator.md +64 -64
- package/skills/design-audit/rubrics/ai-slop-patterns.md +83 -83
- package/skills/design-audit/rubrics/scoring.md +63 -63
- package/skills/design-audit/templates/report.md +88 -88
- package/skills/design-critique/SKILL.md +139 -139
- package/skills/design-critique/rubrics/ux-heuristics.md +143 -143
- package/skills/design-critique/templates/critique-report.md +86 -86
- package/skills/design-distill/SKILL.md +130 -130
- package/skills/design-distill/templates/design-system.md +132 -132
- package/skills/design-normalize/SKILL.md +133 -133
- package/skills/design-normalize/rubrics/token-naming.md +117 -117
- package/skills/design-normalize/templates/token-audit.md +89 -89
- package/skills/design-polish/SKILL.md +131 -131
- package/skills/design-polish/rubrics/polish-checklist.md +68 -68
- package/skills/design-polish/templates/polish-report.md +64 -64
- package/skills/design-teach/SKILL.md +182 -182
- package/skills/design-teach/rubrics/brand-personality.md +73 -73
- package/skills/design-teach/templates/design-context.json +36 -36
- package/skills/e2e-commerce/SKILL.md +62 -62
- package/skills/e2e-commerce/templates/test-scenarios.md +170 -170
- package/skills/event-comms/SKILL.md +162 -162
- package/skills/event-comms/templates/email-invite.md +99 -99
- package/skills/event-comms/templates/sns-post.md +133 -133
- package/skills/event-ops/SKILL.md +198 -198
- package/skills/event-ops/rubrics/contingency.md +85 -85
- package/skills/event-ops/templates/d-day-checklist.md +65 -65
- package/skills/event-planning/SKILL.md +132 -132
- package/skills/event-planning/rubrics/timeline.md +70 -70
- package/skills/event-planning/templates/event-plan.md +91 -91
- package/skills/exec-plan/SKILL.md +149 -149
- package/skills/exec-plan/agents/decomposer.md +47 -47
- package/skills/exec-plan/agents/dependency-mapper.md +44 -44
- package/skills/exec-plan/agents/estimator.md +43 -43
- package/skills/exec-plan/agents/validator.md +55 -55
- package/skills/exec-plan/orchestrator.md +70 -70
- package/skills/exec-plan/rubrics/complexity-scoring.md +75 -75
- package/skills/exec-plan/templates/plan.md +147 -147
- package/skills/git-worktree/SKILL.md +73 -73
- package/skills/git-worktree/rubrics/when-to-use.md +55 -55
- package/skills/handoff/SKILL.md +110 -110
- package/skills/handoff/agents/context-summarizer.md +51 -51
- package/skills/handoff/agents/document-writer.md +63 -63
- package/skills/handoff/agents/state-collector.md +53 -53
- package/skills/handoff/agents/verifier.md +48 -48
- package/skills/handoff/rubrics/completeness.md +62 -62
- package/skills/handoff/templates/handoff.md +107 -107
- package/skills/parallel-research/SKILL.md +89 -89
- package/skills/parallel-research/agents/best-practices.md +43 -43
- package/skills/parallel-research/agents/codebase-patterns.md +46 -46
- package/skills/parallel-research/agents/framework-docs.md +45 -45
- package/skills/parallel-research/agents/security-advisory.md +46 -46
- package/skills/parallel-research/agents/synthesizer.md +52 -52
- package/skills/parallel-research/experts/best-practices.md +50 -50
- package/skills/parallel-research/experts/codebase-patterns.md +70 -70
- package/skills/parallel-research/experts/framework-docs.md +65 -65
- package/skills/parallel-research/experts/security-advisory.md +69 -69
- package/skills/parallel-research/orchestrator.md +65 -65
- package/skills/parallel-research/templates/synthesis.md +101 -101
- package/skills/prioritization-frameworks/SKILL.md +87 -87
- package/skills/prioritization-frameworks/rubrics/frameworks.md +79 -79
- package/skills/prioritization-frameworks/templates/scoring-matrix.md +69 -69
- package/skills/priority-todos/SKILL.md +64 -64
- package/skills/priority-todos/rubrics/prioritization.md +70 -70
- package/skills/priority-todos/templates/todo-board.md +59 -59
- package/skills/seo-checklist/SKILL.md +58 -58
- package/skills/seo-checklist/frameworks/structured-data.md +153 -153
- package/skills/seo-checklist/rubrics/content-seo.md +42 -42
- package/skills/seo-checklist/rubrics/technical-seo.md +48 -48
- package/skills/techdebt/SKILL.md +124 -124
- package/skills/techdebt/agents/analyzer.md +50 -50
- package/skills/techdebt/agents/fixer.md +41 -41
- package/skills/techdebt/agents/reviewer.md +47 -47
- package/skills/techdebt/agents/scanner.md +44 -44
- package/skills/techdebt/orchestrator.md +70 -70
- package/skills/techdebt/rubrics/severity.md +51 -51
- package/skills/techdebt/scripts/scan.js +90 -90
- package/skills/techdebt/templates/report.md +86 -86
- package/skills/tool-fallback/SKILL.md +104 -104
- package/skills/tool-fallback/rubrics/fallback-chain.md +58 -58
- package/skills/typescript-advanced-types/SKILL.md +67 -67
- package/skills/typescript-advanced-types/rubrics/type-patterns.md +109 -109
- package/skills/ui-ux-pro-max/SKILL.md +236 -236
- package/skills/ui-ux-pro-max/reference/color-and-contrast.md +517 -517
- package/skills/ui-ux-pro-max/reference/interaction-design.md +544 -544
- package/skills/ui-ux-pro-max/reference/motion-design.md +591 -591
- package/skills/ui-ux-pro-max/reference/responsive-design.md +463 -463
- package/skills/ui-ux-pro-max/reference/spatial-design.md +390 -390
- package/skills/ui-ux-pro-max/reference/typography.md +455 -455
- package/skills/ui-ux-pro-max/reference/ux-writing.md +469 -469
- package/skills/ui-ux-pro-max/rubrics/interaction-states.md +83 -83
- package/skills/ui-ux-pro-max/rubrics/responsive-breakpoints.md +99 -99
- package/skills/user-personas/SKILL.md +75 -75
- package/skills/user-personas/rubrics/research-methods.md +56 -56
- package/skills/user-personas/templates/persona.md +89 -89
- package/skills/vercel-react-best-practices/SKILL.md +60 -60
- package/skills/vercel-react-best-practices/rubrics/performance.md +82 -82
- package/skills/vercel-react-best-practices/rubrics/server-components.md +86 -86
- package/skills/vibe.docs/SKILL.md +171 -171
- package/skills/vibe.docs/templates/architecture.md +80 -80
- package/skills/vibe.docs/templates/readme.md +84 -84
- package/skills/vibe.docs/templates/release-notes.md +74 -74
- package/skills/vibe.figma/SKILL.md +215 -982
- package/skills/vibe.figma/rubrics/extraction-checklist.md +51 -51
- package/skills/vibe.figma/templates/component-index.md +126 -126
- package/skills/vibe.figma/templates/figma-handoff.md +100 -100
- package/skills/vibe.figma/templates/remapped-tree.md +277 -277
- package/skills/vibe.figma.convert/SKILL.md +188 -511
- package/skills/vibe.figma.convert/rubrics/conversion-rules.md +129 -113
- package/skills/vibe.figma.convert/templates/component.md +140 -140
- package/skills/vibe.figma.extract/SKILL.md +179 -300
- package/skills/vibe.figma.extract/rubrics/image-rules.md +145 -137
- package/skills/video-production/SKILL.md +52 -52
- package/skills/video-production/rubrics/quality-checklist.md +58 -58
- package/skills/video-production/templates/production-plan.md +104 -104
- package/vibe/config.json +29 -29
- package/vibe/constitution.md +227 -227
- package/vibe/rules/principles/communication-guide.md +98 -98
- package/vibe/rules/principles/development-philosophy.md +52 -52
- package/vibe/rules/principles/quick-start.md +102 -102
- package/vibe/rules/quality/bdd-contract-testing.md +393 -393
- package/vibe/rules/quality/checklist.md +276 -276
- package/vibe/rules/quality/performance.md +236 -236
- package/vibe/rules/quality/testing-strategy.md +440 -440
- package/vibe/rules/standards/anti-patterns.md +541 -541
- package/vibe/rules/standards/code-structure.md +291 -291
- package/vibe/rules/standards/complexity-metrics.md +313 -313
- package/vibe/rules/standards/git-workflow.md +237 -237
- package/vibe/rules/standards/naming-conventions.md +198 -198
- package/vibe/rules/standards/security.md +305 -305
- package/vibe/rules/writing/document-style.md +74 -74
- package/vibe/setup.sh +31 -31
- package/vibe/templates/constitution-template.md +252 -252
- package/vibe/templates/contract-backend-template.md +526 -526
- package/vibe/templates/contract-frontend-template.md +599 -599
- package/vibe/templates/feature-template.md +96 -96
- package/vibe/templates/spec-template.md +221 -221
- package/vibe/ui-ux-data/charts.csv +26 -26
- package/vibe/ui-ux-data/colors.csv +97 -97
- package/vibe/ui-ux-data/icons.csv +101 -101
- package/vibe/ui-ux-data/landing.csv +31 -31
- package/vibe/ui-ux-data/products.csv +96 -96
- package/vibe/ui-ux-data/react-performance.csv +45 -45
- package/vibe/ui-ux-data/stacks/astro.csv +54 -54
- package/vibe/ui-ux-data/stacks/flutter.csv +53 -53
- package/vibe/ui-ux-data/stacks/html-tailwind.csv +56 -56
- package/vibe/ui-ux-data/stacks/jetpack-compose.csv +53 -53
- package/vibe/ui-ux-data/stacks/nextjs.csv +53 -53
- package/vibe/ui-ux-data/stacks/nuxt-ui.csv +51 -51
- package/vibe/ui-ux-data/stacks/nuxtjs.csv +59 -59
- package/vibe/ui-ux-data/stacks/react-native.csv +52 -52
- package/vibe/ui-ux-data/stacks/react.csv +54 -54
- package/vibe/ui-ux-data/stacks/shadcn.csv +61 -61
- package/vibe/ui-ux-data/stacks/svelte.csv +54 -54
- package/vibe/ui-ux-data/stacks/swiftui.csv +51 -51
- package/vibe/ui-ux-data/stacks/vue.csv +50 -50
- package/vibe/ui-ux-data/styles.csv +68 -68
- package/vibe/ui-ux-data/typography.csv +57 -57
- package/vibe/ui-ux-data/ui-reasoning.csv +101 -101
- package/vibe/ui-ux-data/ux-guidelines.csv +99 -99
- package/vibe/ui-ux-data/version.json +31 -31
- package/vibe/ui-ux-data/web-interface.csv +31 -31
|
@@ -1,469 +1,469 @@
|
|
|
1
|
-
# UX Writing Reference Guide
|
|
2
|
-
|
|
3
|
-
Practical patterns for writing UI copy that reduces friction, builds trust, and works across languages and contexts.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Button Labels
|
|
8
|
-
|
|
9
|
-
Buttons are the primary call-to-action in any interface. Weak labels create hesitation; strong labels create momentum.
|
|
10
|
-
|
|
11
|
-
**The pattern: verb + object.** Tell users exactly what will happen when they click.
|
|
12
|
-
|
|
13
|
-
| Weak | Strong |
|
|
14
|
-
|------|--------|
|
|
15
|
-
| Submit | Save Profile |
|
|
16
|
-
| OK | Confirm Booking |
|
|
17
|
-
| Yes | Delete Account |
|
|
18
|
-
| Update | Change Password |
|
|
19
|
-
| Continue | Go to Checkout |
|
|
20
|
-
|
|
21
|
-
The verb signals the action type. The object anchors it to the current context. Together they eliminate ambiguity.
|
|
22
|
-
|
|
23
|
-
**DO / DON'T**
|
|
24
|
-
|
|
25
|
-
DO: Match the button label to the consequence.
|
|
26
|
-
```html
|
|
27
|
-
<!-- Destructive action: label mirrors the destruction -->
|
|
28
|
-
<button class="btn-danger">Delete Project</button>
|
|
29
|
-
|
|
30
|
-
<!-- Constructive action: label mirrors the creation -->
|
|
31
|
-
<button class="btn-primary">Create Project</button>
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
DON'T: Use generic labels that could mean anything.
|
|
35
|
-
```html
|
|
36
|
-
<!-- "OK" — OK to what? OK means nothing. -->
|
|
37
|
-
<button>OK</button>
|
|
38
|
-
|
|
39
|
-
<!-- "Submit" — submit what? to where? -->
|
|
40
|
-
<button>Submit</button>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
DO: Reflect form field context in the CTA.
|
|
44
|
-
- A profile editing form ends with `Save Changes`, not `Submit`
|
|
45
|
-
- A payment form ends with `Pay $29.00`, not `Continue`
|
|
46
|
-
- A search form ends with `Search Flights`, not `Go`
|
|
47
|
-
|
|
48
|
-
DON'T: Use the same label on two buttons in the same dialog unless their actions are identical.
|
|
49
|
-
|
|
50
|
-
**Disabled states:** When a button is disabled, a nearby hint should explain why. "Save Changes (fill in required fields first)" is more useful than a greyed-out button with no explanation.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Error Messages
|
|
55
|
-
|
|
56
|
-
Error messages are moments of failure — but they don't have to feel like failure. The formula is three parts:
|
|
57
|
-
|
|
58
|
-
1. **What went wrong** — one plain sentence, no jargon
|
|
59
|
-
2. **Why it happened** — context that helps the user understand, not blame
|
|
60
|
-
3. **How to fix it** — a concrete, actionable next step
|
|
61
|
-
|
|
62
|
-
**Examples:**
|
|
63
|
-
|
|
64
|
-
Validation error:
|
|
65
|
-
```
|
|
66
|
-
Your password is too short.
|
|
67
|
-
Passwords must be at least 8 characters.
|
|
68
|
-
Add more characters and try again.
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Network error:
|
|
72
|
-
```
|
|
73
|
-
We couldn't save your changes.
|
|
74
|
-
Your connection dropped while saving.
|
|
75
|
-
Check your internet connection and click Save again.
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Permission error:
|
|
79
|
-
```
|
|
80
|
-
You can't delete this project.
|
|
81
|
-
Only the project owner can delete it.
|
|
82
|
-
Contact the owner or ask them to transfer ownership to you.
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**DO / DON'T**
|
|
86
|
-
|
|
87
|
-
DO: Use plain language. Avoid codes, stack traces, or internal terminology in user-facing messages.
|
|
88
|
-
```
|
|
89
|
-
// Good
|
|
90
|
-
"That email address is already in use. Sign in instead, or use a different email."
|
|
91
|
-
|
|
92
|
-
// Bad
|
|
93
|
-
"Error 409: Unique constraint violation on users.email"
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
DON'T: Blame the user. Passive or neutral framing is almost always better.
|
|
97
|
-
```
|
|
98
|
-
// Blaming
|
|
99
|
-
"You entered an invalid date."
|
|
100
|
-
|
|
101
|
-
// Neutral
|
|
102
|
-
"That date doesn't match our format. Use MM/DD/YYYY — for example, 03/31/2026."
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
DO: Keep error messages close to the problem. Inline field validation errors should appear next to the field, not in a modal.
|
|
106
|
-
|
|
107
|
-
DON'T: Use vague apologies as a substitute for explanation.
|
|
108
|
-
```
|
|
109
|
-
// Vague
|
|
110
|
-
"Something went wrong. Please try again."
|
|
111
|
-
|
|
112
|
-
// Informative
|
|
113
|
-
"Your file couldn't upload. Files must be under 10 MB. This file is 14 MB."
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
DO: For recoverable errors, include a recovery action in or near the message.
|
|
117
|
-
```html
|
|
118
|
-
<div class="error-message" role="alert">
|
|
119
|
-
<p>Session expired. Your changes weren't saved.</p>
|
|
120
|
-
<button onclick="restoreSession()">Restore session</button>
|
|
121
|
-
</div>
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Empty States
|
|
127
|
-
|
|
128
|
-
An empty state is not just the absence of content — it is an opportunity to orient the user and motivate action. Every empty state needs two things: an explanation of why it's empty, and a clear path forward.
|
|
129
|
-
|
|
130
|
-
**Structure:**
|
|
131
|
-
|
|
132
|
-
1. A heading that describes the situation (not "No items found")
|
|
133
|
-
2. One or two sentences of context
|
|
134
|
-
3. A primary CTA that starts the relevant action
|
|
135
|
-
|
|
136
|
-
**Examples:**
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
No projects yet
|
|
140
|
-
Projects you create or join will appear here.
|
|
141
|
-
[Create your first project]
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
Your inbox is empty
|
|
146
|
-
You're all caught up! New messages from teammates will show up here.
|
|
147
|
-
[Browse channels]
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
No results for "darkmode settings"
|
|
152
|
-
Try searching for "appearance" or "theme" instead.
|
|
153
|
-
[Clear search]
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
**DO / DON'T**
|
|
157
|
-
|
|
158
|
-
DO: Write empty state headings from the user's perspective, not the system's.
|
|
159
|
-
```
|
|
160
|
-
// System-centric (avoid)
|
|
161
|
-
"No records exist"
|
|
162
|
-
|
|
163
|
-
// User-centric (prefer)
|
|
164
|
-
"You haven't added any contacts yet"
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
DON'T: Leave empty states with just an icon and no text. Icons alone don't explain context or provide direction.
|
|
168
|
-
|
|
169
|
-
DO: Tailor CTAs to the specific empty state. The CTA for an empty contacts list should open a "Add Contact" form, not a generic "Get Started" page.
|
|
170
|
-
|
|
171
|
-
DON'T: Use the same empty state copy for every list or table in the application. Each surface has a different context.
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## Confirmation Dialogs
|
|
176
|
-
|
|
177
|
-
Confirmation dialogs interrupt the user to verify intent before a significant action. The copy must be specific enough that the user understands exactly what they are confirming — and the buttons must make the choice unambiguous.
|
|
178
|
-
|
|
179
|
-
**Button rule: use action verbs, never Yes/No/OK.**
|
|
180
|
-
|
|
181
|
-
| Weak | Strong |
|
|
182
|
-
|------|--------|
|
|
183
|
-
| Yes / No | Delete / Keep |
|
|
184
|
-
| OK / Cancel | Remove Member / Keep Member |
|
|
185
|
-
| Confirm / Cancel | Archive Project / Go Back |
|
|
186
|
-
| Yes / Cancel | Log Out / Stay Signed In |
|
|
187
|
-
|
|
188
|
-
**Dialog structure:**
|
|
189
|
-
|
|
190
|
-
- **Title:** State the action, not a question. "Delete this project?" not "Are you sure?"
|
|
191
|
-
- **Body:** Describe consequences. What will be lost? Is it reversible?
|
|
192
|
-
- **Primary button:** Destructive action in destructive styling
|
|
193
|
-
- **Secondary button:** Safe exit, using specific language
|
|
194
|
-
|
|
195
|
-
```html
|
|
196
|
-
<dialog aria-labelledby="dialog-title" aria-describedby="dialog-desc">
|
|
197
|
-
<h2 id="dialog-title">Delete "Q1 Campaign"?</h2>
|
|
198
|
-
<p id="dialog-desc">
|
|
199
|
-
This will permanently delete the project and all 14 assets inside it.
|
|
200
|
-
This action cannot be undone.
|
|
201
|
-
</p>
|
|
202
|
-
<div class="dialog-actions">
|
|
203
|
-
<button class="btn-secondary">Keep Project</button>
|
|
204
|
-
<button class="btn-danger">Delete Project</button>
|
|
205
|
-
</div>
|
|
206
|
-
</dialog>
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
**DO / DON'T**
|
|
210
|
-
|
|
211
|
-
DO: Be specific about what is being deleted/changed/sent. "Delete 14 files" is clearer than "Delete selected items."
|
|
212
|
-
|
|
213
|
-
DON'T: Use "Are you sure?" as the dialog title. It adds no information the user doesn't already have.
|
|
214
|
-
|
|
215
|
-
DO: Place the safe option (cancel/keep) before the destructive option in reading order. This reduces accidental confirmations.
|
|
216
|
-
|
|
217
|
-
DON'T: Use identical styling for both buttons. The destructive action should be visually distinct — typically a danger/red variant.
|
|
218
|
-
|
|
219
|
-
---
|
|
220
|
-
|
|
221
|
-
## Voice vs Tone
|
|
222
|
-
|
|
223
|
-
**Voice** is permanent. It is the brand's personality — the consistent character that shows up in every piece of copy regardless of context. Define it with three to five adjectives and concrete examples.
|
|
224
|
-
|
|
225
|
-
Example voice definition:
|
|
226
|
-
```
|
|
227
|
-
Direct: We say what we mean without filler. "Save" not "Go ahead and save your progress."
|
|
228
|
-
Warm: We write to people, not at them. "You're all set" not "Operation successful."
|
|
229
|
-
Clear: We prefer plain words over jargon. "Connected" not "Authenticated."
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
**Tone** is situational. The same brand voice adapts its tone to match the emotional context:
|
|
233
|
-
|
|
234
|
-
| Situation | Tone Adjustment | Example |
|
|
235
|
-
|-----------|-----------------|---------|
|
|
236
|
-
| Success | Warm, celebratory | "Payment received. See you on the other side." |
|
|
237
|
-
| Error | Calm, solution-focused | "That didn't work. Here's what to try next." |
|
|
238
|
-
| Onboarding | Encouraging, guiding | "Let's set up your workspace — takes about 2 minutes." |
|
|
239
|
-
| Warning | Direct, informative | "You're about to replace 12 files. This can't be undone." |
|
|
240
|
-
| Deletion | Neutral, factual | "This project has been deleted." |
|
|
241
|
-
|
|
242
|
-
**DO / DON'T**
|
|
243
|
-
|
|
244
|
-
DO: Write a voice chart and share it with every contributor who writes UI copy.
|
|
245
|
-
|
|
246
|
-
DON'T: Let tone bleed into the wrong context. Humor and celebration are wrong for error states. Formality is wrong for success toasts.
|
|
247
|
-
|
|
248
|
-
DO: Treat success messages and error messages as different tonal registers, not just different content.
|
|
249
|
-
|
|
250
|
-
DON'T: Confuse personality with friendliness. A brand can be serious and still have a consistent, recognizable voice.
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## Translation Expansion
|
|
255
|
-
|
|
256
|
-
UI copy expands and contracts in translation. Ignoring this creates broken layouts in other languages.
|
|
257
|
-
|
|
258
|
-
**Expansion rules of thumb:**
|
|
259
|
-
|
|
260
|
-
| Language | Change vs English |
|
|
261
|
-
|----------|-------------------|
|
|
262
|
-
| German | +30% to +40% |
|
|
263
|
-
| French | +20% to +30% |
|
|
264
|
-
| Spanish | +20% to +30% |
|
|
265
|
-
| Russian | +20% to +30% |
|
|
266
|
-
| Japanese | -10% to -30% |
|
|
267
|
-
| Chinese (Simplified) | -20% to -30% |
|
|
268
|
-
| Korean | -10% to -20% |
|
|
269
|
-
|
|
270
|
-
"Save Changes" in English becomes "Änderungen speichern" in German — 30% longer. Design for the expansion, not the English string.
|
|
271
|
-
|
|
272
|
-
**Layout patterns that handle i18n gracefully:**
|
|
273
|
-
|
|
274
|
-
```css
|
|
275
|
-
/* Avoid fixed-width buttons — they clip translated text */
|
|
276
|
-
.btn {
|
|
277
|
-
/* Bad */
|
|
278
|
-
width: 120px;
|
|
279
|
-
|
|
280
|
-
/* Good */
|
|
281
|
-
min-width: 120px;
|
|
282
|
-
padding: 0.5rem 1.25rem;
|
|
283
|
-
width: auto;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/* Avoid fixed-height containers for label + description combos */
|
|
287
|
-
.form-field-label {
|
|
288
|
-
/* Bad */
|
|
289
|
-
height: 1.5rem;
|
|
290
|
-
overflow: hidden;
|
|
291
|
-
|
|
292
|
-
/* Good */
|
|
293
|
-
min-height: 1.5rem;
|
|
294
|
-
height: auto;
|
|
295
|
-
}
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
**DO / DON'T**
|
|
299
|
-
|
|
300
|
-
DO: Design with German text as a stress test for button and label widths.
|
|
301
|
-
|
|
302
|
-
DON'T: concatenate translated strings to build sentences. Word order differs across languages, and concatenation breaks in many of them.
|
|
303
|
-
```javascript
|
|
304
|
-
// Bad — word order is language-specific
|
|
305
|
-
const label = t('delete') + ' ' + itemName;
|
|
306
|
-
|
|
307
|
-
// Good — pass variables into a full translated string
|
|
308
|
-
const label = t('delete_item', { name: itemName });
|
|
309
|
-
// en: "Delete Project Alpha"
|
|
310
|
-
// de: "Projekt Alpha löschen"
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
DO: Use a translation key system that supports plurals and variable interpolation natively (ICU message format or equivalent).
|
|
314
|
-
|
|
315
|
-
DON'T: hard-code units, currency symbols, or date separators alongside translated strings. Treat these as formatting concerns, not translation concerns.
|
|
316
|
-
|
|
317
|
-
---
|
|
318
|
-
|
|
319
|
-
## Microcopy
|
|
320
|
-
|
|
321
|
-
Microcopy covers the small, functional copy that guides users through forms and interactions: tooltips, placeholders, help text, validation hints, and loading messages.
|
|
322
|
-
|
|
323
|
-
**Tooltips:**
|
|
324
|
-
- Appear on hover or focus for icon-only controls
|
|
325
|
-
- One sentence maximum
|
|
326
|
-
- Describe what the button does, not what it is
|
|
327
|
-
```html
|
|
328
|
-
<!-- Icon button with tooltip -->
|
|
329
|
-
<button aria-label="Share document" data-tooltip="Share a link to this document">
|
|
330
|
-
<Icon name="share" />
|
|
331
|
-
</button>
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
**Placeholders:**
|
|
335
|
-
- Show example input, not instructions
|
|
336
|
-
- Never use placeholders as a substitute for labels — they disappear on focus
|
|
337
|
-
```html
|
|
338
|
-
<!-- Bad: instruction as placeholder -->
|
|
339
|
-
<input placeholder="Enter your email address" />
|
|
340
|
-
|
|
341
|
-
<!-- Good: example as placeholder, label above -->
|
|
342
|
-
<label for="email">Email</label>
|
|
343
|
-
<input id="email" placeholder="name@example.com" />
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
**Help text:**
|
|
347
|
-
- Place below the input, above the error zone
|
|
348
|
-
- Explain constraints the user needs before they start typing, not after they fail
|
|
349
|
-
```html
|
|
350
|
-
<label for="username">Username</label>
|
|
351
|
-
<input id="username" aria-describedby="username-hint" />
|
|
352
|
-
<p id="username-hint" class="field-hint">
|
|
353
|
-
3–20 characters. Letters, numbers, and underscores only.
|
|
354
|
-
</p>
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
**Loading messages:**
|
|
358
|
-
- Progress over time: vary the message if loading takes more than 3 seconds
|
|
359
|
-
- Avoid "Loading..." alone — describe what is loading
|
|
360
|
-
```javascript
|
|
361
|
-
const loadingMessages = [
|
|
362
|
-
'Loading your projects...',
|
|
363
|
-
'Almost there...',
|
|
364
|
-
'This is taking longer than usual — still working...',
|
|
365
|
-
];
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
**DO / DON'T**
|
|
369
|
-
|
|
370
|
-
DO: Write help text before the fact (constraints), not after (error explanation). "Must be at least 8 characters" belongs in help text, not only in an error message.
|
|
371
|
-
|
|
372
|
-
DON'T: use placeholder text as the only label for a form field. It fails accessibility requirements and disappears as soon as the user starts typing.
|
|
373
|
-
|
|
374
|
-
---
|
|
375
|
-
|
|
376
|
-
## Number and Date Formatting
|
|
377
|
-
|
|
378
|
-
Hard-coded number and date formats break in other locales. The `Intl` API handles locale-aware formatting without manual string construction.
|
|
379
|
-
|
|
380
|
-
**Numbers:**
|
|
381
|
-
|
|
382
|
-
```javascript
|
|
383
|
-
// Currency
|
|
384
|
-
const price = new Intl.NumberFormat('en-US', {
|
|
385
|
-
style: 'currency',
|
|
386
|
-
currency: 'USD',
|
|
387
|
-
}).format(1299.99);
|
|
388
|
-
// → "$1,299.99"
|
|
389
|
-
|
|
390
|
-
const priceDE = new Intl.NumberFormat('de-DE', {
|
|
391
|
-
style: 'currency',
|
|
392
|
-
currency: 'EUR',
|
|
393
|
-
}).format(1299.99);
|
|
394
|
-
// → "1.299,99 €"
|
|
395
|
-
|
|
396
|
-
// Large numbers with grouping
|
|
397
|
-
const count = new Intl.NumberFormat('en-US').format(1000000);
|
|
398
|
-
// → "1,000,000"
|
|
399
|
-
|
|
400
|
-
// Compact notation for space-constrained UI
|
|
401
|
-
const compact = new Intl.NumberFormat('en-US', {
|
|
402
|
-
notation: 'compact',
|
|
403
|
-
maximumFractionDigits: 1,
|
|
404
|
-
}).format(14500);
|
|
405
|
-
// → "14.5K"
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
**Dates:**
|
|
409
|
-
|
|
410
|
-
```javascript
|
|
411
|
-
const date = new Date('2026-03-31');
|
|
412
|
-
|
|
413
|
-
// Full date, locale-aware
|
|
414
|
-
const fullDate = new Intl.DateTimeFormat('en-US', {
|
|
415
|
-
year: 'numeric',
|
|
416
|
-
month: 'long',
|
|
417
|
-
day: 'numeric',
|
|
418
|
-
}).format(date);
|
|
419
|
-
// → "March 31, 2026"
|
|
420
|
-
|
|
421
|
-
// Short format for tables
|
|
422
|
-
const shortDate = new Intl.DateTimeFormat('en-US', {
|
|
423
|
-
month: 'short',
|
|
424
|
-
day: 'numeric',
|
|
425
|
-
}).format(date);
|
|
426
|
-
// → "Mar 31"
|
|
427
|
-
|
|
428
|
-
// Relative time (use with a wrapper)
|
|
429
|
-
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
|
|
430
|
-
rtf.format(-1, 'day'); // → "yesterday"
|
|
431
|
-
rtf.format(-3, 'day'); // → "3 days ago"
|
|
432
|
-
rtf.format(1, 'week'); // → "next week"
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
**DO / DON'T**
|
|
436
|
-
|
|
437
|
-
DO: Accept locale as a parameter derived from the user's browser or account settings. Never hard-code `'en-US'` throughout the codebase.
|
|
438
|
-
```javascript
|
|
439
|
-
function formatCurrency(amount: number, locale: string, currency: string): string {
|
|
440
|
-
return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);
|
|
441
|
-
}
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
DON'T: Build date strings by manually concatenating month names and separators.
|
|
445
|
-
```javascript
|
|
446
|
-
// Bad — breaks in non-English locales, fragile
|
|
447
|
-
const label = `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
|
|
448
|
-
|
|
449
|
-
// Good — locale-aware, handles all edge cases
|
|
450
|
-
const label = new Intl.DateTimeFormat(userLocale, { dateStyle: 'long' }).format(date);
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
DO: Use ISO 8601 (`YYYY-MM-DD`) for data storage and API payloads. Reserve `Intl` formatting for display only.
|
|
454
|
-
|
|
455
|
-
DON'T: assume 12-hour clock. Many locales default to 24-hour. Let `Intl.DateTimeFormat` resolve clock format from locale rather than forcing `hour12: true`.
|
|
456
|
-
|
|
457
|
-
```javascript
|
|
458
|
-
// Locale-appropriate clock format
|
|
459
|
-
const time = new Intl.DateTimeFormat(userLocale, {
|
|
460
|
-
hour: 'numeric',
|
|
461
|
-
minute: '2-digit',
|
|
462
|
-
}).format(new Date());
|
|
463
|
-
// en-US → "2:45 PM"
|
|
464
|
-
// de-DE → "14:45"
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
*Last updated: 2026-03. Maintained as part of the ui-ux-pro-max skill package.*
|
|
1
|
+
# UX Writing Reference Guide
|
|
2
|
+
|
|
3
|
+
Practical patterns for writing UI copy that reduces friction, builds trust, and works across languages and contexts.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Button Labels
|
|
8
|
+
|
|
9
|
+
Buttons are the primary call-to-action in any interface. Weak labels create hesitation; strong labels create momentum.
|
|
10
|
+
|
|
11
|
+
**The pattern: verb + object.** Tell users exactly what will happen when they click.
|
|
12
|
+
|
|
13
|
+
| Weak | Strong |
|
|
14
|
+
|------|--------|
|
|
15
|
+
| Submit | Save Profile |
|
|
16
|
+
| OK | Confirm Booking |
|
|
17
|
+
| Yes | Delete Account |
|
|
18
|
+
| Update | Change Password |
|
|
19
|
+
| Continue | Go to Checkout |
|
|
20
|
+
|
|
21
|
+
The verb signals the action type. The object anchors it to the current context. Together they eliminate ambiguity.
|
|
22
|
+
|
|
23
|
+
**DO / DON'T**
|
|
24
|
+
|
|
25
|
+
DO: Match the button label to the consequence.
|
|
26
|
+
```html
|
|
27
|
+
<!-- Destructive action: label mirrors the destruction -->
|
|
28
|
+
<button class="btn-danger">Delete Project</button>
|
|
29
|
+
|
|
30
|
+
<!-- Constructive action: label mirrors the creation -->
|
|
31
|
+
<button class="btn-primary">Create Project</button>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
DON'T: Use generic labels that could mean anything.
|
|
35
|
+
```html
|
|
36
|
+
<!-- "OK" — OK to what? OK means nothing. -->
|
|
37
|
+
<button>OK</button>
|
|
38
|
+
|
|
39
|
+
<!-- "Submit" — submit what? to where? -->
|
|
40
|
+
<button>Submit</button>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
DO: Reflect form field context in the CTA.
|
|
44
|
+
- A profile editing form ends with `Save Changes`, not `Submit`
|
|
45
|
+
- A payment form ends with `Pay $29.00`, not `Continue`
|
|
46
|
+
- A search form ends with `Search Flights`, not `Go`
|
|
47
|
+
|
|
48
|
+
DON'T: Use the same label on two buttons in the same dialog unless their actions are identical.
|
|
49
|
+
|
|
50
|
+
**Disabled states:** When a button is disabled, a nearby hint should explain why. "Save Changes (fill in required fields first)" is more useful than a greyed-out button with no explanation.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Error Messages
|
|
55
|
+
|
|
56
|
+
Error messages are moments of failure — but they don't have to feel like failure. The formula is three parts:
|
|
57
|
+
|
|
58
|
+
1. **What went wrong** — one plain sentence, no jargon
|
|
59
|
+
2. **Why it happened** — context that helps the user understand, not blame
|
|
60
|
+
3. **How to fix it** — a concrete, actionable next step
|
|
61
|
+
|
|
62
|
+
**Examples:**
|
|
63
|
+
|
|
64
|
+
Validation error:
|
|
65
|
+
```
|
|
66
|
+
Your password is too short.
|
|
67
|
+
Passwords must be at least 8 characters.
|
|
68
|
+
Add more characters and try again.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Network error:
|
|
72
|
+
```
|
|
73
|
+
We couldn't save your changes.
|
|
74
|
+
Your connection dropped while saving.
|
|
75
|
+
Check your internet connection and click Save again.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Permission error:
|
|
79
|
+
```
|
|
80
|
+
You can't delete this project.
|
|
81
|
+
Only the project owner can delete it.
|
|
82
|
+
Contact the owner or ask them to transfer ownership to you.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**DO / DON'T**
|
|
86
|
+
|
|
87
|
+
DO: Use plain language. Avoid codes, stack traces, or internal terminology in user-facing messages.
|
|
88
|
+
```
|
|
89
|
+
// Good
|
|
90
|
+
"That email address is already in use. Sign in instead, or use a different email."
|
|
91
|
+
|
|
92
|
+
// Bad
|
|
93
|
+
"Error 409: Unique constraint violation on users.email"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
DON'T: Blame the user. Passive or neutral framing is almost always better.
|
|
97
|
+
```
|
|
98
|
+
// Blaming
|
|
99
|
+
"You entered an invalid date."
|
|
100
|
+
|
|
101
|
+
// Neutral
|
|
102
|
+
"That date doesn't match our format. Use MM/DD/YYYY — for example, 03/31/2026."
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
DO: Keep error messages close to the problem. Inline field validation errors should appear next to the field, not in a modal.
|
|
106
|
+
|
|
107
|
+
DON'T: Use vague apologies as a substitute for explanation.
|
|
108
|
+
```
|
|
109
|
+
// Vague
|
|
110
|
+
"Something went wrong. Please try again."
|
|
111
|
+
|
|
112
|
+
// Informative
|
|
113
|
+
"Your file couldn't upload. Files must be under 10 MB. This file is 14 MB."
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
DO: For recoverable errors, include a recovery action in or near the message.
|
|
117
|
+
```html
|
|
118
|
+
<div class="error-message" role="alert">
|
|
119
|
+
<p>Session expired. Your changes weren't saved.</p>
|
|
120
|
+
<button onclick="restoreSession()">Restore session</button>
|
|
121
|
+
</div>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Empty States
|
|
127
|
+
|
|
128
|
+
An empty state is not just the absence of content — it is an opportunity to orient the user and motivate action. Every empty state needs two things: an explanation of why it's empty, and a clear path forward.
|
|
129
|
+
|
|
130
|
+
**Structure:**
|
|
131
|
+
|
|
132
|
+
1. A heading that describes the situation (not "No items found")
|
|
133
|
+
2. One or two sentences of context
|
|
134
|
+
3. A primary CTA that starts the relevant action
|
|
135
|
+
|
|
136
|
+
**Examples:**
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
No projects yet
|
|
140
|
+
Projects you create or join will appear here.
|
|
141
|
+
[Create your first project]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Your inbox is empty
|
|
146
|
+
You're all caught up! New messages from teammates will show up here.
|
|
147
|
+
[Browse channels]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
No results for "darkmode settings"
|
|
152
|
+
Try searching for "appearance" or "theme" instead.
|
|
153
|
+
[Clear search]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**DO / DON'T**
|
|
157
|
+
|
|
158
|
+
DO: Write empty state headings from the user's perspective, not the system's.
|
|
159
|
+
```
|
|
160
|
+
// System-centric (avoid)
|
|
161
|
+
"No records exist"
|
|
162
|
+
|
|
163
|
+
// User-centric (prefer)
|
|
164
|
+
"You haven't added any contacts yet"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
DON'T: Leave empty states with just an icon and no text. Icons alone don't explain context or provide direction.
|
|
168
|
+
|
|
169
|
+
DO: Tailor CTAs to the specific empty state. The CTA for an empty contacts list should open a "Add Contact" form, not a generic "Get Started" page.
|
|
170
|
+
|
|
171
|
+
DON'T: Use the same empty state copy for every list or table in the application. Each surface has a different context.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Confirmation Dialogs
|
|
176
|
+
|
|
177
|
+
Confirmation dialogs interrupt the user to verify intent before a significant action. The copy must be specific enough that the user understands exactly what they are confirming — and the buttons must make the choice unambiguous.
|
|
178
|
+
|
|
179
|
+
**Button rule: use action verbs, never Yes/No/OK.**
|
|
180
|
+
|
|
181
|
+
| Weak | Strong |
|
|
182
|
+
|------|--------|
|
|
183
|
+
| Yes / No | Delete / Keep |
|
|
184
|
+
| OK / Cancel | Remove Member / Keep Member |
|
|
185
|
+
| Confirm / Cancel | Archive Project / Go Back |
|
|
186
|
+
| Yes / Cancel | Log Out / Stay Signed In |
|
|
187
|
+
|
|
188
|
+
**Dialog structure:**
|
|
189
|
+
|
|
190
|
+
- **Title:** State the action, not a question. "Delete this project?" not "Are you sure?"
|
|
191
|
+
- **Body:** Describe consequences. What will be lost? Is it reversible?
|
|
192
|
+
- **Primary button:** Destructive action in destructive styling
|
|
193
|
+
- **Secondary button:** Safe exit, using specific language
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<dialog aria-labelledby="dialog-title" aria-describedby="dialog-desc">
|
|
197
|
+
<h2 id="dialog-title">Delete "Q1 Campaign"?</h2>
|
|
198
|
+
<p id="dialog-desc">
|
|
199
|
+
This will permanently delete the project and all 14 assets inside it.
|
|
200
|
+
This action cannot be undone.
|
|
201
|
+
</p>
|
|
202
|
+
<div class="dialog-actions">
|
|
203
|
+
<button class="btn-secondary">Keep Project</button>
|
|
204
|
+
<button class="btn-danger">Delete Project</button>
|
|
205
|
+
</div>
|
|
206
|
+
</dialog>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**DO / DON'T**
|
|
210
|
+
|
|
211
|
+
DO: Be specific about what is being deleted/changed/sent. "Delete 14 files" is clearer than "Delete selected items."
|
|
212
|
+
|
|
213
|
+
DON'T: Use "Are you sure?" as the dialog title. It adds no information the user doesn't already have.
|
|
214
|
+
|
|
215
|
+
DO: Place the safe option (cancel/keep) before the destructive option in reading order. This reduces accidental confirmations.
|
|
216
|
+
|
|
217
|
+
DON'T: Use identical styling for both buttons. The destructive action should be visually distinct — typically a danger/red variant.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Voice vs Tone
|
|
222
|
+
|
|
223
|
+
**Voice** is permanent. It is the brand's personality — the consistent character that shows up in every piece of copy regardless of context. Define it with three to five adjectives and concrete examples.
|
|
224
|
+
|
|
225
|
+
Example voice definition:
|
|
226
|
+
```
|
|
227
|
+
Direct: We say what we mean without filler. "Save" not "Go ahead and save your progress."
|
|
228
|
+
Warm: We write to people, not at them. "You're all set" not "Operation successful."
|
|
229
|
+
Clear: We prefer plain words over jargon. "Connected" not "Authenticated."
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Tone** is situational. The same brand voice adapts its tone to match the emotional context:
|
|
233
|
+
|
|
234
|
+
| Situation | Tone Adjustment | Example |
|
|
235
|
+
|-----------|-----------------|---------|
|
|
236
|
+
| Success | Warm, celebratory | "Payment received. See you on the other side." |
|
|
237
|
+
| Error | Calm, solution-focused | "That didn't work. Here's what to try next." |
|
|
238
|
+
| Onboarding | Encouraging, guiding | "Let's set up your workspace — takes about 2 minutes." |
|
|
239
|
+
| Warning | Direct, informative | "You're about to replace 12 files. This can't be undone." |
|
|
240
|
+
| Deletion | Neutral, factual | "This project has been deleted." |
|
|
241
|
+
|
|
242
|
+
**DO / DON'T**
|
|
243
|
+
|
|
244
|
+
DO: Write a voice chart and share it with every contributor who writes UI copy.
|
|
245
|
+
|
|
246
|
+
DON'T: Let tone bleed into the wrong context. Humor and celebration are wrong for error states. Formality is wrong for success toasts.
|
|
247
|
+
|
|
248
|
+
DO: Treat success messages and error messages as different tonal registers, not just different content.
|
|
249
|
+
|
|
250
|
+
DON'T: Confuse personality with friendliness. A brand can be serious and still have a consistent, recognizable voice.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Translation Expansion
|
|
255
|
+
|
|
256
|
+
UI copy expands and contracts in translation. Ignoring this creates broken layouts in other languages.
|
|
257
|
+
|
|
258
|
+
**Expansion rules of thumb:**
|
|
259
|
+
|
|
260
|
+
| Language | Change vs English |
|
|
261
|
+
|----------|-------------------|
|
|
262
|
+
| German | +30% to +40% |
|
|
263
|
+
| French | +20% to +30% |
|
|
264
|
+
| Spanish | +20% to +30% |
|
|
265
|
+
| Russian | +20% to +30% |
|
|
266
|
+
| Japanese | -10% to -30% |
|
|
267
|
+
| Chinese (Simplified) | -20% to -30% |
|
|
268
|
+
| Korean | -10% to -20% |
|
|
269
|
+
|
|
270
|
+
"Save Changes" in English becomes "Änderungen speichern" in German — 30% longer. Design for the expansion, not the English string.
|
|
271
|
+
|
|
272
|
+
**Layout patterns that handle i18n gracefully:**
|
|
273
|
+
|
|
274
|
+
```css
|
|
275
|
+
/* Avoid fixed-width buttons — they clip translated text */
|
|
276
|
+
.btn {
|
|
277
|
+
/* Bad */
|
|
278
|
+
width: 120px;
|
|
279
|
+
|
|
280
|
+
/* Good */
|
|
281
|
+
min-width: 120px;
|
|
282
|
+
padding: 0.5rem 1.25rem;
|
|
283
|
+
width: auto;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Avoid fixed-height containers for label + description combos */
|
|
287
|
+
.form-field-label {
|
|
288
|
+
/* Bad */
|
|
289
|
+
height: 1.5rem;
|
|
290
|
+
overflow: hidden;
|
|
291
|
+
|
|
292
|
+
/* Good */
|
|
293
|
+
min-height: 1.5rem;
|
|
294
|
+
height: auto;
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**DO / DON'T**
|
|
299
|
+
|
|
300
|
+
DO: Design with German text as a stress test for button and label widths.
|
|
301
|
+
|
|
302
|
+
DON'T: concatenate translated strings to build sentences. Word order differs across languages, and concatenation breaks in many of them.
|
|
303
|
+
```javascript
|
|
304
|
+
// Bad — word order is language-specific
|
|
305
|
+
const label = t('delete') + ' ' + itemName;
|
|
306
|
+
|
|
307
|
+
// Good — pass variables into a full translated string
|
|
308
|
+
const label = t('delete_item', { name: itemName });
|
|
309
|
+
// en: "Delete Project Alpha"
|
|
310
|
+
// de: "Projekt Alpha löschen"
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
DO: Use a translation key system that supports plurals and variable interpolation natively (ICU message format or equivalent).
|
|
314
|
+
|
|
315
|
+
DON'T: hard-code units, currency symbols, or date separators alongside translated strings. Treat these as formatting concerns, not translation concerns.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Microcopy
|
|
320
|
+
|
|
321
|
+
Microcopy covers the small, functional copy that guides users through forms and interactions: tooltips, placeholders, help text, validation hints, and loading messages.
|
|
322
|
+
|
|
323
|
+
**Tooltips:**
|
|
324
|
+
- Appear on hover or focus for icon-only controls
|
|
325
|
+
- One sentence maximum
|
|
326
|
+
- Describe what the button does, not what it is
|
|
327
|
+
```html
|
|
328
|
+
<!-- Icon button with tooltip -->
|
|
329
|
+
<button aria-label="Share document" data-tooltip="Share a link to this document">
|
|
330
|
+
<Icon name="share" />
|
|
331
|
+
</button>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**Placeholders:**
|
|
335
|
+
- Show example input, not instructions
|
|
336
|
+
- Never use placeholders as a substitute for labels — they disappear on focus
|
|
337
|
+
```html
|
|
338
|
+
<!-- Bad: instruction as placeholder -->
|
|
339
|
+
<input placeholder="Enter your email address" />
|
|
340
|
+
|
|
341
|
+
<!-- Good: example as placeholder, label above -->
|
|
342
|
+
<label for="email">Email</label>
|
|
343
|
+
<input id="email" placeholder="name@example.com" />
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**Help text:**
|
|
347
|
+
- Place below the input, above the error zone
|
|
348
|
+
- Explain constraints the user needs before they start typing, not after they fail
|
|
349
|
+
```html
|
|
350
|
+
<label for="username">Username</label>
|
|
351
|
+
<input id="username" aria-describedby="username-hint" />
|
|
352
|
+
<p id="username-hint" class="field-hint">
|
|
353
|
+
3–20 characters. Letters, numbers, and underscores only.
|
|
354
|
+
</p>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**Loading messages:**
|
|
358
|
+
- Progress over time: vary the message if loading takes more than 3 seconds
|
|
359
|
+
- Avoid "Loading..." alone — describe what is loading
|
|
360
|
+
```javascript
|
|
361
|
+
const loadingMessages = [
|
|
362
|
+
'Loading your projects...',
|
|
363
|
+
'Almost there...',
|
|
364
|
+
'This is taking longer than usual — still working...',
|
|
365
|
+
];
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**DO / DON'T**
|
|
369
|
+
|
|
370
|
+
DO: Write help text before the fact (constraints), not after (error explanation). "Must be at least 8 characters" belongs in help text, not only in an error message.
|
|
371
|
+
|
|
372
|
+
DON'T: use placeholder text as the only label for a form field. It fails accessibility requirements and disappears as soon as the user starts typing.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Number and Date Formatting
|
|
377
|
+
|
|
378
|
+
Hard-coded number and date formats break in other locales. The `Intl` API handles locale-aware formatting without manual string construction.
|
|
379
|
+
|
|
380
|
+
**Numbers:**
|
|
381
|
+
|
|
382
|
+
```javascript
|
|
383
|
+
// Currency
|
|
384
|
+
const price = new Intl.NumberFormat('en-US', {
|
|
385
|
+
style: 'currency',
|
|
386
|
+
currency: 'USD',
|
|
387
|
+
}).format(1299.99);
|
|
388
|
+
// → "$1,299.99"
|
|
389
|
+
|
|
390
|
+
const priceDE = new Intl.NumberFormat('de-DE', {
|
|
391
|
+
style: 'currency',
|
|
392
|
+
currency: 'EUR',
|
|
393
|
+
}).format(1299.99);
|
|
394
|
+
// → "1.299,99 €"
|
|
395
|
+
|
|
396
|
+
// Large numbers with grouping
|
|
397
|
+
const count = new Intl.NumberFormat('en-US').format(1000000);
|
|
398
|
+
// → "1,000,000"
|
|
399
|
+
|
|
400
|
+
// Compact notation for space-constrained UI
|
|
401
|
+
const compact = new Intl.NumberFormat('en-US', {
|
|
402
|
+
notation: 'compact',
|
|
403
|
+
maximumFractionDigits: 1,
|
|
404
|
+
}).format(14500);
|
|
405
|
+
// → "14.5K"
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
**Dates:**
|
|
409
|
+
|
|
410
|
+
```javascript
|
|
411
|
+
const date = new Date('2026-03-31');
|
|
412
|
+
|
|
413
|
+
// Full date, locale-aware
|
|
414
|
+
const fullDate = new Intl.DateTimeFormat('en-US', {
|
|
415
|
+
year: 'numeric',
|
|
416
|
+
month: 'long',
|
|
417
|
+
day: 'numeric',
|
|
418
|
+
}).format(date);
|
|
419
|
+
// → "March 31, 2026"
|
|
420
|
+
|
|
421
|
+
// Short format for tables
|
|
422
|
+
const shortDate = new Intl.DateTimeFormat('en-US', {
|
|
423
|
+
month: 'short',
|
|
424
|
+
day: 'numeric',
|
|
425
|
+
}).format(date);
|
|
426
|
+
// → "Mar 31"
|
|
427
|
+
|
|
428
|
+
// Relative time (use with a wrapper)
|
|
429
|
+
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
|
|
430
|
+
rtf.format(-1, 'day'); // → "yesterday"
|
|
431
|
+
rtf.format(-3, 'day'); // → "3 days ago"
|
|
432
|
+
rtf.format(1, 'week'); // → "next week"
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**DO / DON'T**
|
|
436
|
+
|
|
437
|
+
DO: Accept locale as a parameter derived from the user's browser or account settings. Never hard-code `'en-US'` throughout the codebase.
|
|
438
|
+
```javascript
|
|
439
|
+
function formatCurrency(amount: number, locale: string, currency: string): string {
|
|
440
|
+
return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
DON'T: Build date strings by manually concatenating month names and separators.
|
|
445
|
+
```javascript
|
|
446
|
+
// Bad — breaks in non-English locales, fragile
|
|
447
|
+
const label = `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
|
|
448
|
+
|
|
449
|
+
// Good — locale-aware, handles all edge cases
|
|
450
|
+
const label = new Intl.DateTimeFormat(userLocale, { dateStyle: 'long' }).format(date);
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
DO: Use ISO 8601 (`YYYY-MM-DD`) for data storage and API payloads. Reserve `Intl` formatting for display only.
|
|
454
|
+
|
|
455
|
+
DON'T: assume 12-hour clock. Many locales default to 24-hour. Let `Intl.DateTimeFormat` resolve clock format from locale rather than forcing `hour12: true`.
|
|
456
|
+
|
|
457
|
+
```javascript
|
|
458
|
+
// Locale-appropriate clock format
|
|
459
|
+
const time = new Intl.DateTimeFormat(userLocale, {
|
|
460
|
+
hour: 'numeric',
|
|
461
|
+
minute: '2-digit',
|
|
462
|
+
}).format(new Date());
|
|
463
|
+
// en-US → "2:45 PM"
|
|
464
|
+
// de-DE → "14:45"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
*Last updated: 2026-03. Maintained as part of the ui-ux-pro-max skill package.*
|