Skip to content

refactor(design): one colour system on the bot pages - #144

Merged
github-actions[bot] merged 1 commit into
mainfrom
refactor/one-color-system
Aug 28, 2026
Merged

refactor(design): one colour system on the bot pages#144
github-actions[bot] merged 1 commit into
mainfrom
refactor/one-color-system

Conversation

@catomean

Copy link
Copy Markdown
Collaborator

The problem

app/globals.css defines the identity — editorial ink, one ochre accent — and states it outright:

No generic "AI gradient" blue/purple.

The bot pages ran a parallel palette anyway. A single viewport of /bots/legal-expert showed a blue logo, a blue nav button and an ochre CTA at the same time.

Four colour sources, not two

Source What it was
lib/config/colors.ts 16-colour accent sets
lib/hooks/navigationConfig.ts its own 5-colour NAV_COLOR_CLASSES
ACCENT_HERO_CLASSES a fifth set — whose green and indigo entries both set chatBg: 'bg-blue-50', so it wasn't even self-consistent
raw Tailwind text-gray-900, bg-white, border-gray-200

The B mark in BotNavigation was literally bg-gradient-to-r from-blue-600 to-purple-600 — the exact thing globals.css forbids by name.

The fix

The six professional bots are Botsmann, so they wear the brand: one BRAND_ACCENT, one BRAND_HERO, one NAV_COLORS. 113 raw grey/white classes became semantic tokens (text-ink, text-ink-muted, bg-surface, bg-paper, border-edge). Page ground is bg-paper, matching the homepage. The B mark now renders the shared <Logo>, so it can't drift again.

BotPageTemplate.tsx deleted — nothing imported it.

What deliberately stays

The per-colour sets remain for user-created bots. custom_bots.accent_color is a real column with a CHECK constraint and the owner picks it — that's user data, not a design token. Removing it would need a migration and would take a feature away.

Not in this PR

/try, /enterprise, /bots and /knowledge still carry blue/purple gradients — 72 files match the raw palette. Same class, separate pass, so this one stays reviewable.

Verify

format:check, lint, typecheck, 240 tests, build — all green. Verified visually against a local production build: black B matching the homepage, ochre nav and CTA, warm paper ground, ochre-tinted chat panel.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HVwg8DKHQktxJuHeLM3xpG

app/globals.css defines the identity -- editorial ink, one ochre accent --
and says so in a comment: "No generic AI gradient blue/purple." The bot
pages ignored it and ran a parallel palette, so a single viewport of
/bots/legal-expert showed a blue logo, a blue nav button and an ochre CTA
at the same time.

There were four colour sources, not two:
  lib/config/colors.ts        16-colour accent sets
  lib/hooks/navigationConfig  its own 5-colour NAV_COLOR_CLASSES
  ACCENT_HERO_CLASSES         a fifth set (whose green and indigo entries
                              both set chatBg to 'bg-blue-50' -- it was not
                              even self-consistent)
  raw Tailwind greys          text-gray-900 / bg-white / border-gray-200

The six professional bots are Botsmann, so they now wear the brand:
BRAND_ACCENT and BRAND_HERO, plus a single NAV_COLORS scheme. 113 raw
grey/white classes became semantic tokens (text-ink, text-ink-muted,
bg-surface, bg-paper, border-edge). The page ground is bg-paper, matching
the homepage instead of flat white.

The 'B' mark in BotNavigation was literally
`bg-gradient-to-r from-blue-600 to-purple-600` -- the exact thing globals.css
forbids by name. It now renders the shared <Logo>, so it cannot drift again.

Per-bot accentColor is gone from the first-party config and its plumbing.
The per-colour sets STAY for user-created bots: custom_bots.accent_color is
a real column with a CHECK constraint and the owner picks it. That is user
data, not a design token.

Also deleted components/shared/BotPageTemplate.tsx -- nothing imported it.

Not in this change: /try, /enterprise, /bots and /knowledge still carry
blue/purple gradients (72 files match the raw palette). Same class, separate
pass, so this one stays reviewable.

verify: format, lint, typecheck, 240 tests, build -- all green. Verified
visually against a local production build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HVwg8DKHQktxJuHeLM3xpG
@github-actions
github-actions Bot merged commit b93d784 into main Aug 28, 2026
1 check passed
@github-actions
github-actions Bot deleted the refactor/one-color-system branch August 28, 2026 08:16
github-actions Bot pushed a commit that referenced this pull request Aug 28, 2026
)

#144 put the bot pages on the brand. This does the other 60 files, so the
whole product reads as one thing, and adds the guard that keeps it that way.

~410 raw palette classes became semantic tokens across the public marketing
surface (/try, /enterprise, /about, /knowledge, /personal, /professionals,
/bots, blog, navigation) and the app internals (dashboard, documents, chat,
conversations, onboarding, auth, settings, profile).

Gradient text is gone. Fifteen headings were
`bg-gradient-to-r from-X to-Y bg-clip-text text-transparent`; they are now
solid text-ink or text-action. globals.css says the identity is carried by
typography, and a serif display does not need a gradient to do that.

The 'B' mark was still a blue/purple gradient in BotNavigation's MOBILE menu.
#144 only fixed the desktop header. Both now render the shared <Logo>.

Three defects introduced mid-sweep and corrected, all caught by reading the
diff rather than trusting the regex:
  - degenerate gradients (`from-action-tint to-action-tint`) collapsed to solid
  - dead hovers (tint on tint) rebased to bg-surface + hover:bg-action-tint
  - `to-action\b` matched the prefix of `to-action-hover`, so a collapse left a
    stray `bg-action-hover` as a BASE background in 11 places -- those are the
    primary, not the hover shade

Deliberately NOT changed:
  - components/knowledge/Callout.tsx -- its blue is the `info` half of an
    info/warning/error triad. Semantic status colour is a separate scale from
    the brand accent, and warning is amber, so ochre-ing info would make the
    two nearly indistinguishable.
  - the custom-bot surfaces -- custom_bots.accent_color is a real column with
    a CHECK constraint and the owner picks it. User data, not a design token.

Never-twice: tests/__tests__/lib/design-tokens.test.ts refuses any raw
brand-palette class, and any bg-clip-text, outside those two documented
exceptions. Mutation-verified -- swap one token back to bg-blue-600 and it
fails and names the file. No allowlist debt: every other file was swept rather
than excused.

verify: format, lint, typecheck, 256 tests, build -- all green. Twelve pages
smoke-tested and checked visually against a local production build.


Claude-Session: https://claude.ai/code/session_01HVwg8DKHQktxJuHeLM3xpG

Co-authored-by: Mao Nakamoto <41178744+maonakamoto@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Aug 28, 2026
…ssed it (#149)

#148 shipped with the guard passing and the homepage still emitting
bg-blue-100, text-indigo-600, bg-purple-100. Both were true, because the
guard only walked app/ and components/.

The palette was in data/professionals.ts -- its own getAccentColorClasses,
giving each of the six first-party professionals a colour (blue, green,
indigo, red, amber, purple). Same mistake as the bots in #144, in the one
directory the scanner did not read. That is the whole lesson: a source
scanner is blind in exactly the shapes you forget to look at, so its first
clean run proves nothing.

  - the six professionals now use the brand, like the six bots
  - the guard walks data/ and lib/ too
  - data/menuItems.ts lost a blue/purple gradient

Two files are now DOCUMENTED exceptions rather than debt, because their
colour is categorical and has to stay mutually distinguishable:

  lib/constants.ts                    document status -- pending yellow,
                                      processing blue, ready green, error red.
                                      Recolouring "processing" to ochre would
                                      make state read as brand chrome.
  lib/infrastructure/providers.ts     per-provider identity, so Ollama and
                                      OpenAI are tellable apart at a glance.

Both sit alongside Callout.tsx's info/warning/error triad, each with its
reason written next to it.

verify: format, lint, typecheck, 256 tests, build -- all green. Homepage
confirmed to emit no raw palette class at all.


Claude-Session: https://claude.ai/code/session_01HVwg8DKHQktxJuHeLM3xpG

Co-authored-by: Mao Nakamoto <41178744+maonakamoto@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Aug 28, 2026
#144 branded the bot page sections. It did not reach the demo underneath
them, so every first-party bot still ran the per-colour palette in its
interactive step -- the buttons, focus rings, progress dots, message bubbles,
dropzone and context panel -- plus the bot switcher in the nav.

The colour came from lib/demo/botDemoConfigs.ts, which carried its own
accentColor per bot (blue, green, red, indigo, amber). That is the sixth
place a colour was chosen, after: globals.css, lib/config/colors.ts,
lib/hooks/navigationConfig.ts, ACCENT_HERO_CLASSES, and data/professionals.ts.

DemoSection and BotSwitcher are used ONLY by the first-party bot pages
(verified: no custom-bot page imports either), so both are now brand:
BRAND_BUTTON, BRAND_FOCUS_RING, BRAND_STARTER, BRAND_CHECKBOX, BRAND_PROGRESS,
BRAND_MESSAGE, BRAND_DROPZONE, BRAND_CONTEXT_PANEL, BRAND_SWITCHER.

accentColor is gone from the demo config, its type, and the whole prop chain.

What still emits raw palette, correctly:
  VISION_STATUS_CONFIG   roadmap status -- completed green, in-progress blue,
                         planned amber, vision purple. Four states that have to
                         stay tellable apart; collapsing them to ochre would
                         destroy the information.
  the /personal templates per-template identity in the memorial/legends
                         product, chosen from an allowlisted surface.

Both live behind lib/config/colors.ts, which the guard already documents as an
exception -- so the guard passing while those classes ship is correct, not a
blind spot. The blind spot was data/professionals.ts, fixed in #149.

verify: format, lint, typecheck, 256 tests, build -- all green. Bot demo
confirmed ochre end to end against a local production build.


Claude-Session: https://claude.ai/code/session_01HVwg8DKHQktxJuHeLM3xpG

Co-authored-by: Mao Nakamoto <41178744+maonakamoto@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant