Services

Color Review


Cross-repo color review

Executive summary#

The repository has a strong Assistance green brand thread, but it is implemented through several overlapping color systems. Shared UI packages primarily use OKLCH tokens, Studio packages still use HSL tokens, and some apps layer shadcn-style HSL variables on top of the shared token set. The most important risks are low-contrast foreground tokens, duplicated status colors, duplicated code-token palettes, and hard-coded app chrome colors that bypass shared semantics.

The audits did not identify one single broken palette. Instead, they show color drift caused by parallel token contracts across shared packages, content apps, and product/admin surfaces. The highest-impact path is to centralize semantic state and code tokens, clarify token ownership by package family, and replace hard-coded reachable app chrome colors with existing or new semantic tokens.

Evidence reviewed#

This synthesis is based on these audit reports:

  • .awao/findings/review-colors-shared-color-system.md
  • .awao/findings/review-colors-content-apps.md
  • .awao/findings/review-colors-product-apps.md

Top cross-repo color risks#

  1. Parallel color spaces and token contracts create ambiguity.

    • packages/ui and packages/config use OKLCH variables, while packages/studio-ui and packages/studio-config use HSL variables.
    • apps/academy/styles/globals.css and apps/ui-library/styles/globals.css add shadcn-style HSL variables on top of shared UI tokens.
    • apps/studio/styles/assistance-theme.css applies a dark-first HSL token set across :root, .dark, .deep-dark, and several [data-theme] selectors.
  2. Low-contrast tokens are already present in shared and product surfaces.

    • packages/studio-ui/build/css/themes/light.css and packages/studio-ui/build/css/themes/dark.css have --foreground-muted contrast measured at about 2.07:1 and 2.21:1 against --background-default.
    • packages/ui/build/css/themes/dark.css contains an audit comment warning that --foreground-muted is about 2.7:1 against --background-default.
    • apps/manager/src/globals.css uses brand teal #0aa8a7; the product audit measured it at 2.93:1 on white when used as text.
    • Studio muted foreground in apps/studio/styles/assistance-theme.css was approximated at 3.48:1 on the near-black canvas.
  3. Status colors drift because there is no shared semantic state contract.

    • packages/saas-ui/src/shared/status-badge.tsx duplicates arbitrary hex state colors.
    • apps/manager/src/routes/_dashboard/dashboard.tsx, apps/manager/src/routes/_dashboard/billing/detail.tsx, apps/manager/src/routes/_dashboard/subscriptions/detail.tsx, and apps/manager/src/routes/_dashboard/services.tsx repeat status badge mappings.
    • apps/manager/src/routes/_admin/admin/academy/* uses Tailwind palette literals for state badges and metrics.
    • Admin health states use Badge variants rather than a dedicated success/warning/danger/info token set.
  4. Shared generated tokens and legacy config helpers may disagree.

    • packages/config/default-colors.js and packages/studio-config/default-colors.js reference Radix-style variables such as --colors-slate1 and --colors-grayA11, while generated outputs use names such as --colors-slate-light-100 and --colors-gray-dark-1100.
    • packages/ui/build/css/tw-extend/color.js exposes var(--core-colors-...), while inspected generated global CSS defines --colors-* variables.
  5. Duplicated code-token palettes increase maintenance cost.

    • The same --code-token-* palette appears in apps/docs/styles/main.scss, apps/academy/styles/code-block-variables.css, apps/design-system/styles/code-block-variables.css, and apps/ui-library/styles/code-block-variables.css.
  6. Reachable app chrome still includes hard-coded or off-brand colors.

    • apps/docs/styles/Home.module.css contains starter-style #0070f3 and #eaeaea.
    • apps/ui-library/components/command.tsx uses via-[#bbb] and text-[#888].
    • apps/www/styles/customers.module.css repeats #3ecf8e; apps/www/styles/realtime.module.css repeats hsla(153, 60%, 28%, 1), #ffffff, and black shadows.
    • packages/saas-ui/src/components/button.tsx hard-codes hover:bg-[#077877].
    • packages/studio-ui/src/lib/commonCva.ts still defaults brand background/text to purple utilities while borders use border-brand-600.

Quick wins#

  1. Replace hard-coded reachable app chrome colors with existing semantic tokens where the target token is already clear:

    • apps/ui-library/components/command.tsx
    • apps/docs/styles/Home.module.css
    • packages/saas-ui/src/components/button.tsx
    • packages/studio-ui/src/lib/commonCva.ts
  2. Mark known low-contrast muted tokens as decorative or metadata-only in token documentation, especially:

    • packages/ui/build/css/themes/dark.css
    • packages/studio-ui/build/css/themes/light.css
    • packages/studio-ui/build/css/themes/dark.css
    • apps/studio/styles/assistance-theme.css
  3. Stop using Manager #0aa8a7 as normal body-sized text on white. Introduce or use a darker light-mode brand text token in apps/manager/src/globals.css while keeping the current teal for fills, rings, icons, and dark-mode accents.

  4. Confirm whether --core-colors-* variables are emitted in consuming builds. If they are not, align packages/ui/build/css/tw-extend/color.js with the generated --colors-* variable names.

Larger follow-up opportunities#

  1. Define shared semantic state tokens. Add a cross-product contract for success, warning, danger, neutral, and info, then migrate packages/saas-ui/src/shared/status-badge.tsx, Manager route badge maps, and Admin health badges to it.

  2. Centralize code syntax tokens. Move the duplicated --code-token-* palette from docs, academy, design-system, and ui-library into a shared CSS import or package token file.

  3. Make color-space ownership explicit. Decide whether Studio remains an HSL package family while the primary UI family remains OKLCH, and document the boundary. If sidebar/shadcn tokens stay shared, avoid exposing HSL-shaped values through OKLCH wrappers.

  4. Refresh stale shared color helpers. Regenerate, replace, or remove packages/config/default-colors.js and packages/studio-config/default-colors.js so they match the generated token outputs.

  5. Clarify dark-mode commitments per app. Admin has no explicit .dark token block in apps/admin/src/globals.css; decide whether Admin supports dark mode. Studio intentionally collapses light/dark branches to dark values in apps/studio/tailwind.config.ts; document that behavior if it remains the product direction.

Prioritized action plan#

  1. P0 — Prevent contrast regressions. Add a small static contrast check for semantic foreground/background token pairs covering shared UI, Studio UI, Manager, and Admin. Include known risky pairs from the audits, such as muted foreground tokens and Manager brand/pending text on white.

  2. P1 — Centralize product state colors. Introduce shared semantic state tokens and migrate packages/saas-ui/src/shared/status-badge.tsx, packages/saas-ui/src/components/button.tsx, Manager dashboard status maps, and Admin health badges.

  3. P1 — Remove obvious hard-coded chrome colors. Tokenize the highest-value reachable hotspots in apps/ui-library/components/command.tsx, apps/docs/styles/Home.module.css, packages/studio-ui/src/lib/commonCva.ts, and repeated decorative brand colors in apps/www/styles/customers.module.css and apps/www/styles/realtime.module.css.

  4. P2 — Unify duplicated code-token palettes. Create one shared code-token stylesheet and import it from docs, academy, design-system, and ui-library.

  5. P2 — Resolve shared token generation drift. Validate --core-colors-* emission and update tw-extend/color.js or generation outputs as needed. Refresh or remove stale default-colors.js helpers.

  6. P3 — Document app-level color boundaries. Document when apps should use shared OKLCH tokens, app-local shadcn HSL variables, or Studio HSL tokens. Include specific guidance for apps/academy, apps/ui-library, and apps/studio.