diff --git a/site/AGENTS.md b/site/AGENTS.md index d89d2959c6..fe43e999b3 100644 --- a/site/AGENTS.md +++ b/site/AGENTS.md @@ -117,6 +117,15 @@ Debug logs and pprof dumps use the same job name and commit SHA convention. - For JSX boolean props that are `true`, use the shorthand form (``) instead of ``. The two are equivalent; the shorthand is the React convention and reduces noise. +- Use **sentence case** for user-facing UI labels: capitalize only the + first word and proper nouns (`Personal instructions`, `API key`), not + Title Case (`Personal Instructions`, `API Key`). Under + `src/pages/AgentsPage`, a Biome GritQL plugin + (`biome-rules/use-sentence-case-labels.grit`) enforces this for + `label`/`title`/`sectionLabel`/`aria-label` attributes and `label:`/ + `title:` object properties. It cannot see labels rendered as JSX text + or built from variables, so those still need a human eye. Add genuine + proper nouns to the allowlist in that file. - **Avoid unnecessary indirection.** Inline single-use module-level constants, single-use aliases, and one-line helpers that just return a single field at the call site. Do not create wrapper hooks that only diff --git a/site/biome-rules/use-sentence-case-labels.grit b/site/biome-rules/use-sentence-case-labels.grit new file mode 100644 index 0000000000..b87f1f6d06 --- /dev/null +++ b/site/biome-rules/use-sentence-case-labels.grit @@ -0,0 +1,35 @@ +// Enforce sentence case for user-facing UI labels. +// +// Flags Title Case in label-bearing JSX attributes (label, title, +// sectionLabel, aria-label) and object-property labels (label:, title:, +// sectionLabel:). Sentence case capitalizes only the first word and +// proper nouns: "Personal instructions", not "Personal Instructions". +// +// Heuristic: a space followed by a capitalized word ([A-Z][a-z]). This +// also catches acronym-prefixed Title Case like "MCP Servers". Genuine +// multi-word proper nouns (e.g. "VS Code") are false positives and must +// be added to the allowlist below. +// +// Diagnostic-only: Biome GritQL plugins cannot autofix yet. +language js + +or { + JsxAttribute(name = $name) as $node where { + $name <: r"^(?:label|title|sectionLabel|aria-label)$", + $node <: contains JsxString() as $value + }, + JsPropertyObjectMember() as $node where { + $node <: contains JsLiteralMemberName() as $key, + $key <: r"^(?:label|title|sectionLabel)$", + $node <: contains JsStringLiteralExpression() as $value + } +} where { + $value <: r".* [A-Z][a-z].*", + // Allowlist: proper nouns / product names that are correctly multi-cap. + not $value <: r".*(?:VS Code|Coder Agents|GitHub Actions|JetBrains Fleet|Cmd/Ctrl).*", + register_diagnostic( + span = $value, + message = "Use sentence case for UI labels (e.g. \"Personal instructions\"), not Title Case. If this is a proper noun, add it to the allowlist in use-sentence-case-labels.grit.", + severity = "warn" + ) +} diff --git a/site/biome.jsonc b/site/biome.jsonc index 1721a0853c..6df5385abe 100644 --- a/site/biome.jsonc +++ b/site/biome.jsonc @@ -3,5 +3,16 @@ "files": { "includes": ["!e2e/**/*Generated.ts", "!scripts/*.mjs"] }, + "overrides": [ + { + "includes": [ + "src/pages/AgentsPage/**/*.ts", + "src/pages/AgentsPage/**/*.tsx", + "!**/*.stories.tsx", + "!**/*.test.tsx" + ], + "plugins": ["./biome-rules/use-sentence-case-labels.grit"] + } + ], "$schema": "./node_modules/@biomejs/biome/configuration_schema.json" } diff --git a/site/src/pages/AgentsPage/components/ChatModelAdminPanel/ProviderForm.tsx b/site/src/pages/AgentsPage/components/ChatModelAdminPanel/ProviderForm.tsx index fe817705f7..49678327ed 100644 --- a/site/src/pages/AgentsPage/components/ChatModelAdminPanel/ProviderForm.tsx +++ b/site/src/pages/AgentsPage/components/ChatModelAdminPanel/ProviderForm.tsx @@ -256,7 +256,7 @@ export const ProviderForm: FC = ({ >
= ({ disabled={isDisabled} /> - +