From 28cb1bc554e7fc64e3d396d8f643022ad26d8dbc Mon Sep 17 00:00:00 2001 From: LukeGus Date: Wed, 21 Oct 2026 10:44:53 -0500 Subject: [PATCH] feat: make all buttons brand orange and lint against white ones --- package.json | 2 +- scripts/check-button-colors.cjs | 111 ++++++++++++++++++++++++++++ scripts/check-button-colors.test.ts | 80 ++++++++++++++++++++ src/ui/components/button.tsx | 9 ++- 4 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 scripts/check-button-colors.cjs create mode 100644 scripts/check-button-colors.test.ts diff --git a/package.json b/package.json index f35640404..1cf5909b0 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "postinstall": "node scripts/patch-app-builder-lib.cjs && node scripts/patch-better-sqlite3.cjs && node scripts/patch-nan.cjs && node scripts/patch-node-pty.cjs && node scripts/patch-ssh2-agent.cjs && node scripts/patch-ssh2-sk.cjs", "prepare": "husky || true", "prebuild": "node scripts/write-electron-build-info.cjs", - "lint": "node scripts/generate-dialect-schema.cjs --check && eslint . && node scripts/check-importmap-csp.cjs && node scripts/check-core-plugin-ids.cjs && node scripts/check-sdk-ui-exports.cjs && node scripts/check-sdk-guide.cjs && node scripts/check-test-locations.cjs && node scripts/check-changelog.cjs && node scripts/check-env-catalog.cjs", + "lint": "node scripts/generate-dialect-schema.cjs --check && eslint . && node scripts/check-importmap-csp.cjs && node scripts/check-core-plugin-ids.cjs && node scripts/check-sdk-ui-exports.cjs && node scripts/check-button-colors.cjs && node scripts/check-sdk-guide.cjs && node scripts/check-test-locations.cjs && node scripts/check-changelog.cjs && node scripts/check-env-catalog.cjs", "lint:fix": "eslint --fix .", "type-check": "npm run build:sdk && tsc -b --force", "test": "vitest run", diff --git a/scripts/check-button-colors.cjs b/scripts/check-button-colors.cjs new file mode 100644 index 000000000..750dec728 --- /dev/null +++ b/scripts/check-button-colors.cjs @@ -0,0 +1,111 @@ +#!/usr/bin/env node +/** + * Buttons are never white. + * + * Every Button variant is the brand orange with a different background + * opacity (or red for destructive, or transparent for ghost). Fails when a + * variant in src/ui/components/button.tsx uses a neutral fill, or when a + * `, + ); + expect(tags).toHaveLength(1); + expect(tags[0]).toContain('className="x"'); + }); +}); + +describe("check-button-colors", () => { + it("accepts orange buttons and hover fills", () => { + const dir = fixture({ + "a.tsx": `` }); + expect(scan([dir]), cls).toHaveLength(1); + } + }); + + it("rejects a neutral fill in a variant", () => { + const dir = fixture({ + "button.tsx": `variant: {\n default: "bg-primary text-primary-foreground",\n ghost: "hover:bg-muted",\n},\nsize: {`, + }); + expect(scan([], path.join(dir, "button.tsx"))).toHaveLength(1); + }); + + it("passes on the real button", () => { + const button = path.resolve( + __dirname, + "..", + "src", + "ui", + "components", + "button.tsx", + ); + expect(scan([], button)).toEqual([]); + }); +}); diff --git a/src/ui/components/button.tsx b/src/ui/components/button.tsx index 86fb6789e..acb6fbaf2 100644 --- a/src/ui/components/button.tsx +++ b/src/ui/components/button.tsx @@ -10,16 +10,17 @@ const buttonVariants = cva( { variants: { variant: { - default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", + default: + "border-accent-brand/40 bg-accent-brand/15 text-accent-brand hover:bg-accent-brand/25 aria-expanded:bg-accent-brand/25", outline: - "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50", + "border-accent-brand/40 bg-transparent text-accent-brand hover:bg-accent-brand/10 aria-expanded:bg-accent-brand/10", secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", + "border-accent-brand/20 bg-accent-brand/10 text-accent-brand hover:bg-accent-brand/20 aria-expanded:bg-accent-brand/20", ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50", destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40", - link: "text-primary underline-offset-4 hover:underline", + link: "text-accent-brand underline-offset-4 hover:underline", }, size: { default: