bug: shadcn ui merge

This commit is contained in:
null 2026-05-20 01:41:15 -05:00
parent d45fd42c7f
commit ad5ca38a86
73 changed files with 831 additions and 830 deletions

View File

@ -242,7 +242,7 @@ const eventLabel = (eventType: FeedEventType): string => {
const eventPillClass = (eventType: FeedEventType): string => {
if (eventType === "task.comment") {
return "border-blue-200 bg-blue-50 text-blue-700";
return "border-primary/30 bg-primary/10 text-primary";
}
if (eventType === "task.created") {
return "border-emerald-200 bg-emerald-50 text-emerald-700";
@ -263,7 +263,7 @@ const eventPillClass = (eventType: FeedEventType): string => {
return "border-lime-200 bg-lime-50 text-lime-700";
}
if (eventType === "agent.offline") {
return "border-slate-300 bg-slate-100 text-slate-700";
return "border-input bg-accent text-muted-foreground";
}
if (eventType === "agent.updated") {
return "border-indigo-200 bg-indigo-50 text-indigo-700";
@ -280,7 +280,7 @@ const eventPillClass = (eventType: FeedEventType): string => {
if (eventType === "approval.rejected") {
return "border-rose-200 bg-rose-50 text-rose-700";
}
return "border-slate-200 bg-slate-100 text-slate-700";
return "border-border bg-accent text-muted-foreground";
};
const FeedCard = memo(function FeedCard({
@ -297,14 +297,14 @@ const FeedCard = memo(function FeedCard({
<div
id={feedItemElementId(item.id)}
className={cn(
"scroll-mt-28 rounded-xl border bg-white p-4 transition",
"scroll-mt-28 rounded-xl border bg-card p-4 transition",
isHighlighted
? "border-blue-300 ring-2 ring-blue-200"
: "border-slate-200 hover:border-slate-300",
? "border-primary/40 ring-2 ring-primary/20"
: "border-border hover:border-input",
)}
>
<div className="flex items-start gap-3">
<div className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-slate-100 text-xs font-semibold text-slate-700">
<div className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-accent text-xs font-semibold text-muted-foreground">
{authorAvatar}
</div>
<div className="min-w-0 flex-1">
@ -312,7 +312,7 @@ const FeedCard = memo(function FeedCard({
{item.context_href ? (
<Link
href={item.context_href}
className="block text-sm font-semibold leading-snug text-slate-900 transition hover:text-slate-950 hover:underline"
className="block text-sm font-semibold leading-snug text-foreground transition hover:text-foreground hover:underline"
title={item.title}
style={{
display: "-webkit-box",
@ -324,11 +324,11 @@ const FeedCard = memo(function FeedCard({
{item.title}
</Link>
) : (
<p className="text-sm font-semibold leading-snug text-slate-900">
<p className="text-sm font-semibold leading-snug text-foreground">
{item.title}
</p>
)}
<div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-slate-500">
<div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground">
<span
className={cn(
"rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide",
@ -340,29 +340,29 @@ const FeedCard = memo(function FeedCard({
{item.board_href && item.board_name ? (
<Link
href={item.board_href}
className="font-semibold text-slate-700 hover:text-slate-900 hover:underline"
className="font-semibold text-muted-foreground hover:text-foreground hover:underline"
>
{item.board_name}
</Link>
) : item.board_name ? (
<span className="font-semibold text-slate-700">
<span className="font-semibold text-muted-foreground">
{item.board_name}
</span>
) : null}
{item.board_name ? (
<span className="text-slate-300">·</span>
<span className="text-muted-foreground/50">·</span>
) : null}
<span className="font-medium text-slate-700">
<span className="font-medium text-muted-foreground">
{item.actor_name}
</span>
{item.actor_role ? (
<>
<span className="text-slate-300">·</span>
<span className="text-slate-500">{item.actor_role}</span>
<span className="text-muted-foreground/50">·</span>
<span className="text-muted-foreground">{item.actor_role}</span>
</>
) : null}
<span className="text-slate-300">·</span>
<span className="text-slate-400">
<span className="text-muted-foreground/50">·</span>
<span className="text-muted-foreground/70">
{formatShortTimestamp(item.created_at)}
</span>
</div>
@ -370,11 +370,11 @@ const FeedCard = memo(function FeedCard({
</div>
</div>
{message ? (
<div className="mt-3 select-text cursor-text text-sm leading-relaxed text-slate-900 break-words">
<div className="mt-3 select-text cursor-text text-sm leading-relaxed text-foreground break-words">
<Markdown content={message} variant="basic" />
</div>
) : (
<p className="mt-3 text-sm text-slate-500"></p>
<p className="mt-3 text-sm text-muted-foreground"></p>
)}
</div>
);
@ -1506,18 +1506,18 @@ export default function ActivityPage() {
</SignedOut>
<SignedIn>
<DashboardSidebar />
<main className="flex-1 overflow-y-auto bg-slate-50">
<div className="sticky top-0 z-30 border-b border-slate-200 bg-white">
<main className="flex-1 overflow-y-auto bg-muted">
<div className="sticky top-0 z-30 border-b border-border bg-card">
<div className="px-4 py-4 md:px-8 md:py-6">
<div className="flex flex-wrap items-center justify-between gap-4">
<div>
<div className="flex items-center gap-2">
<ActivityIcon className="h-5 w-5 text-slate-600" />
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
<ActivityIcon className="h-5 w-5 text-muted-foreground" />
<h1 className="text-2xl font-semibold tracking-tight text-foreground">
Live feed
</h1>
</div>
<p className="mt-1 text-sm text-slate-500">
<p className="mt-1 text-sm text-muted-foreground">
Realtime task, approval, agent, and board-chat activity
across all boards.
</p>

View File

@ -258,16 +258,16 @@ export default function EditAgentPage() {
>
<form
onSubmit={handleSubmit}
className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm space-y-6"
className="rounded-xl border border-border bg-card p-6 shadow-sm space-y-6"
>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Basic configuration
</p>
<div className="mt-4 space-y-6">
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Agent name <span className="text-red-500">*</span>
</label>
<Input
@ -278,7 +278,7 @@ export default function EditAgentPage() {
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Role
</label>
<Input
@ -297,10 +297,10 @@ export default function EditAgentPage() {
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board
{resolvedIsGatewayMain ? (
<span className="ml-2 text-xs font-normal text-slate-500">
<span className="ml-2 text-xs font-normal text-muted-foreground">
optional
</span>
) : (
@ -310,7 +310,7 @@ export default function EditAgentPage() {
{resolvedBoardId ? (
<button
type="button"
className="text-xs font-medium text-slate-600 hover:text-slate-900"
className="text-xs font-medium text-muted-foreground hover:text-foreground"
onClick={() => {
setBoardId("");
}}
@ -338,19 +338,19 @@ export default function EditAgentPage() {
disabled={boards.length === 0}
/>
{resolvedIsGatewayMain ? (
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Main agents are not attached to a board. If a board is
selected, it is only used to resolve the gateway main
session key and will be cleared on save.
</p>
) : boards.length === 0 ? (
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Create a board before assigning agents.
</p>
) : null}
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Emoji
</label>
<Select
@ -377,20 +377,20 @@ export default function EditAgentPage() {
</div>
</div>
</div>
<div className="mt-6 rounded-xl border border-slate-200 bg-slate-50 p-4">
<label className="flex items-start gap-3 text-sm text-slate-700">
<div className="mt-6 rounded-xl border border-border bg-muted p-4">
<label className="flex items-start gap-3 text-sm text-muted-foreground">
<input
type="checkbox"
className="mt-1 h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-200"
className="mt-1 h-4 w-4 rounded border-input text-primary focus:ring-ring/30"
checked={resolvedIsGatewayMain}
onChange={(event) => setIsGatewayMain(event.target.checked)}
disabled={isLoading}
/>
<span>
<span className="block font-medium text-slate-900">
<span className="block font-medium text-foreground">
Gateway main agent
</span>
<span className="block text-xs text-slate-500">
<span className="block text-xs text-muted-foreground">
Uses the gateway main session key and is not tied to a single
board.
</span>
@ -400,12 +400,12 @@ export default function EditAgentPage() {
</div>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Personality & behavior
</p>
<div className="mt-4">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Communication style
</label>
<Input
@ -423,12 +423,12 @@ export default function EditAgentPage() {
</div>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Schedule & notifications
</p>
<div className="mt-4">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Interval
</label>
<Input
@ -437,7 +437,7 @@ export default function EditAgentPage() {
placeholder="e.g. 10m"
disabled={isLoading}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Set how often this agent runs HEARTBEAT.md.
</p>
</div>
@ -445,7 +445,7 @@ export default function EditAgentPage() {
</div>
{errorMessage ? (
<div className="rounded-lg border border-slate-200 bg-white p-3 text-sm text-slate-600 shadow-sm">
<div className="rounded-lg border border-border bg-card p-3 text-sm text-muted-foreground shadow-sm">
{errorMessage}
</div>
) : null}

View File

@ -142,16 +142,16 @@ export default function NewAgentPage() {
>
<form
onSubmit={handleSubmit}
className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm space-y-6"
className="rounded-xl border border-border bg-card p-6 shadow-sm space-y-6"
>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Basic configuration
</p>
<div className="mt-4 space-y-6">
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Agent name <span className="text-red-500">*</span>
</label>
<Input
@ -162,7 +162,7 @@ export default function NewAgentPage() {
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Role
</label>
<Input
@ -180,7 +180,7 @@ export default function NewAgentPage() {
</div>
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board <span className="text-red-500">*</span>
</label>
<SearchableSelect
@ -197,13 +197,13 @@ export default function NewAgentPage() {
disabled={boards.length === 0}
/>
{boards.length === 0 ? (
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Create a board before adding agents.
</p>
) : null}
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Emoji
</label>
<Select
@ -233,12 +233,12 @@ export default function NewAgentPage() {
</div>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Personality & behavior
</p>
<div className="mt-4">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Communication style
</label>
<Input
@ -256,12 +256,12 @@ export default function NewAgentPage() {
</div>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Schedule & notifications
</p>
<div className="mt-4">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Interval
</label>
<Input
@ -270,7 +270,7 @@ export default function NewAgentPage() {
placeholder="e.g. 10m"
disabled={isLoading}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
How often this agent runs HEARTBEAT.md (10m, 30m, 2h).
</p>
</div>
@ -278,7 +278,7 @@ export default function NewAgentPage() {
</div>
{errorMessage ? (
<div className="rounded-lg border border-slate-200 bg-white p-3 text-sm text-slate-600 shadow-sm">
<div className="rounded-lg border border-border bg-card p-3 text-sm text-muted-foreground shadow-sm">
{errorMessage}
</div>
) : null}

View File

@ -142,7 +142,7 @@ export default function AgentsPage() {
adminOnlyMessage="Only organization owners and admins can access agents."
stickyHeader
>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<AgentsTable
agents={agents}
boards={boards}

View File

@ -166,7 +166,7 @@ function GlobalApprovalsInner() {
}, [errorText, warnings]);
return (
<main className="flex-1 overflow-y-auto bg-gradient-to-br from-slate-50 to-slate-100">
<main className="flex-1 overflow-y-auto bg-background">
<div className="p-4 md:p-6">
<div className="h-[calc(100vh-160px)] min-h-[300px] sm:min-h-[520px]">
<BoardApprovalsPanel

View File

@ -288,7 +288,7 @@ export default function EditBoardGroupPage() {
>
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
{assignFailedCount && Number.isFinite(assignFailedCount) ? (
<div className="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900 shadow-sm">
@ -298,7 +298,7 @@ export default function EditBoardGroupPage() {
) : null}
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Group name <span className="text-red-500">*</span>
</label>
<Input
@ -311,7 +311,7 @@ export default function EditBoardGroupPage() {
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Description
</label>
<Textarea
@ -323,16 +323,16 @@ export default function EditBoardGroupPage() {
/>
</div>
<div className="space-y-2 border-t border-slate-100 pt-6">
<div className="space-y-2 border-t border-border pt-6">
<div className="flex flex-wrap items-center justify-between gap-2">
<div>
<p className="text-sm font-medium text-slate-900">Boards</p>
<p className="mt-1 text-xs text-slate-500">
<p className="text-sm font-medium text-foreground">Boards</p>
<p className="mt-1 text-xs text-muted-foreground">
Assign boards to this group to share context across related
work.
</p>
</div>
<span className="text-xs text-slate-500">
<span className="text-xs text-muted-foreground">
{selectedBoardIds.size} selected
</span>
</div>
@ -344,9 +344,9 @@ export default function EditBoardGroupPage() {
disabled={isLoading || !baseGroup}
/>
<div className="max-h-64 overflow-auto rounded-xl border border-slate-200 bg-slate-50/40">
<div className="max-h-64 overflow-auto rounded-xl border border-border bg-muted/40">
{boardsLoading && boards.length === 0 ? (
<div className="px-4 py-6 text-sm text-slate-500">
<div className="px-4 py-6 text-sm text-muted-foreground">
Loading boards
</div>
) : boardsError ? (
@ -354,7 +354,7 @@ export default function EditBoardGroupPage() {
{boardsError.message}
</div>
) : boards.length === 0 ? (
<div className="px-4 py-6 text-sm text-slate-500">
<div className="px-4 py-6 text-sm text-muted-foreground">
No boards found.
</div>
) : (
@ -378,7 +378,7 @@ export default function EditBoardGroupPage() {
<label className="flex cursor-pointer items-start gap-3">
<input
type="checkbox"
className="mt-1 h-4 w-4 rounded border-slate-300 text-blue-600"
className="mt-1 h-4 w-4 rounded border-input text-primary"
checked={checked}
onChange={() => {
setSelectedBoardIds((prev) => {
@ -394,11 +394,11 @@ export default function EditBoardGroupPage() {
disabled={isLoading || !baseGroup}
/>
<div className="min-w-0">
<p className="truncate text-sm font-medium text-slate-900">
<p className="truncate text-sm font-medium text-foreground">
{board.name}
</p>
<div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-slate-500">
<span className="font-mono text-[11px] text-slate-400">
<div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
<span className="font-mono text-[11px] text-muted-foreground/70">
{board.id}
</span>
{isAlreadyGrouped ? (
@ -420,7 +420,7 @@ export default function EditBoardGroupPage() {
<p className="text-sm text-rose-700">{assignmentsError}</p>
) : null}
{assignmentsResult ? (
<p className="text-sm text-slate-700">
<p className="text-sm text-muted-foreground">
Updated {assignmentsResult.updated} board
{assignmentsResult.updated === 1 ? "" : "s"}, failed{" "}
{assignmentsResult.failed}.

View File

@ -78,9 +78,9 @@ const statusTone = (value?: string | null) => {
case "review":
return "bg-amber-50 text-amber-800 border-amber-200";
case "done":
return "bg-slate-50 text-slate-600 border-slate-200";
return "bg-muted text-muted-foreground border-border";
default:
return "bg-blue-50 text-blue-700 border-blue-200";
return "bg-primary/10 text-primary border-primary/30";
}
};
@ -89,7 +89,7 @@ const priorityTone = (value?: string | null) => {
case "high":
return "bg-rose-50 text-rose-700 border-rose-200";
case "low":
return "bg-slate-50 text-slate-600 border-slate-200";
return "bg-muted text-muted-foreground border-border";
default:
return "bg-indigo-50 text-indigo-700 border-indigo-200";
}
@ -112,24 +112,24 @@ const canWriteGroupBoards = (
function GroupChatMessageCard({ message }: { message: BoardGroupMemoryRead }) {
return (
<div className="rounded-2xl border border-slate-200 bg-slate-50/60 p-4">
<div className="rounded-2xl border border-border bg-muted/60 p-4">
<div className="flex flex-wrap items-center justify-between gap-2">
<p className="text-sm font-semibold text-slate-900">
<p className="text-sm font-semibold text-foreground">
{message.source ?? "User"}
</p>
<span className="text-xs text-slate-400">
<span className="text-xs text-muted-foreground/70">
{formatTimestamp(message.created_at)}
</span>
</div>
<div className="mt-2 select-text cursor-text text-sm leading-relaxed text-slate-900 break-words">
<div className="mt-2 select-text cursor-text text-sm leading-relaxed text-foreground break-words">
<Markdown content={message.content} variant="basic" />
</div>
{message.tags?.length ? (
<div className="mt-3 flex flex-wrap gap-2 text-[11px] text-slate-600">
<div className="mt-3 flex flex-wrap gap-2 text-[11px] text-muted-foreground">
{message.tags.map((tag) => (
<span
key={tag}
className="rounded-full border border-slate-200 bg-white px-2 py-0.5"
className="rounded-full border border-border bg-card px-2 py-0.5"
>
{tag}
</span>
@ -749,23 +749,23 @@ export default function BoardGroupDetailPage() {
</SignedOut>
<SignedIn>
<DashboardSidebar />
<main className="flex-1 overflow-y-auto bg-slate-50">
<div className="sticky top-0 z-30 border-b border-slate-200 bg-white shadow-sm">
<main className="flex-1 overflow-y-auto bg-muted">
<div className="sticky top-0 z-30 border-b border-border bg-card shadow-sm">
<div className="px-4 py-4 md:px-8 md:py-6">
<div className="flex flex-wrap items-start justify-between gap-4">
<div className="min-w-0">
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Board group
</p>
<h1 className="mt-2 text-2xl font-semibold tracking-tight text-slate-900">
<h1 className="mt-2 text-2xl font-semibold tracking-tight text-foreground">
{group?.name ?? "Group"}
</h1>
{group?.description ? (
<p className="mt-2 max-w-2xl text-sm text-slate-600">
<p className="mt-2 max-w-2xl text-sm text-muted-foreground">
{group.description}
</p>
) : (
<p className="mt-2 text-sm text-slate-400">
<p className="mt-2 text-sm text-muted-foreground/70">
No description
</p>
)}
@ -824,18 +824,18 @@ export default function BoardGroupDetailPage() {
</div>
<div className="mt-5 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center">
<label className="inline-flex items-center gap-2 text-sm text-slate-700">
<label className="inline-flex items-center gap-2 text-sm text-muted-foreground">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600"
className="h-4 w-4 rounded border-input text-primary"
checked={includeDone}
onChange={(event) => setIncludeDone(event.target.checked)}
/>
Include done
</label>
<div className="flex items-center gap-2 text-sm text-slate-700">
<span className="text-slate-500">Top tasks per board</span>
<div className="flex items-center gap-1 rounded-lg border border-slate-200 bg-white p-1">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<span className="text-muted-foreground">Top tasks per board</span>
<div className="flex items-center gap-1 rounded-lg border border-border bg-card p-1">
{[0, 3, 5, 10].map((value) => (
<button
key={value}
@ -843,8 +843,8 @@ export default function BoardGroupDetailPage() {
className={cn(
"rounded-md px-2.5 py-1 text-xs font-semibold transition-colors",
perBoardLimit === value
? "bg-slate-900 text-white"
: "text-slate-600 hover:bg-slate-100 hover:text-slate-900",
? "bg-foreground text-background"
: "text-muted-foreground hover:bg-accent hover:text-foreground",
)}
onClick={() => setPerBoardLimit(value)}
>
@ -854,9 +854,9 @@ export default function BoardGroupDetailPage() {
</div>
</div>
<div className="flex flex-wrap items-center gap-2 text-sm text-slate-700">
<span className="text-slate-500">Agent pace</span>
<div className="flex flex-wrap items-center gap-1 rounded-lg border border-slate-200 bg-white p-1">
<div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
<span className="text-muted-foreground">Agent pace</span>
<div className="flex flex-wrap items-center gap-1 rounded-lg border border-border bg-card p-1">
{HEARTBEAT_PRESETS.map((preset) => {
const value = `${preset.amount}${preset.unit}`;
return (
@ -866,8 +866,8 @@ export default function BoardGroupDetailPage() {
className={cn(
"rounded-md px-2.5 py-1 text-xs font-semibold transition-colors",
heartbeatEvery === value
? "bg-slate-900 text-white"
: "text-slate-600 hover:bg-slate-100 hover:text-slate-900",
? "bg-foreground text-background"
: "text-muted-foreground hover:bg-accent hover:text-foreground",
!canManageHeartbeat &&
"opacity-50 cursor-not-allowed",
)}
@ -886,9 +886,9 @@ export default function BoardGroupDetailPage() {
value={heartbeatAmount}
onChange={(event) => setHeartbeatAmount(event.target.value)}
className={cn(
"h-8 w-20 rounded-md border bg-white px-2 text-xs text-slate-900 shadow-sm",
"h-8 w-20 rounded-md border bg-card px-2 text-xs text-foreground shadow-sm",
heartbeatEvery
? "border-slate-200"
? "border-border"
: "border-rose-300 focus:border-rose-400 focus:ring-2 focus:ring-rose-100",
!canManageHeartbeat && "opacity-60 cursor-not-allowed",
)}
@ -921,10 +921,10 @@ export default function BoardGroupDetailPage() {
<SelectItem value="d">day</SelectItem>
</SelectContent>
</Select>
<label className="inline-flex items-center gap-2 text-xs text-slate-700">
<label className="inline-flex items-center gap-2 text-xs text-muted-foreground">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600"
className="h-4 w-4 rounded border-input text-primary"
checked={includeBoardLeads}
onChange={(event) =>
setIncludeBoardLeads(event.target.checked)
@ -952,7 +952,7 @@ export default function BoardGroupDetailPage() {
</Button>
</div>
{!canManageHeartbeat ? (
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Read-only access. You cannot change agent pace for this
group.
</p>
@ -969,11 +969,11 @@ export default function BoardGroupDetailPage() {
</div>
) : null}
{heartbeatApplyResult ? (
<div className="rounded-xl border border-slate-200 bg-white p-4 text-sm text-slate-700 shadow-sm">
<p className="font-semibold text-slate-900">
<div className="rounded-xl border border-border bg-card p-4 text-sm text-muted-foreground shadow-sm">
<p className="font-semibold text-foreground">
Heartbeat applied
</p>
<p className="mt-1 text-slate-600">
<p className="mt-1 text-muted-foreground">
Updated {heartbeatApplyResult.updated_agent_ids.length}{" "}
agents, failed{" "}
{heartbeatApplyResult.failed_agent_ids.length}.
@ -982,7 +982,7 @@ export default function BoardGroupDetailPage() {
) : null}
{snapshotQuery.isLoading ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-600 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Loading group snapshot
</div>
) : snapshotQuery.error ? (
@ -990,7 +990,7 @@ export default function BoardGroupDetailPage() {
{snapshotQuery.error.message}
</div>
) : boards.length === 0 ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-600 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
No boards in this group yet. Assign boards from the board
settings page.
</div>
@ -999,9 +999,9 @@ export default function BoardGroupDetailPage() {
{boards.map((item) => (
<div
key={item.board.id}
className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm"
className="overflow-hidden rounded-xl border border-border bg-card shadow-sm"
>
<div className="border-b border-slate-200 px-6 py-4">
<div className="border-b border-border px-6 py-4">
<div className="flex items-start justify-between gap-4">
<div className="min-w-0">
<Link
@ -1009,17 +1009,17 @@ export default function BoardGroupDetailPage() {
className="group inline-flex items-center gap-2"
title="Open board"
>
<p className="truncate text-sm font-semibold text-slate-900 group-hover:text-blue-600">
<p className="truncate text-sm font-semibold text-foreground group-hover:text-primary">
{item.board.name}
</p>
<ArrowUpRight className="h-4 w-4 text-slate-400 group-hover:text-blue-600" />
<ArrowUpRight className="h-4 w-4 text-muted-foreground/70 group-hover:text-primary" />
</Link>
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
Updated {formatTimestamp(item.board.updated_at)}
</p>
</div>
<div className="flex flex-wrap items-center justify-end gap-2 text-xs">
<span className="rounded-full border border-slate-200 bg-slate-50 px-2 py-0.5 text-slate-700">
<span className="rounded-full border border-border bg-muted px-2 py-0.5 text-muted-foreground">
Inbox {safeCount(item, "inbox")}
</span>
<span className="rounded-full border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-emerald-800">
@ -1042,7 +1042,7 @@ export default function BoardGroupDetailPage() {
pathname: `/boards/${item.board.id}`,
query: { taskId: task.id },
}}
className="block rounded-lg border border-slate-200 bg-slate-50/40 p-3 transition hover:border-blue-200 hover:bg-blue-50/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
className="block rounded-lg border border-border bg-muted/40 p-3 transition hover:border-primary/30 hover:bg-primary/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
title="Open task on board"
>
<div className="flex flex-wrap items-center justify-between gap-2">
@ -1063,22 +1063,22 @@ export default function BoardGroupDetailPage() {
>
{task.priority}
</span>
<p className="truncate text-sm font-medium text-slate-900">
<p className="truncate text-sm font-medium text-foreground">
{task.title}
</p>
</div>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
{formatTimestamp(task.updated_at)}
</p>
</div>
<div className="mt-2 flex flex-wrap items-center justify-between gap-2 text-xs text-slate-600">
<div className="mt-2 flex flex-wrap items-center justify-between gap-2 text-xs text-muted-foreground">
<p className="truncate">
Assignee:{" "}
<span className="font-medium text-slate-900">
<span className="font-medium text-foreground">
{task.assignee ?? "Unassigned"}
</span>
</p>
<p className="font-mono text-[11px] text-slate-400">
<p className="font-mono text-[11px] text-muted-foreground/70">
{task.id}
</p>
</div>
@ -1087,7 +1087,7 @@ export default function BoardGroupDetailPage() {
))}
</ul>
) : (
<p className="text-sm text-slate-500">
<p className="text-sm text-muted-foreground">
No tasks in this snapshot.
</p>
)}
@ -1102,7 +1102,7 @@ export default function BoardGroupDetailPage() {
</SignedIn>
{isChatOpen || isNotesOpen ? (
<div
className="fixed inset-0 z-40 bg-slate-900/20"
className="fixed inset-0 z-40 bg-foreground/20"
onClick={() => {
setIsChatOpen(false);
setChatError(null);
@ -1113,17 +1113,17 @@ export default function BoardGroupDetailPage() {
) : null}
<aside
className={cn(
"fixed right-0 top-0 z-50 h-full w-[560px] max-w-[96vw] transform border-l border-slate-200 bg-white shadow-2xl transition-transform",
"fixed right-0 top-0 z-50 h-full w-[560px] max-w-[96vw] transform border-l border-border bg-card shadow-2xl transition-transform",
isChatOpen ? "transform-none" : "translate-x-full",
)}
>
<div className="flex h-full flex-col">
<div className="flex items-center justify-between border-b border-slate-200 px-6 py-4">
<div className="flex items-center justify-between border-b border-border px-6 py-4">
<div className="min-w-0">
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Group chat
</p>
<p className="mt-1 truncate text-sm font-medium text-slate-900">
<p className="mt-1 truncate text-sm font-medium text-foreground">
Shared across linked boards. Tag @lead, @name, or @all.
</p>
</div>
@ -1133,7 +1133,7 @@ export default function BoardGroupDetailPage() {
setIsChatOpen(false);
setChatError(null);
}}
className="rounded-lg border border-slate-200 p-2 text-slate-500 transition hover:bg-slate-50"
className="rounded-lg border border-border p-2 text-muted-foreground transition hover:bg-muted"
aria-label="Close group chat"
>
<X className="h-4 w-4" />
@ -1141,24 +1141,24 @@ export default function BoardGroupDetailPage() {
</div>
<div className="flex flex-1 flex-col overflow-hidden px-6 py-4">
<div className="flex flex-wrap items-center justify-between gap-3 pb-3">
<label className="inline-flex items-center gap-2 text-sm text-slate-700">
<label className="inline-flex items-center gap-2 text-sm text-muted-foreground">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600"
className="h-4 w-4 rounded border-input text-primary"
checked={chatBroadcast}
onChange={(event) => setChatBroadcast(event.target.checked)}
disabled={!canWriteGroup}
/>
Broadcast
</label>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
{chatBroadcast
? "Notifies every agent in the group."
: "Notifies leads + mentions."}
</p>
</div>
<div className="flex-1 space-y-4 overflow-y-auto rounded-2xl border border-slate-200 bg-white p-4">
<div className="flex-1 space-y-4 overflow-y-auto rounded-2xl border border-border bg-card p-4">
{chatHistoryQuery.error ? (
<div className="rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
{chatHistoryQuery.error.message}
@ -1170,9 +1170,9 @@ export default function BoardGroupDetailPage() {
</div>
) : null}
{chatHistoryQuery.isLoading && chatMessages.length === 0 ? (
<p className="text-sm text-slate-500">Loading</p>
<p className="text-sm text-muted-foreground">Loading</p>
) : chatMessages.length === 0 ? (
<p className="text-sm text-slate-500">
<p className="text-sm text-muted-foreground">
No messages yet. Start the conversation with a broadcast or a
mention.
</p>
@ -1200,17 +1200,17 @@ export default function BoardGroupDetailPage() {
</aside>
<aside
className={cn(
"fixed right-0 top-0 z-50 h-full w-[560px] max-w-[96vw] transform border-l border-slate-200 bg-white shadow-2xl transition-transform",
"fixed right-0 top-0 z-50 h-full w-[560px] max-w-[96vw] transform border-l border-border bg-card shadow-2xl transition-transform",
isNotesOpen ? "transform-none" : "translate-x-full",
)}
>
<div className="flex h-full flex-col">
<div className="flex items-center justify-between border-b border-slate-200 px-6 py-4">
<div className="flex items-center justify-between border-b border-border px-6 py-4">
<div className="min-w-0">
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Group notes
</p>
<p className="mt-1 truncate text-sm font-medium text-slate-900">
<p className="mt-1 truncate text-sm font-medium text-foreground">
Shared across linked boards. Tag @lead, @name, or @all.
</p>
</div>
@ -1220,7 +1220,7 @@ export default function BoardGroupDetailPage() {
setIsNotesOpen(false);
setNoteSendError(null);
}}
className="rounded-lg border border-slate-200 p-2 text-slate-500 transition hover:bg-slate-50"
className="rounded-lg border border-border p-2 text-muted-foreground transition hover:bg-muted"
aria-label="Close group notes"
>
<X className="h-4 w-4" />
@ -1228,24 +1228,24 @@ export default function BoardGroupDetailPage() {
</div>
<div className="flex flex-1 flex-col overflow-hidden px-6 py-4">
<div className="flex flex-wrap items-center justify-between gap-3 pb-3">
<label className="inline-flex items-center gap-2 text-sm text-slate-700">
<label className="inline-flex items-center gap-2 text-sm text-muted-foreground">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600"
className="h-4 w-4 rounded border-input text-primary"
checked={notesBroadcast}
onChange={(event) => setNotesBroadcast(event.target.checked)}
disabled={!canWriteGroup}
/>
Broadcast
</label>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
{notesBroadcast
? "Notifies every agent in the group."
: "Notifies leads + mentions."}
</p>
</div>
<div className="flex-1 space-y-4 overflow-y-auto rounded-2xl border border-slate-200 bg-white p-4">
<div className="flex-1 space-y-4 overflow-y-auto rounded-2xl border border-border bg-card p-4">
{notesHistoryQuery.error ? (
<div className="rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
{notesHistoryQuery.error.message}
@ -1257,9 +1257,9 @@ export default function BoardGroupDetailPage() {
</div>
) : null}
{notesHistoryQuery.isLoading && notesMessages.length === 0 ? (
<p className="text-sm text-slate-500">Loading</p>
<p className="text-sm text-muted-foreground">Loading</p>
) : notesMessages.length === 0 ? (
<p className="text-sm text-slate-500">
<p className="text-sm text-muted-foreground">
No notes yet. Post a note or a broadcast to share context
across boards.
</p>

View File

@ -133,11 +133,11 @@ export default function NewBoardGroupPage() {
>
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Group name <span className="text-red-500">*</span>
</label>
<Input
@ -150,7 +150,7 @@ export default function NewBoardGroupPage() {
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Description
</label>
<Textarea
@ -164,8 +164,8 @@ export default function NewBoardGroupPage() {
<div className="space-y-2">
<div className="flex flex-wrap items-center justify-between gap-2">
<label className="text-sm font-medium text-slate-900">Boards</label>
<span className="text-xs text-slate-500">
<label className="text-sm font-medium text-foreground">Boards</label>
<span className="text-xs text-muted-foreground">
{selectedBoardIds.size} selected
</span>
</div>
@ -175,9 +175,9 @@ export default function NewBoardGroupPage() {
placeholder="Search boards..."
disabled={isCreating}
/>
<div className="max-h-64 overflow-auto rounded-xl border border-slate-200 bg-slate-50/40">
<div className="max-h-64 overflow-auto rounded-xl border border-border bg-muted/40">
{boardsQuery.isLoading ? (
<div className="px-4 py-6 text-sm text-slate-500">
<div className="px-4 py-6 text-sm text-muted-foreground">
Loading boards
</div>
) : boardsQuery.error ? (
@ -185,7 +185,7 @@ export default function NewBoardGroupPage() {
{boardsQuery.error.message}
</div>
) : boards.length === 0 ? (
<div className="px-4 py-6 text-sm text-slate-500">
<div className="px-4 py-6 text-sm text-muted-foreground">
No boards found.
</div>
) : (
@ -207,7 +207,7 @@ export default function NewBoardGroupPage() {
<label className="flex cursor-pointer items-start gap-3">
<input
type="checkbox"
className="mt-1 h-4 w-4 rounded border-slate-300 text-blue-600"
className="mt-1 h-4 w-4 rounded border-input text-primary"
checked={checked}
onChange={() => {
setSelectedBoardIds((prev) => {
@ -223,11 +223,11 @@ export default function NewBoardGroupPage() {
disabled={isCreating}
/>
<div className="min-w-0">
<p className="truncate text-sm font-medium text-slate-900">
<p className="truncate text-sm font-medium text-foreground">
{board.name}
</p>
<div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-slate-500">
<span className="font-mono text-[11px] text-slate-400">
<div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
<span className="font-mono text-[11px] text-muted-foreground/70">
{board.id}
</span>
{isAlreadyGrouped ? (
@ -244,7 +244,7 @@ export default function NewBoardGroupPage() {
</ul>
)}
</div>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Optional. Selected boards will be assigned to this group after
creation. You can change membership later in group edit or board
settings.
@ -267,11 +267,11 @@ export default function NewBoardGroupPage() {
</Button>
</div>
<div className="border-t border-slate-100 pt-4 text-xs text-slate-500">
<div className="border-t border-border pt-4 text-xs text-muted-foreground">
Want to assign boards later? Update each board in{" "}
<Link
href="/boards"
className="font-medium text-blue-600 hover:text-blue-700"
className="font-medium text-primary hover:text-primary"
>
Boards
</Link>{" "}

View File

@ -102,7 +102,7 @@ export default function BoardGroupsPage() {
}
stickyHeader
>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<BoardGroupsTable
groups={groups}
isLoading={groupsQuery.isLoading}

View File

@ -38,9 +38,9 @@ export function TaskCustomFieldsEditor({
emptyMessage = "No custom fields configured for this board.",
}: TaskCustomFieldsEditorProps) {
if (isLoading)
return <p className="text-xs text-slate-500">{loadingMessage}</p>;
return <p className="text-xs text-muted-foreground">{loadingMessage}</p>;
if (definitions.length === 0) {
return <p className="text-xs text-slate-500">{emptyMessage}</p>;
return <p className="text-xs text-muted-foreground">{emptyMessage}</p>;
}
return (
@ -51,7 +51,7 @@ export function TaskCustomFieldsEditor({
return (
<div key={definition.id} className="space-y-1">
<label className="text-[11px] font-semibold uppercase tracking-wide text-slate-500">
<label className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
{definition.label || definition.field_key}
{definition.required === true ? (
<span className="ml-1 text-rose-600">*</span>
@ -145,7 +145,7 @@ export function TaskCustomFieldsEditor({
)}
{definition.description ? (
<p className="text-xs text-slate-500">{definition.description}</p>
<p className="text-xs text-muted-foreground">{definition.description}</p>
) : null}
</div>
);

View File

@ -32,7 +32,7 @@ export default function BoardApprovalsPage() {
</SignedOut>
<SignedIn>
<DashboardSidebar />
<main className="flex-1 overflow-y-auto bg-gradient-to-br from-slate-50 to-slate-100">
<main className="flex-1 overflow-y-auto bg-background">
<div className="p-4 md:p-6">
{boardId ? (
<div className="h-[calc(100vh-160px)] min-h-[300px] sm:min-h-[520px]">

View File

@ -142,7 +142,7 @@ export const formatCustomFieldDetailValue = (
href={parsedUrl.toString()}
target="_blank"
rel="noreferrer"
className="inline-flex items-center gap-1 text-blue-700 underline decoration-blue-300 underline-offset-2 hover:text-blue-800"
className="inline-flex items-center gap-1 text-primary underline decoration-primary/40 underline-offset-2 hover:text-primary"
>
<span className="break-all">{parsedUrl.toString()}</span>
<ArrowUpRight className="h-3.5 w-3.5 flex-shrink-0" />
@ -157,7 +157,7 @@ export const formatCustomFieldDetailValue = (
try {
const normalized = typeof value === "string" ? JSON.parse(value) : value;
return (
<pre className="whitespace-pre-wrap break-words rounded border border-slate-200 bg-white px-2 py-1 font-mono text-xs leading-relaxed text-slate-800">
<pre className="whitespace-pre-wrap break-words rounded border border-border bg-card px-2 py-1 font-mono text-xs leading-relaxed text-foreground">
{JSON.stringify(normalized, null, 2)}
</pre>
);

View File

@ -137,10 +137,10 @@ function WebhookCard({
return (
<div
key={webhook.id}
className="space-y-3 rounded-lg border border-slate-200 px-4 py-4"
className="space-y-3 rounded-lg border border-border px-4 py-4"
>
<div className="flex flex-wrap items-center justify-between gap-2">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Webhook {webhook.id.slice(0, 8)}
</span>
<div className="flex items-center gap-2">
@ -218,7 +218,7 @@ function WebhookCard({
disabled={isBusy}
/>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">Agent</label>
<label className="text-sm font-medium text-foreground">Agent</label>
<Select
value={draftAgentValue}
onValueChange={setDraftAgentValue}
@ -243,19 +243,19 @@ function WebhookCard({
</>
) : (
<>
<div className="text-sm text-slate-700">
<div className="text-sm text-muted-foreground">
<Markdown
content={webhook.description || ""}
variant="description"
/>
</div>
<p className="text-xs text-slate-600">
<p className="text-xs text-muted-foreground">
Recipient: {mappedAgent?.name ?? "Lead agent"}
</p>
</>
)}
<div className="rounded-md bg-slate-50 px-3 py-2">
<code className="break-all text-xs text-slate-700">
<div className="rounded-md bg-muted px-3 py-2">
<code className="break-all text-xs text-muted-foreground">
{webhook.endpoint_url ?? webhook.endpoint_path}
</code>
</div>
@ -770,7 +770,7 @@ export default function EditBoardPage() {
<div className="space-y-6">
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
{resolvedBoardType !== "general" &&
baseBoard &&
@ -796,7 +796,7 @@ export default function EditBoardPage() {
) : null}
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board name <span className="text-red-500">*</span>
</label>
<Input
@ -807,7 +807,7 @@ export default function EditBoardPage() {
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Gateway <span className="text-red-500">*</span>
</label>
<SearchableSelect
@ -827,7 +827,7 @@ export default function EditBoardPage() {
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board type
</label>
<Select value={resolvedBoardType} onValueChange={setBoardType}>
@ -840,7 +840,7 @@ export default function EditBoardPage() {
</SelectContent>
</Select>
<div className="space-y-2 pt-1">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Max worker agents
</label>
<Input
@ -861,7 +861,7 @@ export default function EditBoardPage() {
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board group
</label>
<SearchableSelect
@ -877,14 +877,14 @@ export default function EditBoardPage() {
itemClassName="px-4 py-3"
disabled={isLoading}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Boards in the same group can share cross-board context for
agents.
</p>
</div>
{resolvedBoardType !== "general" ? (
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Target date
</label>
<Input
@ -898,7 +898,7 @@ export default function EditBoardPage() {
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Description <span className="text-red-500">*</span>
</label>
<Textarea
@ -913,7 +913,7 @@ export default function EditBoardPage() {
{resolvedBoardType !== "general" ? (
<>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Objective
{isGoalFieldsRequired && (
<span className="text-red-500"> *</span>
@ -929,7 +929,7 @@ export default function EditBoardPage() {
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Success metrics (JSON)
{isGoalFieldsRequired && (
<span className="text-red-500"> *</span>
@ -942,7 +942,7 @@ export default function EditBoardPage() {
className="min-h-[140px] font-mono text-xs"
disabled={isLoading}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Add key outcomes so the lead agent can measure progress.
</p>
{metricsError ? (
@ -952,16 +952,16 @@ export default function EditBoardPage() {
</>
) : null}
<section className="space-y-3 border-t border-slate-200 pt-4">
<section className="space-y-3 border-t border-border pt-4">
<div>
<h2 className="text-base font-semibold text-slate-900">
<h2 className="text-base font-semibold text-foreground">
Rules
</h2>
<p className="text-xs text-slate-600">
<p className="text-xs text-muted-foreground">
Configure board-level workflow enforcement.
</p>
</div>
<div className="flex items-start gap-3 rounded-lg border border-slate-200 px-3 py-3">
<div className="flex items-start gap-3 rounded-lg border border-border px-3 py-3">
<button
type="button"
role="switch"
@ -974,11 +974,11 @@ export default function EditBoardPage() {
className={`mt-0.5 inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
resolvedRequireApprovalForDone
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
resolvedRequireApprovalForDone
? "translate-x-5"
: "translate-x-0.5"
@ -986,17 +986,17 @@ export default function EditBoardPage() {
/>
</button>
<span className="space-y-1">
<span className="block text-sm font-medium text-slate-900">
<span className="block text-sm font-medium text-foreground">
Require approval
</span>
<span className="block text-xs text-slate-600">
<span className="block text-xs text-muted-foreground">
Require at least one linked approval in{" "}
<code>approved</code> state before a task can be marked{" "}
<code>done</code>.
</span>
</span>
</div>
<div className="flex items-start gap-3 rounded-lg border border-slate-200 px-3 py-3">
<div className="flex items-start gap-3 rounded-lg border border-border px-3 py-3">
<button
type="button"
role="switch"
@ -1009,11 +1009,11 @@ export default function EditBoardPage() {
className={`mt-0.5 inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
resolvedRequireReviewBeforeDone
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
resolvedRequireReviewBeforeDone
? "translate-x-5"
: "translate-x-0.5"
@ -1021,16 +1021,16 @@ export default function EditBoardPage() {
/>
</button>
<span className="space-y-1">
<span className="block text-sm font-medium text-slate-900">
<span className="block text-sm font-medium text-foreground">
Require review before done
</span>
<span className="block text-xs text-slate-600">
<span className="block text-xs text-muted-foreground">
Tasks must move to <code>review</code> before they can be
marked <code>done</code>.
</span>
</span>
</div>
<div className="flex items-start gap-3 rounded-lg border border-slate-200 px-3 py-3">
<div className="flex items-start gap-3 rounded-lg border border-border px-3 py-3">
<button
type="button"
role="switch"
@ -1045,11 +1045,11 @@ export default function EditBoardPage() {
className={`mt-0.5 inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
resolvedCommentRequiredForReview
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
resolvedCommentRequiredForReview
? "translate-x-5"
: "translate-x-0.5"
@ -1057,16 +1057,16 @@ export default function EditBoardPage() {
/>
</button>
<span className="space-y-1">
<span className="block text-sm font-medium text-slate-900">
<span className="block text-sm font-medium text-foreground">
Require comment for review
</span>
<span className="block text-xs text-slate-600">
<span className="block text-xs text-muted-foreground">
Require a task comment when moving status to{" "}
<code>review</code>.
</span>
</span>
</div>
<div className="flex items-start gap-3 rounded-lg border border-slate-200 px-3 py-3">
<div className="flex items-start gap-3 rounded-lg border border-border px-3 py-3">
<button
type="button"
role="switch"
@ -1081,11 +1081,11 @@ export default function EditBoardPage() {
className={`mt-0.5 inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
resolvedBlockStatusChangesWithPendingApproval
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
resolvedBlockStatusChangesWithPendingApproval
? "translate-x-5"
: "translate-x-0.5"
@ -1093,16 +1093,16 @@ export default function EditBoardPage() {
/>
</button>
<span className="space-y-1">
<span className="block text-sm font-medium text-slate-900">
<span className="block text-sm font-medium text-foreground">
Block status changes with pending approval
</span>
<span className="block text-xs text-slate-600">
<span className="block text-xs text-muted-foreground">
Prevent status transitions while any linked approval is in{" "}
<code>pending</code> state.
</span>
</span>
</div>
<div className="flex items-start gap-3 rounded-lg border border-slate-200 px-3 py-3">
<div className="flex items-start gap-3 rounded-lg border border-border px-3 py-3">
<button
type="button"
role="switch"
@ -1115,11 +1115,11 @@ export default function EditBoardPage() {
className={`mt-0.5 inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
resolvedOnlyLeadCanChangeStatus
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
resolvedOnlyLeadCanChangeStatus
? "translate-x-5"
: "translate-x-0.5"
@ -1127,10 +1127,10 @@ export default function EditBoardPage() {
/>
</button>
<span className="space-y-1">
<span className="block text-sm font-medium text-slate-900">
<span className="block text-sm font-medium text-foreground">
Only lead can change status
</span>
<span className="block text-xs text-slate-600">
<span className="block text-xs text-muted-foreground">
Restrict status changes to the board lead.
</span>
</span>
@ -1138,7 +1138,7 @@ export default function EditBoardPage() {
</section>
{gateways.length === 0 ? (
<div className="rounded-lg border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600">
<div className="rounded-lg border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
<p>
No gateways available. Create one in Gateways to continue.
</p>
@ -1166,18 +1166,18 @@ export default function EditBoardPage() {
</Button>
</div>
<section className="space-y-4 border-t border-slate-200 pt-4">
<section className="space-y-4 border-t border-border pt-4">
<div>
<h2 className="text-base font-semibold text-slate-900">
<h2 className="text-base font-semibold text-foreground">
Webhooks
</h2>
<p className="text-xs text-slate-600">
<p className="text-xs text-muted-foreground">
Add inbound webhook endpoints so the lead agent can react to
external events.
</p>
</div>
<div className="space-y-3 rounded-lg border border-slate-200 px-4 py-4">
<label className="text-sm font-medium text-slate-900">
<div className="space-y-3 rounded-lg border border-border px-4 py-4">
<label className="text-sm font-medium text-foreground">
Lead agent instruction
</label>
<Textarea
@ -1190,7 +1190,7 @@ export default function EditBoardPage() {
disabled={isLoading || isWebhookBusy}
/>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Agent
</label>
<Select
@ -1237,11 +1237,11 @@ export default function EditBoardPage() {
) : null}
{webhooksQuery.isLoading ? (
<p className="text-sm text-slate-500">Loading webhooks</p>
<p className="text-sm text-muted-foreground">Loading webhooks</p>
) : null}
{!webhooksQuery.isLoading && webhooks.length === 0 ? (
<p className="rounded-lg border border-dashed border-slate-300 px-4 py-3 text-sm text-slate-600">
<p className="rounded-lg border border-dashed border-input px-4 py-3 text-sm text-muted-foreground">
No webhooks configured yet.
</p>
) : null}
@ -1282,7 +1282,7 @@ export default function EditBoardPage() {
<DialogClose asChild>
<button
type="button"
className="sticky top-4 z-10 ml-auto rounded-lg border border-slate-200 bg-[color:var(--surface)] p-2 text-slate-500 transition hover:bg-slate-50"
className="sticky top-4 z-10 ml-auto rounded-lg border border-border bg-[color:var(--surface)] p-2 text-muted-foreground transition hover:bg-muted"
aria-label="Close onboarding"
>
<X className="h-4 w-4" />
@ -1295,7 +1295,7 @@ export default function EditBoardPage() {
onConfirmed={handleOnboardingConfirmed}
/>
) : (
<div className="rounded-lg border border-slate-200 bg-slate-50 p-3 text-sm text-slate-600">
<div className="rounded-lg border border-border bg-muted p-3 text-sm text-muted-foreground">
Unable to start onboarding.
</div>
)}

File diff suppressed because it is too large Load Diff

View File

@ -111,13 +111,13 @@ export default function WebhookPayloadsPage() {
isAdmin={isAdmin}
adminOnlyMessage="Only organization owners and admins can view webhook payloads."
>
<div className="space-y-4 rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
<div className="space-y-4 rounded-xl border border-border bg-card p-6 shadow-sm">
<div className="flex flex-wrap items-start justify-between gap-3">
<div className="space-y-1">
<h2 className="text-base font-semibold text-slate-900">
<h2 className="text-base font-semibold text-foreground">
{payloadTitle}
</h2>
<p className="text-sm text-slate-600">
<p className="text-sm text-muted-foreground">
{webhook?.description ?? "Loading webhook details..."}
</p>
</div>
@ -131,15 +131,15 @@ export default function WebhookPayloadsPage() {
</div>
{webhook ? (
<div className="rounded-md bg-slate-50 px-3 py-2">
<code className="break-all text-xs text-slate-700">
<div className="rounded-md bg-muted px-3 py-2">
<code className="break-all text-xs text-muted-foreground">
{webhook.endpoint_url ?? webhook.endpoint_path}
</code>
</div>
) : null}
<div className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-slate-200 px-3 py-2">
<p className="text-sm text-slate-700">
<div className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-border px-3 py-2">
<p className="text-sm text-muted-foreground">
{total} payload{total === 1 ? "" : "s"} total
</p>
<div className="flex items-center gap-2">
@ -153,7 +153,7 @@ export default function WebhookPayloadsPage() {
>
Previous
</Button>
<span className="text-xs text-slate-600">
<span className="text-xs text-muted-foreground">
Page {currentPage} of {pageCount}
</span>
<Button
@ -172,11 +172,11 @@ export default function WebhookPayloadsPage() {
) : null}
{isLoading ? (
<p className="text-sm text-slate-500">Loading payloads...</p>
<p className="text-sm text-muted-foreground">Loading payloads...</p>
) : null}
{!isLoading && payloads.length === 0 ? (
<p className="rounded-lg border border-dashed border-slate-300 px-4 py-3 text-sm text-slate-600">
<p className="rounded-lg border border-dashed border-input px-4 py-3 text-sm text-muted-foreground">
No payloads received for this webhook yet.
</p>
) : null}
@ -185,17 +185,17 @@ export default function WebhookPayloadsPage() {
{payloads.map((payload: BoardWebhookPayloadRead) => (
<div
key={payload.id}
className="space-y-3 rounded-lg border border-slate-200 px-4 py-4"
className="space-y-3 rounded-lg border border-border px-4 py-4"
>
<div className="flex flex-wrap items-center justify-between gap-2">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Payload {payload.id.slice(0, 8)}
</span>
<span className="text-xs text-slate-500">
<span className="text-xs text-muted-foreground">
{new Date(payload.received_at).toLocaleString()}
</span>
</div>
<div className="grid gap-2 text-xs text-slate-600 md:grid-cols-2">
<div className="grid gap-2 text-xs text-muted-foreground md:grid-cols-2">
<p>
Content type:{" "}
<code>{payload.content_type ?? "not provided"}</code>
@ -204,7 +204,7 @@ export default function WebhookPayloadsPage() {
Source IP: <code>{payload.source_ip ?? "not provided"}</code>
</p>
</div>
<pre className="max-h-96 overflow-auto rounded-md bg-slate-900/95 p-3 text-xs text-slate-100">
<pre className="max-h-96 overflow-auto rounded-md bg-foreground/95 p-3 text-xs text-background">
{stringifyPayload(payload.payload)}
</pre>
</div>

View File

@ -161,12 +161,12 @@ export default function NewBoardPage() {
>
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
<div className="space-y-4">
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board name <span className="text-red-500">*</span>
</label>
<Input
@ -177,7 +177,7 @@ export default function NewBoardPage() {
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Gateway <span className="text-red-500">*</span>
</label>
<SearchableSelect
@ -197,7 +197,7 @@ export default function NewBoardPage() {
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Board group
</label>
<SearchableSelect
@ -213,14 +213,14 @@ export default function NewBoardPage() {
itemClassName="px-4 py-3"
disabled={isLoading}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Optional. Groups increase cross-board visibility.
</p>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Description <span className="text-red-500">*</span>
</label>
<Textarea
@ -234,12 +234,12 @@ export default function NewBoardPage() {
</div>
{gateways.length === 0 ? (
<div className="rounded-lg border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600">
<div className="rounded-lg border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
<p>
No gateways available. Create one in{" "}
<Link
href="/gateways"
className="font-medium text-blue-600 hover:text-blue-700"
className="font-medium text-primary hover:text-primary"
>
Gateways
</Link>{" "}

View File

@ -134,7 +134,7 @@ export default function BoardsPage() {
}
stickyHeader
>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<BoardsTable
boards={boards}
boardGroups={groups}

View File

@ -129,7 +129,7 @@ export default function EditCustomFieldPage() {
stickyHeader
>
{customFieldsQuery.isLoading ? (
<div className="max-w-3xl rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-500 shadow-sm">
<div className="max-w-3xl rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Loading custom field
</div>
) : null}

View File

@ -101,7 +101,7 @@ export default function CustomFieldsPage() {
adminOnlyMessage="Only organization owners and admins can manage custom fields."
stickyHeader
>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<CustomFieldsTable
fields={customFields}
isLoading={customFieldsQuery.isLoading}

View File

@ -185,7 +185,7 @@ export default function GatewayDetailPage() {
adminOnlyMessage="Only organization owners and admins can access gateways."
>
{gatewayQuery.isLoading ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-500 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Loading gateway
</div>
) : gatewayQuery.error ? (
@ -195,16 +195,16 @@ export default function GatewayDetailPage() {
) : gateway ? (
<div className="space-y-6">
<div className="grid gap-6 lg:grid-cols-2">
<div className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 shadow-sm">
<div className="flex items-center justify-between">
<p className="text-xs font-semibold uppercase tracking-wide text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Connection
</p>
<div className="flex items-center gap-2 text-xs text-slate-500">
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<span
className={`h-2 w-2 rounded-full ${
statusQuery.isLoading
? "bg-slate-300"
? "bg-muted-foreground/40"
: isConnected
? "bg-emerald-500"
: "bg-rose-500"
@ -219,59 +219,59 @@ export default function GatewayDetailPage() {
</span>
</div>
</div>
<div className="mt-4 space-y-3 text-sm text-slate-700">
<div className="mt-4 space-y-3 text-sm text-muted-foreground">
<div>
<p className="text-xs uppercase text-slate-400">
<p className="text-xs uppercase text-muted-foreground/70">
Gateway URL
</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="mt-1 text-sm font-medium text-foreground">
{gateway.url}
</p>
</div>
<div>
<p className="text-xs uppercase text-slate-400">Token</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="text-xs uppercase text-muted-foreground/70">Token</p>
<p className="mt-1 text-sm font-medium text-foreground">
{maskToken(gateway.token)}
</p>
</div>
<div>
<p className="text-xs uppercase text-slate-400">
<p className="text-xs uppercase text-muted-foreground/70">
Device pairing
</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="mt-1 text-sm font-medium text-foreground">
{gateway.disable_device_pairing ? "Disabled" : "Required"}
</p>
</div>
</div>
</div>
<div className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
<p className="text-xs font-semibold uppercase tracking-wide text-slate-500">
<div className="rounded-xl border border-border bg-card p-6 shadow-sm">
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Runtime
</p>
<div className="mt-4 space-y-3 text-sm text-slate-700">
<div className="mt-4 space-y-3 text-sm text-muted-foreground">
<div>
<p className="text-xs uppercase text-slate-400">
<p className="text-xs uppercase text-muted-foreground/70">
Workspace root
</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="mt-1 text-sm font-medium text-foreground">
{gateway.workspace_root}
</p>
</div>
<div className="grid gap-3 sm:grid-cols-2">
<div>
<p className="text-xs uppercase text-slate-400">
<p className="text-xs uppercase text-muted-foreground/70">
Created
</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="mt-1 text-sm font-medium text-foreground">
{formatTimestamp(gateway.created_at)}
</p>
</div>
<div>
<p className="text-xs uppercase text-slate-400">
<p className="text-xs uppercase text-muted-foreground/70">
Updated
</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="mt-1 text-sm font-medium text-foreground">
{formatTimestamp(gateway.updated_at)}
</p>
</div>
@ -280,15 +280,15 @@ export default function GatewayDetailPage() {
</div>
</div>
<div className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 shadow-sm">
<div className="flex items-center justify-between">
<p className="text-xs font-semibold uppercase tracking-wide text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Agents
</p>
{agentsQuery.isLoading ? (
<span className="text-xs text-slate-500">Loading</span>
<span className="text-xs text-muted-foreground">Loading</span>
) : (
<span className="text-xs text-slate-500">
<span className="text-xs text-muted-foreground">
{agents.length} total
</span>
)}

View File

@ -113,7 +113,7 @@ export default function GatewaysPage() {
adminOnlyMessage="Only organization owners and admins can access gateways."
stickyHeader
>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<GatewaysTable
gateways={gateways}
isLoading={gatewaysQuery.isLoading}

View File

@ -170,7 +170,7 @@ export default function ForgejoConnectionsEditPage({
errorMessage={deleteError}
confirmLabel="Delete Connection"
confirmingLabel="Deleting…"
confirmClassName="bg-[color:var(--danger)] text-white hover:bg-[color:var(--danger)]/90"
confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
cancelLabel="Keep Connection"
/>
</DashboardPageLayout>

View File

@ -175,7 +175,7 @@ export default function ForgejoConnectionsPage() {
errorMessage={deleteError}
confirmLabel="Delete Connection"
confirmingLabel="Deleting…"
confirmClassName="bg-[color:var(--danger)] text-white hover:bg-[color:var(--danger)]/90"
confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
cancelLabel="Keep Connection"
/>
</>

View File

@ -177,7 +177,7 @@ export default function ForgejoRepositoriesEditPage({
errorMessage={deleteError}
confirmLabel="Delete Repository"
confirmingLabel="Deleting…"
confirmClassName="bg-[color:var(--danger)] text-white hover:bg-[color:var(--danger)]/90"
confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
cancelLabel="Keep Repository"
/>
</DashboardPageLayout>

View File

@ -201,7 +201,7 @@ export default function ForgejoRepositoriesPage() {
errorMessage={deleteError}
confirmLabel="Delete Repository"
confirmingLabel="Deleting…"
confirmClassName="bg-[color:var(--danger)] text-white hover:bg-[color:var(--danger)]/90"
confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
cancelLabel="Keep Repository"
/>
</>

View File

@ -152,7 +152,7 @@ export default function InvitePage() {
<Suspense
fallback={
<div className="min-h-screen bg-app text-strong">
<header className="border-b border-[color:var(--border)] bg-white">
<header className="border-b border-[color:var(--border)] bg-card">
<div className="mx-auto flex max-w-5xl items-center justify-between px-6 py-4">
<BrandMark />
</div>

View File

@ -5,8 +5,8 @@ export default function Loading() {
className="flex min-h-screen items-center justify-center bg-app px-6"
>
<div className="flex flex-col items-center gap-3">
<div className="h-10 w-10 animate-spin rounded-full border-2 border-slate-200 border-t-[var(--accent)]" />
<p className="text-sm text-slate-500">Loading pipeline...</p>
<div className="h-10 w-10 animate-spin rounded-full border-2 border-border border-t-[var(--accent)]" />
<p className="text-sm text-muted-foreground">Loading pipeline...</p>
</div>
</div>
);

View File

@ -115,12 +115,12 @@ export default function OnboardingPage() {
<DashboardShell>
<SignedOut>
<div className="lg:col-span-2 flex min-h-[70vh] items-center justify-center">
<div className="w-full max-w-2xl rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="border-b border-slate-100 px-6 py-5">
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
<div className="w-full max-w-2xl rounded-xl border border-border bg-card shadow-sm">
<div className="border-b border-border px-6 py-5">
<h1 className="text-2xl font-semibold tracking-tight text-foreground">
Pipeline profile
</h1>
<p className="mt-1 text-sm text-slate-600">
<p className="mt-1 text-sm text-muted-foreground">
Sign in to configure your profile and timezone.
</p>
</div>
@ -138,12 +138,12 @@ export default function OnboardingPage() {
</SignedOut>
<SignedIn>
<div className="lg:col-span-2 flex min-h-[70vh] items-center justify-center">
<section className="w-full max-w-2xl rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="border-b border-slate-100 px-6 py-5">
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
<section className="w-full max-w-2xl rounded-xl border border-border bg-card shadow-sm">
<div className="border-b border-border px-6 py-5">
<h1 className="text-2xl font-semibold tracking-tight text-foreground">
Pipeline profile
</h1>
<p className="mt-1 text-sm text-slate-600">
<p className="mt-1 text-sm text-muted-foreground">
Configure your Pipeline settings and preferences.
</p>
</div>
@ -151,8 +151,8 @@ export default function OnboardingPage() {
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-700 flex items-center gap-2">
<User className="h-4 w-4 text-slate-500" />
<label className="text-sm font-medium text-muted-foreground flex items-center gap-2">
<User className="h-4 w-4 text-muted-foreground" />
Name
<span className="text-red-500">*</span>
</label>
@ -161,12 +161,12 @@ export default function OnboardingPage() {
onChange={(event) => setName(event.target.value)}
placeholder="Enter your name"
disabled={isLoading}
className="border-slate-300 text-slate-900 focus-visible:ring-blue-500"
className="border-input text-foreground focus-visible:ring-ring"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-700 flex items-center gap-2">
<Globe className="h-4 w-4 text-slate-500" />
<label className="text-sm font-medium text-muted-foreground flex items-center gap-2">
<Globe className="h-4 w-4 text-muted-foreground" />
Timezone
<span className="text-red-500">*</span>
</label>
@ -185,8 +185,8 @@ export default function OnboardingPage() {
</div>
</div>
<div className="rounded-lg border border-blue-200 bg-blue-50 p-4 text-sm text-blue-800 flex items-start gap-3">
<Info className="mt-0.5 h-4 w-4 text-blue-600" />
<div className="flex items-start gap-3 rounded-lg border border-border bg-muted p-4 text-sm text-muted-foreground">
<Info className="mt-0.5 h-4 w-4 text-primary" />
<p>
<strong>Note:</strong> Your timezone is used to display all
timestamps and schedule mission-critical events accurately.
@ -194,7 +194,7 @@ export default function OnboardingPage() {
</div>
{errorMessage ? (
<div className="rounded-lg border border-slate-200 bg-slate-50 p-3 text-xs text-slate-600">
<div className="rounded-lg border border-border bg-muted p-3 text-xs text-muted-foreground">
{errorMessage}
</div>
) : null}
@ -202,26 +202,27 @@ export default function OnboardingPage() {
<div className="flex flex-wrap gap-3 pt-2">
<Button
type="submit"
className="flex-1 bg-blue-600 text-white hover:bg-blue-700 py-2.5"
className="flex-1 py-2.5"
disabled={isLoading || requiredMissing}
>
<Save className="h-4 w-4" />
{isLoading ? "Saving…" : "Save Profile"}
</Button>
<button
<Button
type="button"
variant="outline"
onClick={() => {
setName("");
setTimezone("");
setError(null);
}}
className="flex-1 rounded-md border border-slate-300 px-4 py-2.5 text-sm font-medium text-slate-700 transition-colors hover:bg-slate-50"
className="flex-1 py-2.5"
>
<span className="inline-flex items-center gap-2">
<RotateCcw className="h-4 w-4" />
Reset
</span>
</button>
</Button>
</div>
</form>
</div>

View File

@ -157,17 +157,17 @@ function BoardAccessEditor({
return (
<div className="space-y-3">
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Board access
</p>
<div className="mt-3 inline-flex rounded-xl border border-slate-200 bg-slate-100 p-1">
<div className="mt-3 inline-flex rounded-xl border border-border bg-accent p-1">
<button
type="button"
className={cn(
"rounded-md px-3 py-1.5 text-xs font-semibold transition",
scope === "all"
? "bg-white text-slate-900 shadow-sm"
: "text-slate-500 hover:text-slate-700",
? "bg-card text-foreground shadow-sm"
: "text-muted-foreground hover:text-muted-foreground",
)}
onClick={() => onScopeChange("all")}
disabled={disabled}
@ -179,8 +179,8 @@ function BoardAccessEditor({
className={cn(
"rounded-md px-3 py-1.5 text-xs font-semibold transition",
scope === "custom"
? "bg-white text-slate-900 shadow-sm"
: "text-slate-500 hover:text-slate-700",
? "bg-card text-foreground shadow-sm"
: "text-muted-foreground hover:text-muted-foreground",
)}
onClick={() => onScopeChange("custom")}
disabled={disabled}
@ -191,8 +191,8 @@ function BoardAccessEditor({
</div>
{scope === "all" ? (
<div className="flex flex-wrap items-center gap-6 rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm">
<label className="flex items-center gap-2 text-slate-600">
<div className="flex flex-wrap items-center gap-6 rounded-xl border border-border bg-card px-4 py-2.5 text-sm">
<label className="flex items-center gap-2 text-muted-foreground">
<input
type="checkbox"
className="h-4 w-4"
@ -202,7 +202,7 @@ function BoardAccessEditor({
/>
Read
</label>
<label className="flex items-center gap-2 text-slate-600">
<label className="flex items-center gap-2 text-muted-foreground">
<input
type="checkbox"
className="h-4 w-4"
@ -212,18 +212,18 @@ function BoardAccessEditor({
/>
Write
</label>
<span className="text-xs text-slate-500">
<span className="text-xs text-muted-foreground">
Write access implies read permissions.
</span>
</div>
) : (
<div>
{boards.length === 0 ? (
<div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-500">
<div className="rounded-xl border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
{emptyMessage ?? "No boards available yet."}
</div>
) : (
<div className="overflow-hidden rounded-xl border border-slate-200">
<div className="overflow-hidden rounded-xl border border-border">
<BoardAccessTable
boards={boards}
access={access}
@ -702,13 +702,13 @@ export default function OrganizationPage() {
</SignedOut>
<SignedIn>
<DashboardSidebar />
<main className="flex-1 overflow-y-auto bg-slate-50">
<div className="sticky top-0 z-30 border-b border-slate-200 bg-white">
<main className="flex-1 overflow-y-auto bg-muted">
<div className="sticky top-0 z-30 border-b border-border bg-card">
<div className="px-4 py-4 md:px-8 md:py-6">
<div className="flex flex-wrap items-center justify-between gap-6">
<div>
<div className="flex flex-wrap items-center gap-3">
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
<h1 className="text-2xl font-semibold tracking-tight text-foreground">
Organization
</h1>
<Badge
@ -719,24 +719,24 @@ export default function OrganizationPage() {
{orgName}
</Badge>
</div>
<p className="mt-1 text-sm text-slate-500">
<p className="mt-1 text-sm text-muted-foreground">
Manage members and board access across your workspace.
</p>
<div className="mt-3 flex flex-wrap items-center gap-4 text-xs text-slate-500">
<div className="mt-3 flex flex-wrap items-center gap-4 text-xs text-muted-foreground">
<span>
<strong className="text-slate-900">
<strong className="text-foreground">
{members.length}
</strong>{" "}
members
</span>
<span>
<strong className="text-slate-900">
<strong className="text-foreground">
{boards.length}
</strong>{" "}
boards
</span>
<span>
<strong className="text-slate-900">
<strong className="text-foreground">
{invites.length}
</strong>{" "}
pending
@ -776,17 +776,17 @@ export default function OrganizationPage() {
</div>
<div className="px-4 py-4 md:px-8 md:py-8">
<div className="overflow-hidden rounded-2xl border border-slate-200 bg-white">
<div className="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 px-5 py-4">
<div className="overflow-hidden rounded-2xl border border-border bg-card">
<div className="flex flex-wrap items-center justify-between gap-3 border-b border-border px-5 py-4">
<div>
<h2 className="text-sm font-semibold text-slate-900">
<h2 className="text-sm font-semibold text-foreground">
Members & invites
</h2>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Invite teammates and tune their board permissions.
</p>
</div>
<div className="flex items-center gap-2 text-xs text-slate-500">
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<Users className="h-4 w-4" />
{members.length + invites.length} total
</div>
@ -829,7 +829,7 @@ export default function OrganizationPage() {
<form className="space-y-5" onSubmit={handleInviteSubmit}>
<div className="grid gap-4 sm:grid-cols-[1fr_200px]">
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Email address
</label>
<Input
@ -841,7 +841,7 @@ export default function OrganizationPage() {
/>
</div>
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Role
</label>
<Select value={inviteRole} onValueChange={setInviteRole}>
@ -893,7 +893,7 @@ export default function OrganizationPage() {
</DialogFooter>
</form>
) : (
<div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-500">
<div className="rounded-xl border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
Only organization admins can invite new members.
</div>
)}
@ -910,26 +910,26 @@ export default function OrganizationPage() {
</DialogHeader>
{memberDetailsQuery.isLoading ? (
<div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-500">
<div className="rounded-xl border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
Loading member access...
</div>
) : memberDetailsQuery.data?.status === 200 ? (
<div className="space-y-6">
<div className="rounded-xl border border-slate-200 bg-white px-5 py-4">
<p className="text-sm font-semibold text-slate-900">
<div className="rounded-xl border border-border bg-card px-5 py-4">
<p className="text-sm font-semibold text-foreground">
{memberDetailsQuery.data.data.user?.name ||
memberDetailsQuery.data.data.user?.preferred_name ||
memberDetailsQuery.data.data.user?.email ||
memberDetailsQuery.data.data.user_id}
</p>
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
{memberDetailsQuery.data.data.user?.email ??
"No email on file"}
</p>
</div>
<div className="space-y-3">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Role
</label>
<Select
@ -967,7 +967,7 @@ export default function OrganizationPage() {
) : null}
</div>
) : (
<div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-500">
<div className="rounded-xl border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
Unable to load member access.
</div>
)}

View File

@ -683,7 +683,7 @@ export default function GitProjectSettingsPage() {
errorMessage={deleteError}
confirmLabel="Delete"
confirmingLabel="Deleting…"
confirmClassName="bg-[color:var(--danger)] text-white hover:bg-[color:var(--danger)]/90"
confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
cancelLabel="Keep"
/>
</>

View File

@ -161,17 +161,17 @@ export default function SettingsPage() {
description="Update your profile and account preferences."
>
<div className="space-y-6">
<section className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
<h2 className="text-base font-semibold text-slate-900">Profile</h2>
<p className="mt-1 text-sm text-slate-500">
<section className="rounded-xl border border-border bg-card p-6 shadow-sm">
<h2 className="text-base font-semibold text-foreground">Profile</h2>
<p className="mt-1 text-sm text-muted-foreground">
Keep your identity and timezone up to date.
</p>
<form onSubmit={handleSave} className="mt-6 space-y-5">
<div className="grid gap-5 md:grid-cols-2">
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-medium text-slate-700">
<User className="h-4 w-4 text-slate-500" />
<label className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<User className="h-4 w-4 text-muted-foreground" />
Name
</label>
<Input
@ -182,12 +182,12 @@ export default function SettingsPage() {
}}
placeholder="Your name"
disabled={isSaving}
className="border-slate-300 [--input-bg:#fff] [--input-text:#0f172a] placeholder:text-slate-500 focus-visible:ring-blue-500"
className="border-input [--input-bg:var(--card)] [--input-text:var(--card-foreground)] placeholder:text-muted-foreground focus-visible:ring-ring"
/>
</div>
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-medium text-slate-700">
<Globe className="h-4 w-4 text-slate-500" />
<label className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<Globe className="h-4 w-4 text-muted-foreground" />
Timezone
</label>
<SearchableSelect
@ -210,15 +210,15 @@ export default function SettingsPage() {
</div>
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-medium text-slate-700">
<Mail className="h-4 w-4 text-slate-500" />
<label className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<Mail className="h-4 w-4 text-muted-foreground" />
Email
</label>
<Input
value={displayEmail}
readOnly
disabled
className="border-slate-200 [--input-bg:#f8fafc] [--input-text:#475569]"
className="border-border [--input-bg:var(--muted)] [--input-text:var(--muted-foreground)]"
/>
</div>
@ -251,14 +251,14 @@ export default function SettingsPage() {
</form>
</section>
<section className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
<section className="rounded-xl border border-border bg-card p-6 shadow-sm">
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div className="min-w-0">
<h2 className="flex items-center gap-2 text-base font-semibold text-slate-900">
<GitBranch className="h-4 w-4 text-slate-500" />
<h2 className="flex items-center gap-2 text-base font-semibold text-foreground">
<GitBranch className="h-4 w-4 text-muted-foreground" />
Git Projects
</h2>
<p className="mt-1 text-sm text-slate-500">
<p className="mt-1 text-sm text-muted-foreground">
Manage Forgejo connections, tracked repositories, and issue
sync.
</p>
@ -283,7 +283,7 @@ export default function SettingsPage() {
<div className="mt-4">
<Button
type="button"
className="bg-rose-600 text-white hover:bg-rose-700"
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
onClick={() => {
setDeleteError(null);
setDeleteDialogOpen(true);

View File

@ -21,7 +21,7 @@ export default function SignInPage() {
// Dedicated sign-in route for Cypress E2E.
// Avoids modal/iframe auth flows and gives Cypress a stable top-level page.
return (
<main className="flex min-h-screen items-center justify-center bg-slate-50 p-6">
<main className="flex min-h-screen items-center justify-center bg-muted p-6">
<SignIn
routing="path"
path="/sign-in"

View File

@ -788,8 +788,8 @@ export default function SkillsMarketplacePage() {
>
<div className="space-y-6">
{gateways.length === 0 ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-600 shadow-sm">
<p className="font-medium text-slate-900">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
<p className="font-medium text-foreground">
No gateways available yet.
</p>
<p className="mt-2">
@ -804,12 +804,12 @@ export default function SkillsMarketplacePage() {
</div>
) : (
<>
<div className="mb-5 rounded-xl border border-slate-200 bg-white p-4 shadow-sm">
<div className="mb-5 rounded-xl border border-border bg-card p-4 shadow-sm">
<div className="grid gap-4 md:grid-cols-[1fr_240px_240px]">
<div>
<label
htmlFor="marketplace-search"
className="mb-1 block text-sm font-medium text-slate-700"
className="mb-1 block text-sm font-medium text-muted-foreground"
>
Search
</label>
@ -824,7 +824,7 @@ export default function SkillsMarketplacePage() {
<div>
<label
htmlFor="marketplace-category-filter"
className="mb-1 block text-sm font-medium text-slate-700"
className="mb-1 block text-sm font-medium text-muted-foreground"
>
Category
</label>
@ -854,7 +854,7 @@ export default function SkillsMarketplacePage() {
<div>
<label
htmlFor="marketplace-risk-filter"
className="mb-1 block text-sm font-medium text-slate-700"
className="mb-1 block text-sm font-medium text-muted-foreground"
>
Risk
</label>
@ -880,7 +880,7 @@ export default function SkillsMarketplacePage() {
</div>
</div>
</div>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<MarketplaceSkillsTable
skills={filteredSkills}
installedGatewayNamesBySkillId={
@ -901,13 +901,13 @@ export default function SkillsMarketplacePage() {
}}
/>
</div>
<div className="flex items-center justify-between rounded-xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-600 shadow-sm">
<div className="flex items-center justify-between rounded-xl border border-border bg-card px-4 py-3 text-sm text-muted-foreground shadow-sm">
<div className="flex items-center gap-3">
<p>
Showing {rangeStart}-{rangeEnd} of {totalSkills}
</p>
<div className="flex items-center gap-2">
<span className="text-xs font-medium uppercase tracking-wide text-slate-500">
<span className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
Rows
</span>
<Select
@ -951,7 +951,7 @@ export default function SkillsMarketplacePage() {
>
Previous
</Button>
<span className="text-xs font-medium uppercase tracking-wide text-slate-500">
<span className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
{totalCountInfo.hasKnownTotal
? `Page ${currentPage} of ${totalPages}`
: `Page ${currentPage}`}

View File

@ -54,7 +54,7 @@ export default function EditSkillPackPage() {
stickyHeader
>
{packQuery.isLoading ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-500 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Loading pack...
</div>
) : packQuery.error ? (
@ -62,7 +62,7 @@ export default function EditSkillPackPage() {
{packQuery.error.message}
</div>
) : !pack ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-500 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Pack not found.
</div>
) : (

View File

@ -231,7 +231,7 @@ export default function SkillsPacksPage() {
stickyHeader
>
<div className="space-y-6">
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<SkillPacksTable
packs={packs}
isLoading={packsQuery.isLoading}

View File

@ -60,7 +60,7 @@ export default function EditTagPage() {
adminOnlyMessage="Only organization owners and admins can manage tags."
>
{tagQuery.isLoading ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-500 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Loading tag
</div>
) : tagQuery.error ? (
@ -68,7 +68,7 @@ export default function EditTagPage() {
{tagQuery.error.message}
</div>
) : !tag ? (
<div className="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-500 shadow-sm">
<div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
Tag not found.
</div>
) : (

View File

@ -100,7 +100,7 @@ export default function TagsPage() {
adminOnlyMessage="Only organization owners and admins can manage tags."
stickyHeader
>
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
<TagsTable
tags={tags}
isLoading={tagsQuery.isLoading}

View File

@ -134,14 +134,14 @@ const formatRubricTooltipValue = (
return (
<div className="flex w-full items-center justify-between gap-3">
<span className="flex items-center gap-2 text-slate-600">
<span className="flex items-center gap-2 text-muted-foreground">
<span
className="h-2.5 w-2.5 rounded-[2px]"
style={{ backgroundColor: indicatorColor }}
/>
<span>{label}</span>
</span>
<span className="font-mono font-medium tabular-nums text-slate-900">
<span className="font-mono font-medium tabular-nums text-foreground">
{displayValue}
</span>
</div>
@ -554,11 +554,11 @@ export function BoardApprovalsPanel({
</div>
) : null}
{loadingState ? (
<p className="text-sm text-slate-500">Loading approvals</p>
<p className="text-sm text-muted-foreground">Loading approvals</p>
) : pendingCount === 0 && resolvedCount === 0 ? (
<div
className={cn(
"rounded-xl border border-dashed border-slate-200 bg-white px-6 py-10 text-center",
"rounded-xl border border-dashed border-border bg-card px-6 py-10 text-center",
scrollable && "flex h-full items-center justify-center",
)}
>
@ -566,10 +566,10 @@ export function BoardApprovalsPanel({
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-emerald-50 text-emerald-600">
<CheckCircle2 className="h-6 w-6" />
</div>
<p className="mt-4 text-sm font-semibold text-slate-900">
<p className="mt-4 text-sm font-semibold text-foreground">
All clear
</p>
<p className="mt-2 text-sm text-slate-500">
<p className="mt-2 text-sm text-muted-foreground">
No approvals to review right now. New approvals will show up here
as soon as they arrive.
</p>
@ -584,15 +584,15 @@ export function BoardApprovalsPanel({
>
<div
className={cn(
"overflow-hidden rounded-xl border border-slate-200 bg-white",
"overflow-hidden rounded-xl border border-border bg-card",
scrollable && "flex min-h-0 flex-col",
)}
>
<div className="border-b border-slate-200 bg-slate-50 px-4 py-3">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<div className="border-b border-border bg-muted px-4 py-3">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Unapproved tasks
</p>
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
{pendingCount} pending · {resolvedCount} resolved
</p>
</div>
@ -632,13 +632,13 @@ export function BoardApprovalsPanel({
type="button"
onClick={() => setSelectedId(approval.id)}
className={cn(
"w-full px-4 py-4 text-left transition hover:bg-slate-50",
"w-full px-4 py-4 text-left transition hover:bg-muted",
isSelected && "bg-amber-50 border-l-2 border-amber-500",
!isPending && "opacity-60",
)}
>
<div className="flex items-start justify-between gap-3">
<span className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">
<span className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
{humanizeAction(approval.action_type)}
</span>
<span
@ -650,16 +650,16 @@ export function BoardApprovalsPanel({
{formatStatusLabel(approval.status)}
</span>
</div>
<p className="mt-2 text-sm font-semibold text-slate-900">
<p className="mt-2 text-sm font-semibold text-foreground">
{primaryLabel}
</p>
{boardText ? (
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
Board · {boardText}
</p>
) : null}
<div className="mt-2 flex items-center gap-2 text-xs text-slate-500">
<span className="rounded bg-slate-100 px-1.5 py-0.5 font-semibold text-slate-700">
<div className="mt-2 flex items-center gap-2 text-xs text-muted-foreground">
<span className="rounded bg-accent px-1.5 py-0.5 font-semibold text-muted-foreground">
{approval.confidence}% score
</span>
<Clock className="h-3.5 w-3.5 opacity-60" />
@ -673,19 +673,19 @@ export function BoardApprovalsPanel({
<div
className={cn(
"overflow-hidden rounded-xl border border-slate-200 bg-white",
"overflow-hidden rounded-xl border border-border bg-card",
scrollable && "flex min-h-0 flex-col",
)}
>
<div className="border-b border-slate-200 bg-slate-50 px-4 py-3">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<div className="border-b border-border bg-muted px-4 py-3">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
{selectedApproval?.status === "pending"
? "Latest unapproved task"
: "Approval detail"}
</p>
</div>
{!selectedApproval ? (
<div className="flex h-full items-center justify-center px-6 py-10 text-sm text-slate-500">
<div className="flex h-full items-center justify-center px-6 py-10 text-sm text-muted-foreground">
Select an approval to review details.
</div>
) : (
@ -755,10 +755,10 @@ export function BoardApprovalsPanel({
<div className="flex h-full flex-col gap-6 px-6 py-6">
<div className="flex flex-wrap items-start justify-between gap-3">
<div>
<p className="text-lg font-semibold text-slate-900">
<p className="text-lg font-semibold text-foreground">
{humanizeAction(selectedApproval.action_type)}
</p>
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
Requested{" "}
{formatTimestamp(selectedApproval.created_at)}
</p>
@ -781,7 +781,7 @@ export function BoardApprovalsPanel({
handleDecision(selectedApproval.id, "approved")
}
disabled={updatingId === selectedApproval.id}
className="bg-slate-900 text-white hover:bg-slate-800"
className="bg-foreground text-background hover:bg-foreground/90"
>
Approve
</Button>
@ -792,7 +792,7 @@ export function BoardApprovalsPanel({
handleDecision(selectedApproval.id, "rejected")
}
disabled={updatingId === selectedApproval.id}
className="border-slate-300 text-slate-700 hover:bg-slate-100"
className="border-input text-muted-foreground hover:bg-accent"
>
Reject
</Button>
@ -801,17 +801,17 @@ export function BoardApprovalsPanel({
</div>
</div>
<div className="flex items-center gap-3 rounded-lg border border-slate-200 bg-slate-50 px-4 py-3">
<div className="flex items-center gap-3 rounded-lg border border-border bg-muted px-4 py-3">
<StatusDot
status={selectedApproval.status}
variant="approval"
className={cn("h-2 w-2 rounded-full")}
/>
<div>
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Status
</p>
<p className="text-sm font-medium text-slate-700">
<p className="text-sm font-medium text-muted-foreground">
{formatStatusLabel(selectedApproval.status)} ·{" "}
{selectedApproval.status === "pending"
? "Awaiting your decision"
@ -822,10 +822,10 @@ export function BoardApprovalsPanel({
{titleText ? (
<div className="space-y-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Title
</p>
<div className="text-sm font-medium text-slate-900">
<div className="text-sm font-medium text-foreground">
{titleText}
</div>
</div>
@ -833,10 +833,10 @@ export function BoardApprovalsPanel({
{descriptionText ? (
<div className="space-y-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Description
</p>
<div className="rounded-lg border border-slate-200 bg-white px-4 py-3 text-sm text-slate-700">
<div className="rounded-lg border border-border bg-card px-4 py-3 text-sm text-muted-foreground">
{descriptionText}
</div>
</div>
@ -844,10 +844,10 @@ export function BoardApprovalsPanel({
{reasoningText ? (
<div className="space-y-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Lead reasoning
</p>
<div className="rounded-lg border border-slate-200 bg-white px-4 py-3 text-sm text-slate-600">
<div className="rounded-lg border border-border bg-card px-4 py-3 text-sm text-muted-foreground">
<p>{reasoningText}</p>
</div>
</div>
@ -855,7 +855,7 @@ export function BoardApprovalsPanel({
{relatedTasks.length > 0 ? (
<div className="space-y-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Related tasks
</p>
<div className="flex flex-wrap gap-2">
@ -866,7 +866,7 @@ export function BoardApprovalsPanel({
selectedApproval.board_id,
task.id,
)}
className="rounded-md border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 underline-offset-2 transition hover:border-slate-300 hover:bg-slate-50 hover:text-slate-900 hover:underline"
className="rounded-md border border-border bg-card px-2 py-1 text-xs text-muted-foreground underline-offset-2 transition hover:border-input hover:bg-muted hover:text-foreground hover:underline"
>
{task.title}
</Link>
@ -877,19 +877,19 @@ export function BoardApprovalsPanel({
{extraRows.length > 0 ? (
<div className="space-y-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Details
</p>
<div className="grid gap-3 sm:grid-cols-2">
{extraRows.map((row) => (
<div
key={`${selectedApproval.id}-${row.label}`}
className="rounded-lg border border-slate-200 bg-white px-3 py-2"
className="rounded-lg border border-border bg-card px-3 py-2"
>
<p className="text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-500">
<p className="text-[10px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
{row.label}
</p>
<p className="mt-1 text-sm font-medium text-slate-900">
<p className="mt-1 text-sm font-medium text-foreground">
{row.value}
</p>
</div>
@ -900,7 +900,7 @@ export function BoardApprovalsPanel({
{hasRubric ? (
<div className="space-y-4">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-500">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
Rubric scores
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:items-center">
@ -915,11 +915,11 @@ export function BoardApprovalsPanel({
className="h-2.5 w-2.5 rounded-full"
style={{ backgroundColor: entry.fill }}
/>
<span className="text-slate-700">
<span className="text-muted-foreground">
{entry.name}
</span>
</div>
<span className="font-medium tabular-nums text-slate-900">
<span className="font-medium tabular-nums text-foreground">
{entry.percentLabel}
</span>
</div>

View File

@ -227,7 +227,7 @@ function BoardChatComposerImpl({
disabled={isSending || disabled}
/>
{mentionTarget && filteredMentionOptions.length > 0 ? (
<div className="absolute bottom-full left-0 z-20 mb-2 w-full overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg">
<div className="absolute bottom-full left-0 z-20 mb-2 w-full overflow-hidden rounded-xl border border-border bg-card shadow-lg">
<div className="max-h-52 overflow-y-auto py-1">
{filteredMentionOptions.map((option, index) => (
<button
@ -239,12 +239,12 @@ function BoardChatComposerImpl({
}}
className={`flex w-full items-center justify-between px-3 py-2 text-left text-sm transition ${
index === activeIndex
? "bg-slate-100 text-slate-900"
: "text-slate-700 hover:bg-slate-50"
? "bg-accent text-foreground"
: "text-muted-foreground hover:bg-muted"
}`}
>
<span className="font-mono">@{option}</span>
<span className="text-xs text-slate-400">mention</span>
<span className="text-xs text-muted-foreground/70">mention</span>
</button>
))}
</div>

View File

@ -392,13 +392,13 @@ export function BoardOnboardingChat({
{draft ? (
<div className="space-y-3">
<p className="text-sm text-slate-600">
<p className="text-sm text-muted-foreground">
Review the lead agent draft and confirm.
</p>
{isAwaitingAgent ? (
<div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-700">
<div className="flex items-center gap-2 font-medium text-slate-900">
<RefreshCcw className="h-4 w-4 animate-spin text-slate-500" />
<div className="rounded-xl border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
<div className="flex items-center gap-2 font-medium text-foreground">
<RefreshCcw className="h-4 w-4 animate-spin text-muted-foreground" />
<span>
{awaitingKind === "extra_context"
? "Updating the draft…"
@ -406,80 +406,80 @@ export function BoardOnboardingChat({
</span>
</div>
{lastSubmittedAnswer ? (
<p className="mt-2 text-xs text-slate-600">
<p className="mt-2 text-xs text-muted-foreground">
Sent:{" "}
<span className="font-medium text-slate-900">
<span className="font-medium text-foreground">
{lastSubmittedAnswer}
</span>
</p>
) : null}
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
This usually takes a few seconds.
</p>
</div>
) : null}
<div className="rounded-lg border border-slate-200 bg-slate-50 p-3 text-sm">
<p className="font-semibold text-slate-900">Objective</p>
<p className="text-slate-700">{draft.objective || "—"}</p>
<p className="mt-3 font-semibold text-slate-900">Success metrics</p>
<pre className="mt-1 whitespace-pre-wrap text-xs text-slate-600">
<div className="rounded-lg border border-border bg-muted p-3 text-sm">
<p className="font-semibold text-foreground">Objective</p>
<p className="text-muted-foreground">{draft.objective || "—"}</p>
<p className="mt-3 font-semibold text-foreground">Success metrics</p>
<pre className="mt-1 whitespace-pre-wrap text-xs text-muted-foreground">
{JSON.stringify(draft.success_metrics ?? {}, null, 2)}
</pre>
<p className="mt-3 font-semibold text-slate-900">Target date</p>
<p className="text-slate-700">{draft.target_date || "—"}</p>
<p className="mt-3 font-semibold text-slate-900">Board type</p>
<p className="text-slate-700">{draft.board_type || "goal"}</p>
<p className="mt-3 font-semibold text-foreground">Target date</p>
<p className="text-muted-foreground">{draft.target_date || "—"}</p>
<p className="mt-3 font-semibold text-foreground">Board type</p>
<p className="text-muted-foreground">{draft.board_type || "goal"}</p>
{draft.user_profile ? (
<>
<p className="mt-4 font-semibold text-slate-900">
<p className="mt-4 font-semibold text-foreground">
User profile
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">
<p className="text-muted-foreground">
<span className="font-medium text-foreground">
Preferred name:
</span>{" "}
{draft.user_profile.preferred_name || "—"}
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">Pronouns:</span>{" "}
<p className="text-muted-foreground">
<span className="font-medium text-foreground">Pronouns:</span>{" "}
{draft.user_profile.pronouns || "—"}
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">Timezone:</span>{" "}
<p className="text-muted-foreground">
<span className="font-medium text-foreground">Timezone:</span>{" "}
{draft.user_profile.timezone || "—"}
</p>
</>
) : null}
{draft.lead_agent ? (
<>
<p className="mt-4 font-semibold text-slate-900">
<p className="mt-4 font-semibold text-foreground">
Lead agent preferences
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">Name:</span>{" "}
<p className="text-muted-foreground">
<span className="font-medium text-foreground">Name:</span>{" "}
{draft.lead_agent.name || "—"}
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">Role:</span>{" "}
<p className="text-muted-foreground">
<span className="font-medium text-foreground">Role:</span>{" "}
{draft.lead_agent.identity_profile?.role || "—"}
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">
<p className="text-muted-foreground">
<span className="font-medium text-foreground">
Communication:
</span>{" "}
{draft.lead_agent.identity_profile?.communication_style ||
"—"}
</p>
<p className="text-slate-700">
<span className="font-medium text-slate-900">Emoji:</span>{" "}
<p className="text-muted-foreground">
<span className="font-medium text-foreground">Emoji:</span>{" "}
{draft.lead_agent.identity_profile?.emoji || "—"}
</p>
</>
) : null}
</div>
<div className="rounded-lg border border-slate-200 bg-white p-3">
<div className="rounded-lg border border-border bg-card p-3">
<div className="flex items-center justify-between gap-2">
<p className="text-sm font-semibold text-slate-900">
<p className="text-sm font-semibold text-foreground">
Extra context (optional)
</p>
<Button
@ -527,12 +527,12 @@ export function BoardOnboardingChat({
: "Send context"}
</Button>
</div>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Tip: press Enter to send. Shift+Enter for a newline.
</p>
</div>
) : (
<p className="mt-2 text-xs text-slate-600">
<p className="mt-2 text-xs text-muted-foreground">
Add anything that wasn&apos;t covered in the agent&apos;s
questions.
</p>
@ -550,13 +550,13 @@ export function BoardOnboardingChat({
</div>
) : question ? (
<div className="space-y-3">
<p className="text-sm font-medium text-slate-900">
<p className="text-sm font-medium text-foreground">
{question.question}
</p>
{isAwaitingAgent ? (
<div className="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-700">
<div className="flex items-center gap-2 font-medium text-slate-900">
<RefreshCcw className="h-4 w-4 animate-spin text-slate-500" />
<div className="rounded-xl border border-border bg-muted px-4 py-3 text-sm text-muted-foreground">
<div className="flex items-center gap-2 font-medium text-foreground">
<RefreshCcw className="h-4 w-4 animate-spin text-muted-foreground" />
<span>
{awaitingKind === "extra_context"
? "Updating the draft…"
@ -564,14 +564,14 @@ export function BoardOnboardingChat({
</span>
</div>
{lastSubmittedAnswer ? (
<p className="mt-2 text-xs text-slate-600">
<p className="mt-2 text-xs text-muted-foreground">
Sent:{" "}
<span className="font-medium text-slate-900">
<span className="font-medium text-foreground">
{lastSubmittedAnswer}
</span>
</p>
) : null}
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
This usually takes a few seconds.
</p>
</div>
@ -611,7 +611,7 @@ export function BoardOnboardingChat({
}}
disabled={loading || isAwaitingAgent}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Tip: press Enter to send. Shift+Enter for a newline.
</p>
</div>
@ -631,16 +631,16 @@ export function BoardOnboardingChat({
{loading ? "Sending..." : isAwaitingAgent ? "Waiting..." : "Next"}
</Button>
{loading ? (
<p className="text-xs text-slate-500">Sending your answer</p>
<p className="text-xs text-muted-foreground">Sending your answer</p>
) : isAwaitingAgent ? (
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Waiting for the agent to respond
</p>
) : null}
</div>
</div>
) : (
<div className="rounded-lg border border-slate-200 bg-slate-50 p-3 text-sm text-slate-600">
<div className="rounded-lg border border-border bg-muted p-3 text-sm text-muted-foreground">
{loading
? "Waiting for the lead agent..."
: "Preparing onboarding..."}

View File

@ -18,13 +18,13 @@ export function ActivityFeed<TItem extends FeedItem>({
renderItem,
}: ActivityFeedProps<TItem>) {
if (isLoading && items.length === 0) {
return <p className="text-sm text-slate-500">Loading feed</p>;
return <p className="text-sm text-muted-foreground">Loading feed</p>;
}
const hasError = errorMessage !== null && errorMessage !== undefined;
if (hasError) {
return (
<div className="rounded-lg border border-slate-200 bg-white p-4 text-sm text-slate-700 shadow-sm">
<div className="rounded-lg border border-border bg-card p-4 text-sm text-muted-foreground shadow-sm">
{errorMessage || "Unable to load feed."}
</div>
);
@ -32,11 +32,11 @@ export function ActivityFeed<TItem extends FeedItem>({
if (items.length === 0) {
return (
<div className="rounded-xl border border-slate-200 bg-white p-10 text-center shadow-sm">
<p className="text-sm font-medium text-slate-900">
<div className="rounded-xl border border-border bg-card p-10 text-center shadow-sm">
<p className="text-sm font-medium text-foreground">
Waiting for new activity
</p>
<p className="mt-1 text-sm text-slate-500">
<p className="mt-1 text-sm text-muted-foreground">
When updates happen, they will show up here.
</p>
</div>

View File

@ -46,7 +46,7 @@ type AgentsTableProps = {
const DEFAULT_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@ -120,7 +120,7 @@ export function AgentsTable({
accessorKey: "openclaw_session_id",
header: "Session",
cell: ({ row }) => (
<span className="text-sm text-slate-700">
<span className="text-sm text-muted-foreground">
{truncate(row.original.openclaw_session_id)}
</span>
),
@ -131,7 +131,7 @@ export function AgentsTable({
cell: ({ row }) => {
const boardId = row.original.board_id;
if (!boardId) {
return <span className="text-sm text-slate-700"></span>;
return <span className="text-sm text-muted-foreground"></span>;
}
const boardName = boardNameById.get(boardId) ?? boardId;
return linkifyCell({
@ -186,7 +186,7 @@ export function AgentsTable({
}
: undefined
}
rowClassName="hover:bg-slate-50"
rowClassName="hover:bg-muted"
cellClassName="px-6 py-4"
emptyState={
emptyState

View File

@ -108,7 +108,7 @@ const MARKDOWN_CODE_COMPONENTS: Components = {
pre: ({ node: _node, className, ...props }) => (
<pre
className={cn(
"my-3 overflow-x-auto rounded-lg bg-slate-950 p-3 text-xs leading-relaxed text-slate-100",
"my-3 overflow-x-auto rounded-lg bg-foreground p-3 text-xs leading-relaxed text-background",
className,
)}
{...props}
@ -134,7 +134,7 @@ const MARKDOWN_CODE_COMPONENTS: Components = {
return (
<code
className={cn(
"rounded bg-slate-100 px-1 py-0.5 font-mono text-[0.85em] text-slate-900",
"rounded bg-accent px-1 py-0.5 font-mono text-[0.85em] text-foreground",
className,
)}
{...props}
@ -160,7 +160,7 @@ const MARKDOWN_TABLE_COMPONENTS: Components = {
</div>
),
thead: ({ node: _node, className, ...props }) => (
<thead className={cn("bg-slate-50", className)} {...props} />
<thead className={cn("bg-muted", className)} {...props} />
),
tbody: ({ node: _node, className, ...props }) => (
<tbody className={cn("divide-y divide-slate-100", className)} {...props} />
@ -171,7 +171,7 @@ const MARKDOWN_TABLE_COMPONENTS: Components = {
th: ({ node: _node, className, children, ...props }) => (
<th
className={cn(
"border border-slate-200 px-3 py-2 text-left text-xs font-semibold",
"border border-border px-3 py-2 text-left text-xs font-semibold",
className,
)}
{...props}
@ -181,7 +181,7 @@ const MARKDOWN_TABLE_COMPONENTS: Components = {
),
td: ({ node: _node, className, children, ...props }) => (
<td
className={cn("border border-slate-200 px-3 py-2 align-top", className)}
className={cn("border border-border px-3 py-2 align-top", className)}
{...props}
>
{renderMentions(children)}

View File

@ -9,7 +9,7 @@ export function PipelineIcon({ className }: PipelineIconProps) {
<div
className={
className ??
"grid h-10 w-10 place-items-center rounded-lg bg-[color:var(--accent)] text-white shadow-sm"
"grid h-10 w-10 place-items-center rounded-lg bg-primary text-primary-foreground shadow-sm"
}
aria-hidden="true"
>

View File

@ -8,7 +8,7 @@ const AGENT_STATUS_DOT_CLASS_BY_STATUS: Record<string, string> = {
provisioning: "bg-amber-500",
updating: "bg-sky-500",
deleting: "bg-rose-500",
offline: "bg-slate-400",
offline: "bg-muted-foreground",
};
const APPROVAL_STATUS_DOT_CLASS_BY_STATUS: Record<string, string> = {
@ -18,7 +18,7 @@ const APPROVAL_STATUS_DOT_CLASS_BY_STATUS: Record<string, string> = {
};
const TASK_STATUS_DOT_CLASS_BY_STATUS: Record<string, string> = {
inbox: "bg-slate-400",
inbox: "bg-muted-foreground",
in_progress: "bg-purple-500",
review: "bg-indigo-500",
done: "bg-emerald-500",
@ -34,9 +34,9 @@ const STATUS_DOT_CLASS_BY_VARIANT: Record<
};
const DEFAULT_STATUS_DOT_CLASS: Record<StatusDotVariant, string> = {
agent: "bg-slate-300",
agent: "bg-muted-foreground/40",
approval: "bg-amber-500",
task: "bg-slate-300",
task: "bg-muted-foreground/40",
};
export const statusDotClass = (

View File

@ -4,7 +4,7 @@ type AdminOnlyNoticeProps = {
export function AdminOnlyNotice({ message }: AdminOnlyNoticeProps) {
return (
<div className="rounded-xl border border-slate-200 bg-white px-6 py-5 text-sm text-slate-600 shadow-sm">
<div className="rounded-xl border border-border bg-card px-6 py-5 text-sm text-muted-foreground shadow-sm">
{message}
</div>
);

View File

@ -20,9 +20,9 @@ export function SignedOutPanel({
buttonTestId,
}: SignedOutPanelProps) {
return (
<div className="col-span-1 md:col-span-2 flex min-h-[calc(100vh-64px)] items-center justify-center bg-slate-50 p-10 text-center">
<div className="rounded-xl border border-slate-200 bg-white px-4 py-4 md:px-8 md:py-6 shadow-sm">
<p className="text-sm text-slate-600">{message}</p>
<div className="col-span-1 md:col-span-2 flex min-h-[calc(100vh-64px)] items-center justify-center bg-muted p-10 text-center">
<div className="rounded-xl border border-border bg-card px-4 py-4 md:px-8 md:py-6 shadow-sm">
<p className="text-sm text-muted-foreground">{message}</p>
<SignInButton
mode={mode}
forceRedirectUrl={forceRedirectUrl}

View File

@ -37,7 +37,7 @@ type BoardGroupsTableProps = {
const DEFAULT_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@ -94,8 +94,8 @@ export function BoardGroupsTable({
label: row.original.name,
subtitle: row.original.description ?? "No description",
subtitleClassName: row.original.description
? "mt-1 line-clamp-2 text-xs text-slate-500"
: "mt-1 text-xs text-slate-400",
? "mt-1 line-clamp-2 text-xs text-muted-foreground"
: "mt-1 text-xs text-muted-foreground/70",
}),
},
{
@ -129,7 +129,7 @@ export function BoardGroupsTable({
isLoading={isLoading}
stickyHeader={stickyHeader}
emptyMessage={emptyMessage}
rowClassName="transition hover:bg-slate-50"
rowClassName="transition hover:bg-muted"
cellClassName="px-3 py-3 md:px-6 md:py-4 align-top"
rowActions={
showActions

View File

@ -38,7 +38,7 @@ type BoardsTableProps = {
const DEFAULT_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@ -117,7 +117,7 @@ export function BoardsTable({
cell: ({ row }) => {
const groupId = row.original.board_group_id;
if (!groupId) {
return <span className="text-sm text-slate-400"></span>;
return <span className="text-sm text-muted-foreground/70"></span>;
}
const group = groupById.get(groupId);
const label = group?.name ?? compactId(groupId);
@ -161,7 +161,7 @@ export function BoardsTable({
isLoading={isLoading}
stickyHeader={stickyHeader}
emptyMessage={emptyMessage}
rowClassName="transition hover:bg-slate-50"
rowClassName="transition hover:bg-muted"
cellClassName="px-3 py-3 md:px-6 md:py-4 align-top"
rowActions={
showActions

View File

@ -314,10 +314,10 @@ function ChartTooltipCard({
<ChartTooltipContent
{...props}
className={cn(
"border border-gray-200 bg-white px-3 py-2 text-sm shadow-lg",
"border border-border bg-popover px-3 py-2 text-sm text-popover-foreground shadow-lg",
className,
)}
labelClassName={cn("text-sm font-semibold text-gray-900", labelClassName)}
labelClassName={cn("text-sm font-semibold text-foreground", labelClassName)}
/>
);
}
@ -439,7 +439,7 @@ function ChartLegendItem({
aria-pressed={!isHidden}
onClick={handleClick}
className={cn(
"flex items-center gap-2 text-gray-600 transition-opacity [&>svg]:h-3 [&>svg]:w-3 cursor-pointer disabled:cursor-not-allowed disabled:opacity-60",
"flex items-center gap-2 text-muted-foreground transition-opacity [&>svg]:h-3 [&>svg]:w-3 cursor-pointer disabled:cursor-not-allowed disabled:opacity-60",
isHidden && "opacity-50",
className,
)}
@ -453,7 +453,7 @@ function ChartLegendItem({
style={{ backgroundColor: resolvedColor }}
/>
)}
<span className={cn(isHidden && "line-through text-gray-400")}>
<span className={cn(isHidden && "line-through text-muted-foreground/70")}>
{resolvedLabel}
</span>
</button>

View File

@ -65,7 +65,7 @@ const SparklineTooltip = ({
: "Day";
const prefix = resolvedLabel ?? (dayIndex ? `${label} ${dayIndex}` : "");
return (
<div className="rounded-md border border-gray-200 bg-white px-2 py-1 text-xs font-medium text-gray-700 shadow-sm">
<div className="rounded-md border border-border bg-popover px-2 py-1 text-xs font-medium text-popover-foreground shadow-sm">
{prefix ? `${prefix}: ` : ""}
{formatSparkValue(rawValue)}
</div>
@ -85,8 +85,8 @@ export default function MetricSparkline({
}
const data = buildSparkData(values);
const strokeColor = "#60a5fa";
const fillColor = "#bfdbfe";
const strokeColor = "var(--accent)";
const fillColor = "var(--accent-soft)";
return (
<div className={cn("h-8 w-full", className)}>

View File

@ -93,15 +93,15 @@ export function CustomFieldForm({
return (
<form
onSubmit={handleSubmit}
className="max-w-3xl rounded-xl border border-slate-200 bg-white p-6 shadow-sm space-y-6"
className="max-w-3xl rounded-xl border border-border bg-card p-6 shadow-sm space-y-6"
>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Basic configuration
</p>
<div className="mt-4 grid gap-6 md:grid-cols-2">
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Field key
</span>
<Input
@ -118,14 +118,14 @@ export function CustomFieldForm({
required={mode === "create"}
/>
{mode === "edit" ? (
<span className="text-xs text-slate-500">
<span className="text-xs text-muted-foreground">
Field key cannot be changed after creation.
</span>
) : null}
</label>
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">Label</span>
<span className="text-sm font-semibold text-foreground">Label</span>
<Input
value={formState.label}
onChange={(event) =>
@ -138,7 +138,7 @@ export function CustomFieldForm({
</label>
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Field type
</span>
<Select
@ -165,7 +165,7 @@ export function CustomFieldForm({
</label>
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
UI visible
</span>
<Select
@ -192,7 +192,7 @@ export function CustomFieldForm({
</label>
</div>
<label className="mt-4 flex items-center gap-2 text-sm text-slate-700">
<label className="mt-4 flex items-center gap-2 text-sm text-muted-foreground">
<input
type="checkbox"
checked={formState.required}
@ -209,12 +209,12 @@ export function CustomFieldForm({
</div>
<div>
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Validation and defaults
</p>
<div className="mt-4 space-y-4">
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Validation regex
</span>
<Input
@ -231,13 +231,13 @@ export function CustomFieldForm({
!STRING_VALIDATION_FIELD_TYPES.has(formState.fieldType)
}
/>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Supported for text/date/date-time/url fields.
</p>
</label>
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Default value
</span>
<Textarea
@ -255,7 +255,7 @@ export function CustomFieldForm({
</label>
<label className="space-y-1">
<span className="text-sm font-semibold text-slate-900">
<span className="text-sm font-semibold text-foreground">
Description
</span>
<Textarea
@ -276,10 +276,10 @@ export function CustomFieldForm({
<div>
<div className="flex flex-wrap items-center justify-between gap-2">
<p className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Board bindings
</p>
<span className="text-xs text-slate-500">
<span className="text-xs text-muted-foreground">
{selectedBoardIds.size} selected
</span>
</div>
@ -290,9 +290,9 @@ export function CustomFieldForm({
placeholder="Search boards..."
disabled={isSubmitting}
/>
<div className="max-h-64 overflow-auto rounded-xl border border-slate-200 bg-slate-50/40">
<div className="max-h-64 overflow-auto rounded-xl border border-border bg-muted/40">
{boardsLoading ? (
<div className="px-4 py-6 text-sm text-slate-500">
<div className="px-4 py-6 text-sm text-muted-foreground">
Loading boards
</div>
) : boardsError ? (
@ -300,7 +300,7 @@ export function CustomFieldForm({
{boardsError}
</div>
) : filteredBoards.length === 0 ? (
<div className="px-4 py-6 text-sm text-slate-500">
<div className="px-4 py-6 text-sm text-muted-foreground">
No boards found.
</div>
) : (
@ -312,7 +312,7 @@ export function CustomFieldForm({
<label className="flex cursor-pointer items-start gap-3">
<input
type="checkbox"
className="mt-1 h-4 w-4 rounded border-slate-300 text-blue-600"
className="mt-1 h-4 w-4 rounded border-input text-primary"
checked={checked}
onChange={() => {
setSelectedBoardIds((prev) => {
@ -328,10 +328,10 @@ export function CustomFieldForm({
disabled={isSubmitting}
/>
<div className="min-w-0">
<p className="truncate text-sm font-medium text-slate-900">
<p className="truncate text-sm font-medium text-foreground">
{board.name}
</p>
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
{board.slug}
</p>
</div>
@ -342,7 +342,7 @@ export function CustomFieldForm({
</ul>
)}
</div>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
Required. The custom field appears on tasks in selected boards.
</p>
</div>

View File

@ -33,7 +33,7 @@ type CustomFieldsTableProps = {
const DEFAULT_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@ -77,13 +77,13 @@ export function CustomFieldsTable({
header: "Field",
cell: ({ row }) => (
<div>
<p className="text-sm font-semibold text-slate-900">
<p className="text-sm font-semibold text-foreground">
{row.original.label || row.original.field_key}
</p>
<p className="mt-1 font-mono text-xs text-slate-500">
<p className="mt-1 font-mono text-xs text-muted-foreground">
key: {row.original.field_key}
</p>
<p className="mt-1 text-xs text-slate-500">
<p className="mt-1 text-xs text-muted-foreground">
{row.original.description || "No description"}
</p>
</div>
@ -93,7 +93,7 @@ export function CustomFieldsTable({
accessorKey: "required",
header: "Required",
cell: ({ row }) => (
<span className="text-sm text-slate-700">
<span className="text-sm text-muted-foreground">
{row.original.required === true ? "Required" : "Optional"}
</span>
),
@ -102,7 +102,7 @@ export function CustomFieldsTable({
accessorKey: "field_type",
header: "Type",
cell: ({ row }) => (
<span className="text-sm text-slate-700">
<span className="text-sm text-muted-foreground">
{row.original.field_type}
</span>
),
@ -111,7 +111,7 @@ export function CustomFieldsTable({
accessorKey: "ui_visibility",
header: "UI visible",
cell: ({ row }) => (
<span className="text-sm text-slate-700">
<span className="text-sm text-muted-foreground">
{row.original.ui_visibility}
</span>
),
@ -121,7 +121,7 @@ export function CustomFieldsTable({
header: "Default value",
enableSorting: false,
cell: ({ row }) => (
<p className="font-mono text-xs break-all text-slate-700">
<p className="font-mono text-xs break-all text-muted-foreground">
{formatCustomFieldDefaultValue(row.original.default_value) || "—"}
</p>
),
@ -152,7 +152,7 @@ export function CustomFieldsTable({
table={table}
isLoading={isLoading}
stickyHeader={stickyHeader}
rowClassName="transition hover:bg-slate-50"
rowClassName="transition hover:bg-muted"
cellClassName="px-6 py-4 align-top"
rowActions={
editHref || onDelete

View File

@ -60,10 +60,10 @@ export function GatewayForm({
return (
<form
onSubmit={onSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Gateway name <span className="text-red-500">*</span>
</label>
<Input
@ -76,7 +76,7 @@ export function GatewayForm({
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Gateway URL <span className="text-red-500">*</span>
</label>
<div className="relative">
@ -95,7 +95,7 @@ export function GatewayForm({
) : null}
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Gateway token
</label>
<Input
@ -109,7 +109,7 @@ export function GatewayForm({
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Workspace root <span className="text-red-500">*</span>
</label>
<Input
@ -121,10 +121,10 @@ export function GatewayForm({
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Disable device pairing
</label>
<label className="flex h-10 items-center gap-3 px-1 text-sm text-slate-900">
<label className="flex h-10 items-center gap-3 px-1 text-sm text-foreground">
<button
type="button"
role="switch"
@ -137,11 +137,11 @@ export function GatewayForm({
className={`inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
disableDevicePairing
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
disableDevicePairing ? "translate-x-5" : "translate-x-0.5"
}`}
/>
@ -151,10 +151,10 @@ export function GatewayForm({
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-slate-900">
<label className="text-sm font-medium text-foreground">
Allow self-signed TLS certificates
</label>
<label className="flex h-10 items-center gap-3 px-1 text-sm text-slate-900">
<label className="flex h-10 items-center gap-3 px-1 text-sm text-foreground">
<button
type="button"
role="switch"
@ -165,11 +165,11 @@ export function GatewayForm({
className={`inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
allowInsecureTls
? "border-emerald-600 bg-emerald-600"
: "border-slate-300 bg-slate-200"
: "border-input bg-border"
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
>
<span
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
className={`inline-block h-5 w-5 rounded-full bg-card shadow-sm transition ${
allowInsecureTls ? "translate-x-5" : "translate-x-0.5"
}`}
/>

View File

@ -38,7 +38,7 @@ type GatewaysTableProps = {
const DEFAULT_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@ -100,7 +100,7 @@ export function GatewaysTable({
accessorKey: "workspace_root",
header: "Workspace root",
cell: ({ row }) => (
<span className="text-sm text-slate-700">
<span className="text-sm text-muted-foreground">
{truncate(row.original.workspace_root, 28)}
</span>
),

View File

@ -385,7 +385,7 @@ export function BoardForgejoRepositoryLinks({
errorMessage={unlinkError}
confirmLabel="Unlink Repository"
confirmingLabel="Unlinking..."
confirmClassName="bg-[color:var(--danger)] text-white hover:bg-[color:var(--danger)]/90"
confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
cancelLabel="Keep Linked"
/>
</>

View File

@ -24,7 +24,7 @@ type DependencyBannerVariant = "blocked" | "resolved";
const toneClassByVariant: Record<DependencyBannerVariant, string> = {
blocked: "border-rose-200 bg-rose-50 text-rose-700",
resolved: "border-blue-200 bg-blue-50 text-blue-700",
resolved: "border-primary/30 bg-primary/10 text-primary",
};
export function DependencyBanner({
@ -52,12 +52,12 @@ export function DependencyBanner({
? "border-rose-200 bg-rose-50 hover:bg-rose-100/40"
: isDone
? "border-emerald-200 bg-emerald-50 hover:bg-emerald-100/40"
: "border-slate-200 bg-white hover:bg-slate-50",
: "border-border bg-card hover:bg-muted",
dependency.disabled && "cursor-not-allowed opacity-60",
)}
>
<div className="flex items-center justify-between gap-3">
<p className="truncate text-sm font-medium text-slate-900">
<p className="truncate text-sm font-medium text-foreground">
{dependency.title}
</p>
<span
@ -67,7 +67,7 @@ export function DependencyBanner({
? "text-rose-700"
: isDone
? "text-emerald-700"
: "text-slate-500",
: "text-muted-foreground",
)}
>
{dependency.statusLabel}
@ -77,7 +77,7 @@ export function DependencyBanner({
);
})
) : (
<p className="text-sm text-slate-500">{emptyMessage}</p>
<p className="text-sm text-muted-foreground">{emptyMessage}</p>
)}
{children ? (
<div

View File

@ -61,7 +61,7 @@ export function TaskCard({
if (normalized === "low") {
return "bg-emerald-100 text-emerald-700";
}
return "bg-slate-100 text-slate-600";
return "bg-accent text-muted-foreground";
};
const priorityLabel = priority ? priority.toUpperCase() : "MEDIUM";
@ -70,7 +70,7 @@ export function TaskCard({
return (
<div
className={cn(
"group relative cursor-pointer rounded-lg border border-slate-200 bg-white p-4 shadow-sm transition-all hover:-translate-y-0.5 hover:border-slate-300 hover:shadow-md",
"group relative cursor-pointer rounded-lg border border-border bg-card p-4 shadow-sm transition-all hover:-translate-y-0.5 hover:border-input hover:shadow-md",
isDragging && "opacity-60 shadow-none",
hasPendingApproval && "border-amber-200 bg-amber-50/40",
isBlocked && "border-rose-200 bg-rose-50/50",
@ -99,7 +99,7 @@ export function TaskCard({
) : null}
<div className="flex items-start justify-between gap-3">
<div className="min-w-0 space-y-2">
<p className="text-sm font-medium text-slate-900 line-clamp-2 break-words">
<p className="text-sm font-medium text-foreground line-clamp-2 break-words">
{title}
</p>
{isBlocked ? (
@ -125,7 +125,7 @@ export function TaskCard({
{visibleTags.map((tag) => (
<span
key={tag.id}
className="inline-flex items-center gap-1 rounded-full border border-slate-200 bg-white px-2 py-0.5 text-[10px] font-semibold text-slate-700"
className="inline-flex items-center gap-1 rounded-full border border-border bg-card px-2 py-0.5 text-[10px] font-semibold text-muted-foreground"
>
<span
className="h-1.5 w-1.5 rounded-full"
@ -135,7 +135,7 @@ export function TaskCard({
</span>
))}
{tags.length > visibleTags.length ? (
<span className="text-[10px] font-semibold text-slate-500">
<span className="text-[10px] font-semibold text-muted-foreground">
+{tags.length - visibleTags.length}
</span>
) : null}
@ -146,16 +146,16 @@ export function TaskCard({
<span
className={cn(
"inline-flex items-center rounded-full px-2 py-1 text-[10px] font-semibold uppercase tracking-wide",
priorityBadge(priority) ?? "bg-slate-100 text-slate-600",
priorityBadge(priority) ?? "bg-accent text-muted-foreground",
)}
>
{priorityLabel}
</span>
</div>
</div>
<div className="mt-3 flex items-center justify-between text-xs text-slate-500">
<div className="mt-3 flex items-center justify-between text-xs text-muted-foreground">
<div className="flex items-center gap-2">
<UserCircle className="h-4 w-4 text-slate-400" />
<UserCircle className="h-4 w-4 text-muted-foreground/70" />
<span>{assignee ?? "Unassigned"}</span>
</div>
{due ? (
@ -168,7 +168,7 @@ export function TaskCard({
<CalendarClock
className={cn(
"h-4 w-4",
isOverdue ? "text-rose-500" : "text-slate-400",
isOverdue ? "text-rose-500" : "text-muted-foreground/70",
)}
/>
<span>{due}</span>

View File

@ -51,17 +51,17 @@ const columns: Array<{
{
title: "Inbox",
status: "inbox",
dot: "bg-slate-400",
accent: "hover:border-slate-400 hover:bg-slate-50",
text: "group-hover:text-slate-700 text-slate-500",
badge: "bg-slate-100 text-slate-600",
dot: "bg-muted-foreground",
accent: "hover:border-muted-foreground hover:bg-muted",
text: "group-hover:text-muted-foreground text-muted-foreground",
badge: "bg-accent text-muted-foreground",
},
{
title: "In Progress",
status: "in_progress",
dot: "bg-purple-500",
accent: "hover:border-purple-400 hover:bg-purple-50",
text: "group-hover:text-purple-600 text-slate-500",
text: "group-hover:text-purple-600 text-muted-foreground",
badge: "bg-purple-100 text-purple-700",
},
{
@ -69,7 +69,7 @@ const columns: Array<{
status: "review",
dot: "bg-indigo-500",
accent: "hover:border-indigo-400 hover:bg-indigo-50",
text: "group-hover:text-indigo-600 text-slate-500",
text: "group-hover:text-indigo-600 text-muted-foreground",
badge: "bg-indigo-100 text-indigo-700",
},
{
@ -77,7 +77,7 @@ const columns: Array<{
status: "done",
dot: "bg-green-500",
accent: "hover:border-green-400 hover:bg-green-50",
text: "group-hover:text-green-600 text-slate-500",
text: "group-hover:text-green-600 text-muted-foreground",
badge: "bg-emerald-100 text-emerald-700",
},
];
@ -424,17 +424,17 @@ export const TaskBoard = memo(function TaskBoard({
"sm:min-h-[calc(100vh-260px)]",
activeColumn === column.status &&
!readOnly &&
"ring-2 ring-slate-200",
"ring-2 ring-border",
)}
onDrop={readOnly ? undefined : handleDrop(column.status)}
onDragOver={readOnly ? undefined : handleDragOver(column.status)}
onDragLeave={readOnly ? undefined : handleDragLeave(column.status)}
>
<div className="column-header z-10 rounded-t-xl border border-b-0 border-slate-200 bg-white px-4 py-3 sm:sticky sm:top-0 sm:bg-white/80 sm:backdrop-blur">
<div className="column-header z-10 rounded-t-xl border border-b-0 border-border bg-card px-4 py-3 sm:sticky sm:top-0 sm:bg-card/80 sm:backdrop-blur">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span className={cn("h-2 w-2 rounded-full", column.dot)} />
<h3 className="text-sm font-semibold text-slate-900">
<h3 className="text-sm font-semibold text-foreground">
{column.title}
</h3>
</div>
@ -448,7 +448,7 @@ export const TaskBoard = memo(function TaskBoard({
</span>
</div>
{column.status === "review" && reviewCounts ? (
<div className="mt-2 flex flex-wrap items-center gap-2 text-[10px] font-semibold uppercase tracking-wide text-slate-500">
<div className="mt-2 flex flex-wrap items-center gap-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
{(
[
{ key: "all", label: "All", count: reviewCounts.all },
@ -476,8 +476,8 @@ export const TaskBoard = memo(function TaskBoard({
className={cn(
"rounded-full border px-2.5 py-1 transition",
reviewBucket === option.key
? "border-slate-900 bg-slate-900 text-white"
: "border-slate-200 bg-white text-slate-600 hover:border-slate-300 hover:bg-slate-50",
? "border-foreground bg-foreground text-background"
: "border-border bg-card text-muted-foreground hover:border-input hover:bg-muted",
)}
aria-pressed={reviewBucket === option.key}
>
@ -487,7 +487,7 @@ export const TaskBoard = memo(function TaskBoard({
</div>
) : null}
</div>
<div className="rounded-b-xl border border-t-0 border-slate-200 bg-white p-3">
<div className="rounded-b-xl border border-t-0 border-border bg-card p-3">
<div className="space-y-3">
{filteredTasks.map((task) => {
const dueState = resolveDueState(task);

View File

@ -69,7 +69,7 @@ export function UserMenu({
>
<span
className={cn(
"relative flex h-9 w-9 items-center justify-center overflow-hidden rounded-[10px] text-xs font-semibold text-white shadow-sm",
"relative flex h-9 w-9 items-center justify-center overflow-hidden rounded-[10px] text-xs font-semibold text-primary-foreground shadow-sm",
avatarUrl
? "bg-[color:var(--neutral-200,var(--surface-muted))]"
: "bg-gradient-to-br from-[color:var(--primary-navy,var(--accent))] to-[color:var(--secondary-navy,var(--accent-strong))]",
@ -99,7 +99,7 @@ export function UserMenu({
<div className="flex items-center gap-3">
<span
className={cn(
"flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl text-sm font-semibold text-white",
"flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl text-sm font-semibold text-primary-foreground",
avatarUrl
? "bg-[color:var(--neutral-200,var(--surface-muted))]"
: "bg-gradient-to-br from-[color:var(--primary-navy,var(--accent))] to-[color:var(--secondary-navy,var(--accent-strong))]",
@ -141,7 +141,7 @@ export function UserMenu({
</Link>
<Link
href="/boards/new"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-[color:var(--primary-navy,var(--accent))] px-3 py-2 text-sm font-semibold text-white shadow-[0_2px_8px_rgba(10,22,40,0.15)] transition hover:bg-[color:var(--secondary-navy,var(--accent-strong))] hover:translate-y-[-1px] hover:shadow-[0_4px_12px_rgba(10,22,40,0.20)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--accent-teal,var(--accent))] focus-visible:ring-offset-2"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-primary px-3 py-2 text-sm font-semibold text-primary-foreground shadow-[0_2px_8px_rgba(10,22,40,0.15)] transition hover:bg-[color:var(--accent-strong)] hover:translate-y-[-1px] hover:shadow-[0_4px_12px_rgba(10,22,40,0.20)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
onClick={() => setOpen(false)}
>
<Plus className="h-4 w-4 opacity-90" />

View File

@ -37,7 +37,7 @@ export function BoardAccessTable({
href: `/boards/${row.original.id}`,
label: row.original.name,
subtitle: row.original.slug,
subtitleClassName: "mt-1 text-xs text-slate-500",
subtitleClassName: "mt-1 text-xs text-muted-foreground",
}),
},
{
@ -97,8 +97,8 @@ export function BoardAccessTable({
return (
<DataTable
table={table}
rowClassName="border-t border-slate-200 hover:bg-slate-50"
headerClassName="bg-slate-50 text-[11px] uppercase tracking-wide text-slate-500"
rowClassName="border-t border-border hover:bg-muted"
headerClassName="bg-muted text-[11px] uppercase tracking-wide text-muted-foreground"
headerCellClassName="px-4 py-2 font-medium"
cellClassName="px-4 py-3"
/>

View File

@ -97,14 +97,14 @@ export function MembersInvitesTable({
const display = memberDisplay(row.original.member);
return (
<div className="flex items-center gap-3">
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-500 text-xs font-semibold text-white">
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-primary text-xs font-semibold text-primary-foreground">
{display.initials}
</div>
<div>
<div className="text-sm font-semibold text-slate-900">
<div className="text-sm font-semibold text-foreground">
{display.primary}
</div>
<div className="text-xs text-slate-500">
<div className="text-xs text-muted-foreground">
{display.secondary}
</div>
</div>
@ -114,14 +114,14 @@ export function MembersInvitesTable({
return (
<div className="flex items-center gap-3">
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-slate-200 text-xs font-semibold text-slate-600">
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-border text-xs font-semibold text-muted-foreground">
{initialsFrom(row.original.invite.invited_email)}
</div>
<div>
<div className="text-sm font-semibold text-slate-900">
<div className="text-sm font-semibold text-foreground">
{row.original.invite.invited_email}
</div>
<div className="text-xs text-slate-500">
<div className="text-xs text-muted-foreground">
Invited {formatTimestamp(row.original.invite.created_at)}
</div>
</div>
@ -155,7 +155,7 @@ export function MembersInvitesTable({
id: "access",
header: "Access",
cell: ({ row }) => (
<span className="text-slate-600">
<span className="text-muted-foreground">
{row.original.kind === "member"
? summarizeAccess(
row.original.member.all_boards_read,
@ -175,7 +175,7 @@ export function MembersInvitesTable({
if (row.original.kind === "member") {
const member = row.original.member;
if (!isAdmin) {
return <span className="text-xs text-slate-400">Admin only</span>;
return <span className="text-xs text-muted-foreground/70">Admin only</span>;
}
return (
<div className="flex justify-end">
@ -241,13 +241,13 @@ export function MembersInvitesTable({
isLoading={isLoading}
loadingLabel="Loading members..."
emptyMessage="No members or invites yet."
headerClassName="bg-slate-50 text-[11px] uppercase tracking-wide text-slate-500"
headerClassName="bg-muted text-[11px] uppercase tracking-wide text-muted-foreground"
headerCellClassName="px-5 py-3 text-left font-medium"
cellClassName="px-5 py-4"
rowClassName={(row) =>
row.original.kind === "invite"
? "border-t border-slate-200 bg-slate-50/60"
: "border-t border-slate-200 hover:bg-slate-50"
? "border-t border-border bg-muted/60"
: "border-t border-border hover:bg-muted"
}
/>
);

View File

@ -138,13 +138,13 @@ export function MarketplaceSkillForm({
return (
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
<div className="space-y-5">
<div className="space-y-2">
<label
htmlFor="source-url"
className="text-xs font-semibold uppercase tracking-wider text-slate-500"
className="text-xs font-semibold uppercase tracking-wider text-muted-foreground"
>
{sourceLabel}
</label>
@ -158,7 +158,7 @@ export function MarketplaceSkillForm({
disabled={isSubmitting || sourceUrlReadOnly}
/>
{sourceUrlHelpText ? (
<p className="text-xs text-slate-500">{sourceUrlHelpText}</p>
<p className="text-xs text-muted-foreground">{sourceUrlHelpText}</p>
) : null}
</div>
@ -166,7 +166,7 @@ export function MarketplaceSkillForm({
<div className="space-y-2">
<label
htmlFor="skill-branch"
className="text-xs font-semibold uppercase tracking-wider text-slate-500"
className="text-xs font-semibold uppercase tracking-wider text-muted-foreground"
>
{branchLabel}
</label>
@ -183,7 +183,7 @@ export function MarketplaceSkillForm({
<div className="space-y-2">
<label
htmlFor="skill-name"
className="text-xs font-semibold uppercase tracking-wider text-slate-500"
className="text-xs font-semibold uppercase tracking-wider text-muted-foreground"
>
{nameLabel}
</label>
@ -199,7 +199,7 @@ export function MarketplaceSkillForm({
<div className="space-y-2">
<label
htmlFor="skill-description"
className="text-xs font-semibold uppercase tracking-wider text-slate-500"
className="text-xs font-semibold uppercase tracking-wider text-muted-foreground"
>
{descriptionLabel}
</label>

View File

@ -68,7 +68,7 @@ function riskPillClassName(risk: string | null | undefined) {
case "critical":
return "bg-[color:rgba(244,63,94,0.16)] text-rose-800 border border-rose-200/70";
case "unknown":
return "bg-[color:rgba(148,163,184,0.16)] text-slate-700 border border-slate-200/80";
return "bg-[color:rgba(148,163,184,0.16)] text-muted-foreground border border-border/80";
default:
return "bg-[color:rgba(99,102,241,0.16)] text-indigo-800 border border-indigo-200/70";
}
@ -129,17 +129,17 @@ export function MarketplaceSkillsTable({
<button
type="button"
onClick={() => onSkillClick(row.original)}
className="text-sm font-medium text-blue-700 hover:text-blue-600 hover:underline"
className="text-sm font-medium text-primary hover:text-primary hover:underline"
>
{row.original.name}
</button>
) : (
<p className="text-sm font-medium text-slate-900">
<p className="text-sm font-medium text-foreground">
{row.original.name}
</p>
)}
<p
className="mt-1 line-clamp-2 text-xs text-slate-500"
className="mt-1 line-clamp-2 text-xs text-muted-foreground"
title={row.original.description || "No description provided."}
>
{row.original.description || "No description provided."}
@ -155,7 +155,7 @@ export function MarketplaceSkillsTable({
return (
<Link
href={packsHrefFromPackUrl(packUrl)}
className="inline-flex items-center gap-1 text-sm font-medium text-slate-700 hover:text-blue-600"
className="inline-flex items-center gap-1 text-sm font-medium text-muted-foreground hover:text-primary"
>
{truncate(packLabelFromUrl(packUrl), 40)}
</Link>
@ -166,7 +166,7 @@ export function MarketplaceSkillsTable({
accessorKey: "category",
header: "Category",
cell: ({ row }) => (
<span className="text-sm text-slate-700">
<span className="text-sm text-muted-foreground">
{row.original.category || "uncategorized"}
</span>
),
@ -190,7 +190,7 @@ export function MarketplaceSkillsTable({
const sourceHref = row.original.source || row.original.source_url;
if (!sourceHref) {
return <span className="text-sm text-slate-400">No source</span>;
return <span className="text-sm text-muted-foreground/70">No source</span>;
}
return (
@ -198,7 +198,7 @@ export function MarketplaceSkillsTable({
href={sourceHref}
target="_blank"
rel="noreferrer"
className="text-sm font-medium text-slate-700 hover:text-blue-600 hover:underline"
className="text-sm font-medium text-muted-foreground hover:text-primary hover:underline"
title={sourceHref}
>
{truncate(sourceHref, 36)}
@ -214,7 +214,7 @@ export function MarketplaceSkillsTable({
const installedOn =
installedGatewayNamesBySkillId?.[row.original.id] ?? [];
if (installedOn.length === 0) {
return <span className="text-sm text-slate-500">-</span>;
return <span className="text-sm text-muted-foreground">-</span>;
}
return (
<div className="flex flex-wrap gap-1">
@ -223,12 +223,12 @@ export function MarketplaceSkillsTable({
return (
<span
key={`${gateway.id}-${index}`}
className="inline-flex items-center gap-1 text-sm text-slate-700"
className="inline-flex items-center gap-1 text-sm text-muted-foreground"
title={gateway.name}
>
<Link
href={`/gateways/${gateway.id}`}
className="text-blue-700 hover:text-blue-600 hover:underline"
className="text-primary hover:text-primary hover:underline"
>
{gateway.name}
</Link>
@ -302,7 +302,7 @@ export function MarketplaceSkillsTable({
table={table}
isLoading={isLoading}
stickyHeader={stickyHeader}
rowClassName="transition hover:bg-slate-50"
rowClassName="transition hover:bg-muted"
cellClassName="px-6 py-4 align-top"
emptyState={
emptyState

View File

@ -58,7 +58,7 @@ export function SkillInstallDialog({
<div className="mt-2 space-y-3.5">
{isGatewayStatusLoading ? (
<p className="text-sm text-slate-500">Loading gateways...</p>
<p className="text-sm text-muted-foreground">Loading gateways...</p>
) : (
gateways.map((gateway) => {
const isInstalled = gatewayInstalledById[gateway.id] === true;
@ -67,10 +67,10 @@ export function SkillInstallDialog({
return (
<div
key={gateway.id}
className="flex items-center justify-between rounded-xl border border-slate-200 bg-white p-4"
className="flex items-center justify-between rounded-xl border border-border bg-card p-4"
>
<div>
<p className="text-sm font-medium text-slate-900">
<p className="text-sm font-medium text-foreground">
{gateway.name}
</p>
</div>
@ -101,7 +101,7 @@ export function SkillInstallDialog({
) : null}
</div>
<DialogFooter className="mt-6 border-t border-slate-200 pt-4">
<DialogFooter className="mt-6 border-t border-border pt-4">
<Button
variant="outline"
onClick={() => onOpenChange(false)}

View File

@ -65,10 +65,10 @@ export function SkillPacksTable({
header: "Pack",
cell: ({ row }) => (
<div>
<p className="text-sm font-medium text-slate-900">
<p className="text-sm font-medium text-foreground">
{row.original.name}
</p>
<p className="mt-1 line-clamp-2 text-xs text-slate-500">
<p className="mt-1 line-clamp-2 text-xs text-muted-foreground">
{row.original.description || "No description provided."}
</p>
</div>
@ -82,7 +82,7 @@ export function SkillPacksTable({
href={row.original.source_url}
target="_blank"
rel="noreferrer"
className="inline-flex items-center gap-1 text-sm font-medium text-slate-700 hover:text-blue-600"
className="inline-flex items-center gap-1 text-sm font-medium text-muted-foreground hover:text-primary"
>
{truncate(row.original.source_url, 48)}
</Link>
@ -92,7 +92,7 @@ export function SkillPacksTable({
accessorKey: "branch",
header: "Branch",
cell: ({ row }) => (
<p className="text-sm text-slate-900">
<p className="text-sm text-foreground">
{row.original.branch || "main"}
</p>
),
@ -103,7 +103,7 @@ export function SkillPacksTable({
cell: ({ row }) => (
<Link
href={`/skills/marketplace?packId=${encodeURIComponent(row.original.id)}`}
className="text-sm font-medium text-blue-700 hover:text-blue-600 hover:underline"
className="text-sm font-medium text-primary hover:text-primary hover:underline"
>
{row.original.skill_count ?? 0}
</Link>
@ -159,7 +159,7 @@ export function SkillPacksTable({
table={table}
isLoading={isLoading}
stickyHeader={stickyHeader}
rowClassName="transition hover:bg-slate-50"
rowClassName="transition hover:bg-muted"
cellClassName="px-6 py-4 align-top"
rowActions={
getEditHref || onDelete

View File

@ -10,7 +10,7 @@ import {
export const SKILLS_TABLE_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"

View File

@ -101,13 +101,13 @@ export function TagForm({
return (
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm"
className="space-y-6 rounded-xl border border-border bg-card p-6 shadow-sm"
>
<div className="space-y-5">
<div className="rounded-xl border border-slate-200 bg-slate-50/40 p-4">
<div className="rounded-xl border border-border bg-muted/40 p-4">
<div className="grid gap-4 md:grid-cols-2">
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Name
</label>
<Input
@ -119,13 +119,13 @@ export function TagForm({
</div>
<div className="space-y-2">
<div className="flex items-center justify-between gap-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Slug
</label>
<button
type="button"
onClick={() => setSlug(suggestedSlug)}
className="text-xs font-medium text-slate-500 underline underline-offset-2 transition hover:text-slate-700 disabled:cursor-not-allowed disabled:opacity-50"
className="text-xs font-medium text-muted-foreground underline underline-offset-2 transition hover:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
disabled={!suggestedSlug || isSubmitting}
>
Use from name
@ -139,18 +139,18 @@ export function TagForm({
/>
</div>
</div>
<p className="mt-2 text-xs text-slate-500">
<p className="mt-2 text-xs text-muted-foreground">
Leave slug blank to auto-generate from the tag name.
</p>
</div>
<div className="grid gap-4 md:grid-cols-[1fr_auto]">
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Color
</label>
<div className="flex items-center rounded-lg border border-slate-200 bg-white px-3">
<span className="text-sm font-medium text-slate-400">#</span>
<div className="flex items-center rounded-lg border border-border bg-card px-3">
<span className="text-sm font-medium text-muted-foreground/70">#</span>
<Input
value={color}
onChange={(event) => setColor(event.target.value)}
@ -161,15 +161,15 @@ export function TagForm({
</div>
</div>
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Preview
</label>
<div className="inline-flex h-[42px] items-center gap-2 rounded-lg border border-slate-200 bg-white px-3">
<div className="inline-flex h-[42px] items-center gap-2 rounded-lg border border-border bg-card px-3">
<span
className="h-4 w-4 rounded border border-slate-300"
className="h-4 w-4 rounded border border-input"
style={{ backgroundColor: `#${previewColor}` }}
/>
<span className="text-xs font-semibold text-slate-700">
<span className="text-xs font-semibold text-muted-foreground">
#{previewColor.toUpperCase()}
</span>
</div>
@ -177,7 +177,7 @@ export function TagForm({
</div>
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-slate-500">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
Description
</label>
<Textarea

View File

@ -32,7 +32,7 @@ type TagsTableProps = {
const DEFAULT_EMPTY_ICON = (
<svg
className="h-16 w-16 text-slate-300"
className="h-16 w-16 text-muted-foreground/50"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@ -81,14 +81,14 @@ export function TagsTable({
const color = normalizeColor(row.original.color);
return (
<div className="space-y-1">
<div className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-white px-2.5 py-1 text-xs font-semibold text-slate-800">
<div className="inline-flex items-center gap-2 rounded-full border border-border bg-card px-2.5 py-1 text-xs font-semibold text-foreground">
<span
className="h-2 w-2 rounded-full"
style={{ backgroundColor: `#${color}` }}
/>
{row.original.name}
</div>
<p className="text-xs text-slate-500">
<p className="text-xs text-muted-foreground">
{row.original.slug}
{row.original.description
? ` · ${row.original.description}`
@ -104,9 +104,9 @@ export function TagsTable({
cell: ({ row }) => {
const color = normalizeColor(row.original.color);
return (
<div className="inline-flex items-center gap-2 text-xs text-slate-700">
<div className="inline-flex items-center gap-2 text-xs text-muted-foreground">
<span
className="h-4 w-4 rounded border border-slate-300"
className="h-4 w-4 rounded border border-input"
style={{ backgroundColor: `#${color}` }}
/>
#{color.toUpperCase()}
@ -118,7 +118,7 @@ export function TagsTable({
accessorKey: "task_count",
header: "Tasks",
cell: ({ row }) => (
<span className="text-sm font-medium text-slate-700">
<span className="text-sm font-medium text-muted-foreground">
{row.original.task_count ?? 0}
</span>
),
@ -149,7 +149,7 @@ export function TagsTable({
table={table}
isLoading={isLoading}
stickyHeader={stickyHeader}
rowClassName="transition hover:bg-slate-50"
rowClassName="transition hover:bg-muted"
cellClassName="px-6 py-4 align-top"
rowActions={
onEdit || onDelete

View File

@ -11,7 +11,7 @@ const buttonVariants = cva(
variants: {
variant: {
primary:
"bg-[color:var(--accent)] text-white shadow-sm hover:bg-[color:var(--accent-strong)]",
"bg-primary text-primary-foreground shadow-sm hover:bg-[color:var(--accent-strong)]",
secondary:
"border border-[color:var(--border)] bg-[color:var(--surface)] text-strong hover:border-[color:var(--accent)] hover:text-[color:var(--accent)]",
outline:

View File

@ -17,7 +17,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-slate-950/40 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
"fixed inset-0 z-50 bg-foreground/40 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}

View File

@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"rounded-full px-4 py-2 text-xs font-semibold text-muted transition data-[state=active]:bg-[color:var(--accent)] data-[state=active]:text-white",
"rounded-full px-4 py-2 text-xs font-semibold text-muted transition data-[state=active]:bg-primary data-[state=active]:text-primary-foreground",
className,
)}
{...props}

View File

@ -17,7 +17,7 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
"rounded-lg bg-slate-900 px-3 py-2 text-xs font-semibold text-white shadow-lg",
"rounded-lg bg-foreground px-3 py-2 text-xs font-semibold text-background shadow-lg",
className,
)}
{...props}