bug: shadcn ui merge
This commit is contained in:
parent
d45fd42c7f
commit
ad5ca38a86
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>{" "}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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]">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>{" "}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
/>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
/>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
/>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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}`}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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't covered in the agent'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..."}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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 = (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)}>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}`}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
/>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
Loading…
Reference in New Issue