refactor(nexus): replace literal brand hexes with tailwind aliases

This commit is contained in:
Nexus Dev 2026-04-11 17:22:15 +00:00
parent 044a2571bd
commit c9ed4c927f
7 changed files with 17 additions and 18 deletions

View file

@ -15,9 +15,9 @@ import { useVoice } from "../../context/VoiceContext";
* - listening: volt fill, 1.5s pulse loop + expanding volt ring
* - speaking: silver fill, no pulse
*
* Literal hex `#166534` (forest) and `#a0a0a0` (silver) are used because
* MIGRATION-PLAN.md §3 proposes these as new CSS variables but has not yet
* shipped them. Volt uses the `text-primary`/`bg-primary` semantic token.
* Uses the direct brand Tailwind aliases (`bg-forest`, `bg-silver`) that
* resolve to the `--forest` / `--silver` CSS vars declared in index.css.
* Volt uses the `text-primary`/`bg-primary` semantic token.
*/
export function GlobalMicButton() {
const { state, toggleListening, hasQueuedVoice } = useVoice();
@ -53,7 +53,7 @@ export function GlobalMicButton() {
aria-hidden="true"
className={cn(
"h-2 w-2 rounded-full",
hasQueuedVoice ? "bg-primary" : "bg-[#166534]",
hasQueuedVoice ? "bg-primary" : "bg-forest",
)}
/>
)}
@ -72,7 +72,7 @@ export function GlobalMicButton() {
{state === "speaking" && (
<span
aria-hidden="true"
className="h-2 w-2 rounded-full bg-[#a0a0a0]"
className="h-2 w-2 rounded-full bg-silver"
/>
)}
</button>

View file

@ -137,7 +137,7 @@ describe("ProjectCard", () => {
it("renders a forest-green dot for idle status", () => {
const api = render({ slug: "A", status: "idle", progress: 0 });
expect(api.dot?.dataset.status).toBe("idle");
expect(api.dot?.className).toContain("bg-[#166534]");
expect(api.dot?.className).toContain("bg-forest");
});
it("renders a pulsing volt dot for working status", () => {
@ -150,7 +150,7 @@ describe("ProjectCard", () => {
it("renders a pale-yellow dot for waiting status", () => {
const api = render({ slug: "A", status: "waiting", progress: 0 });
expect(api.dot?.dataset.status).toBe("waiting");
expect(api.dot?.className).toContain("bg-[#f4f692]");
expect(api.dot?.className).toContain("bg-volt-pale");
});
it("sets progress bar fill width from normal progress value", () => {

View file

@ -43,13 +43,12 @@ export interface ProjectCardProps {
function StatusDot({ status }: { status: ProjectCardStatus }) {
if (status === "waiting") {
// Pale yellow literal hex — token doesn't ship until MIGRATION-PLAN §3.
return (
<span
data-testid="project-card-status-dot"
data-status="waiting"
aria-label="Waiting on gate"
className="h-2 w-2 rounded-full bg-[#f4f692]"
className="h-2 w-2 rounded-full bg-volt-pale"
/>
);
}
@ -68,7 +67,7 @@ function StatusDot({ status }: { status: ProjectCardStatus }) {
data-testid="project-card-status-dot"
data-status="idle"
aria-label="Idle"
className="h-2 w-2 rounded-full bg-[#166534]"
className="h-2 w-2 rounded-full bg-forest"
/>
);
}

View file

@ -78,7 +78,7 @@ function MilestoneBullet({ item }: { item: MilestoneItem }) {
data-testid="milestone-bullet"
data-state="next-gate"
aria-hidden="true"
className="inline-block w-5 shrink-0 text-[#f4f692]"
className="inline-block w-5 shrink-0 text-volt-pale"
>
[]
</span>
@ -135,7 +135,7 @@ function MilestoneChecklistCard({
{item.state === "next-gate" ? (
<span
data-testid="milestone-next-gate-marker"
className="ml-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-[#f4f692]"
className="ml-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-volt-pale"
>
Next gate
</span>

View file

@ -33,7 +33,7 @@ export function TabPlaceholder({ testId, title, gapReason }: TabPlaceholderProps
<p className="text-[14px] text-muted-foreground">
<span
data-testid={`${testId}-gap`}
className="inline-block rounded border border-[#f4f692]/40 bg-[#f4f692]/5 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.1em] text-[#f4f692]"
className="inline-block rounded border border-volt-pale/40 bg-volt-pale/5 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.1em] text-volt-pale"
>
Phase 11 data gap
</span>

View file

@ -65,7 +65,7 @@ export function TelegramSection() {
<span
className={cn(
"text-xs font-medium",
running ? "text-[#166534] dark:text-primary" : "text-muted-foreground",
running ? "text-forest dark:text-primary" : "text-muted-foreground",
)}
>
{statusQuery.isLoading ? "..." : running ? "Running" : "Not running"}

View file

@ -225,9 +225,9 @@ export function Projects() {
data-testid="projects-empty-cta"
className={cn(
"inline-flex items-center gap-2 rounded-md px-5 py-3",
"bg-[#166534] text-white",
"bg-forest text-white",
"text-[14px] font-semibold uppercase tracking-[0.1em]",
"hover:bg-[#166534]/90 transition-colors",
"hover:bg-forest/90 transition-colors",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background",
)}
>
@ -250,9 +250,9 @@ export function Projects() {
data-testid="projects-new-project-cta"
className={cn(
"inline-flex items-center gap-2 rounded-md px-4 py-2",
"bg-[#166534] text-white",
"bg-forest text-white",
"text-[12px] font-semibold uppercase tracking-[0.12em]",
"hover:bg-[#166534]/90 transition-colors",
"hover:bg-forest/90 transition-colors",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background",
)}
>