refactor(site): replace shadcn color aliases with semantic design tokens (#24284)

The shadcn-compatible CSS aliases (`--background`, `--foreground`,
`--muted`,
`--muted-foreground`, `--primary`, `--primary-foreground`) were added as
part
of the Coder agents work with hardcoded HSL values that duplicated
existing
semantic design tokens. These non-standard color classes (`bg-muted`,
`text-muted-foreground`, `text-foreground`) had started spreading
through
components like Table, MultiUserSelect, and WorkspacesTable.

This PR makes two changes:

1. **CSS aliases now derive from canonical tokens via `var()`
references**
instead of duplicating HSL values. The aliases remain for `streamdown`
   and other external consumers, but `--background` now resolves to
   `--surface-primary` (`#FFFFFF` in light, was `#FAFAFA`), and the rest
   map to their semantic equivalents (`--content-primary`,
   `--surface-secondary`, `--content-secondary`, `--content-link`).

2. **Component classes replaced with semantic equivalents:**
   - `bg-muted` → `bg-surface-secondary`
   - `text-muted-foreground` → `text-content-secondary`
   - `text-foreground` → `text-content-primary`
   - `text-amber-400` → `text-content-warning`
   - `hsl(var(--background))` → `hsl(var(--surface-primary))`
   - `hsl(var(--muted-foreground))` → `hsl(var(--content-secondary))`

> This PR was initially created by Claude Opus 4.

Co-authored-by: Jaayden Halko <jaayden@coder.com>
Co-authored-by: Jaayden Halko <jaayden.halko@gmail.com>
This commit is contained in:
christin
2026-04-18 14:39:55 +02:00
committed by GitHub
parent 2a1984f0e8
commit 23f9e26796
7 changed files with 25 additions and 23 deletions
+3 -3
View File
@@ -223,7 +223,7 @@ export const ChartTooltipContent: React.FC<ChartTooltipContentProps> = ({
<div
key={item.dataKey}
className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-content-secondary",
indicator === "dot" && "items-center",
)}
>
@@ -263,12 +263,12 @@ export const ChartTooltipContent: React.FC<ChartTooltipContentProps> = ({
>
<div className="grid gap-1.5">
{nestLabel ? tooltipLabel : null}
<span className="text-muted-foreground">
<span className="text-content-secondary">
{itemConfig?.label || item.name}
</span>
</div>
{item.value && (
<span className="font-mono font-medium tabular-nums text-foreground">
<span className="font-mono font-medium tabular-nums text-content-primary">
{item.value.toLocaleString()}
</span>
)}
+3 -3
View File
@@ -54,7 +54,7 @@ export const TableFooter: React.FC<React.ComponentPropsWithRef<"tfoot">> = ({
return (
<tfoot
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
"border-t bg-surface-secondary/50 font-medium [&>tr]:last:border-b-0",
className,
)}
{...props}
@@ -65,7 +65,7 @@ export const TableFooter: React.FC<React.ComponentPropsWithRef<"tfoot">> = ({
const tableRowVariants = cva(
[
"border-0 border-b border-solid border-border transition-colors",
"data-[state=selected]:bg-muted",
"data-[state=selected]:bg-surface-secondary",
],
{
variants: {
@@ -95,7 +95,7 @@ export const TableRow: React.FC<TableRowProps> = ({
<tr
className={cn(
"border-0 border-b border-solid border-border transition-colors",
"data-[state=selected]:bg-muted",
"data-[state=selected]:bg-surface-secondary",
tableRowVariants({ hover }),
className,
)}
+12 -12
View File
@@ -80,12 +80,12 @@
intentionally generic so they match shadcn conventions.
Do NOT rename without updating every consumer.
*/
--background: 0 0% 98%;
--foreground: 240 10% 4%;
--muted: 240 5% 96%;
--muted-foreground: 240 5% 34%;
--primary: 221 83% 53%;
--primary-foreground: 0 0% 98%;
--background: var(--surface-primary);
--foreground: var(--content-primary);
--muted: var(--surface-secondary);
--muted-foreground: var(--content-secondary);
--primary: var(--content-link);
--primary-foreground: var(--surface-primary);
--avatar-lg: 2.5rem;
--avatar-default: 2rem;
--avatar-sm: 1.5rem;
@@ -147,12 +147,12 @@
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
/* shadcn-compatible aliases see :root block for details. */
--background: 240 10% 4%;
--foreground: 0 0% 98%;
--muted: 240 6% 10%;
--muted-foreground: 240 5% 65%;
--primary: 213 94% 68%;
--primary-foreground: 240 10% 4%;
--background: var(--surface-primary);
--foreground: var(--content-primary);
--muted: var(--surface-secondary);
--muted-foreground: var(--content-secondary);
--primary: var(--content-link);
--primary-foreground: var(--surface-primary);
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ export const AgentExternal: FC<AgentExternalProps> = ({ agent, workspace }) => {
}
return (
<section className="text-base text-muted-foreground pb-2 leading-relaxed">
<section className="text-base text-content-secondary pb-2 leading-relaxed">
<p>
Please run the following command to attach an agent to the{" "}
{workspace.name} workspace:
@@ -49,7 +49,7 @@ const ShimmerComponent = ({
animate={{ backgroundPosition: "0% center" }}
className={cn(
"relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent",
"[--bg:linear-gradient(90deg,#0000_calc(50%-var(--spread)),hsl(var(--background)),#0000_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]",
"[--bg:linear-gradient(90deg,#0000_calc(50%-var(--spread)),hsl(var(--surface-primary)),#0000_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]",
className,
)}
initial={{ backgroundPosition: "100% center" }}
@@ -57,7 +57,7 @@ const ShimmerComponent = ({
{
"--spread": `${dynamicSpread}px`,
backgroundImage:
"var(--bg), linear-gradient(hsl(var(--muted-foreground)), hsl(var(--muted-foreground)))",
"var(--bg), linear-gradient(hsl(var(--content-secondary)), hsl(var(--content-secondary)))",
} as CSSProperties
}
transition={{
@@ -215,7 +215,9 @@ export const GitPanel: FC<GitPanelProps> = ({
<CircleDotIcon
className={cn(
"!size-3.5 shrink-0",
isActive ? "text-amber-400" : "text-amber-400/60",
isActive
? "text-content-warning"
: "text-content-warning/60",
)}
/>
<span className="truncate">
@@ -341,7 +341,7 @@ const WorkspacesRow: FC<WorkspacesRowProps> = ({
{...clickableProps}
data-testid={`workspace-${workspace.id}`}
className={cn([
checked ? "bg-muted hover:bg-muted" : undefined,
checked ? "bg-surface-secondary hover:bg-surface-secondary" : undefined,
clickableProps.className,
])}
>