Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions frontend/public/dark-theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,49 @@
background-color: var(--studio-bg-success);
}

/* Status card/badge backgrounds (100-level) */
.dark .bg-yellow-100 {
background-color: var(--studio-bg-warning);
}

Comment on lines +63 to +67
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dark-mode status background overrides cover yellow/green/red/blue, but Task Manager also uses bg-gray-100 for the cancelled status (see getStatusColor()), which is not overridden here and will stay very light in dark mode. Consider adding a .dark .bg-gray-100 override (and related gray status classes) so cancelled badges don’t glare against dark backgrounds.

Copilot uses AI. Check for mistakes.
.dark .bg-green-100 {
background-color: var(--studio-bg-success);
}

.dark .bg-red-100 {
background-color: var(--studio-bg-error);
}

.dark .bg-blue-100 {
background-color: var(--studio-bg-info);
}

/* Status pill active/selected backgrounds (200-level) */
.dark .bg-yellow-200 {
background-color: var(--studio-bg-warning-active);
}

.dark .bg-green-200 {
background-color: var(--studio-bg-success-active);
}

.dark .bg-red-200 {
background-color: var(--studio-bg-error-active);
}

/* Status card/badge hover backgrounds */
.dark .hover\:bg-yellow-100:hover {
background-color: var(--studio-bg-warning-hover);
}

.dark .hover\:bg-green-100:hover {
background-color: var(--studio-bg-success-hover);
}

.dark .hover\:bg-red-100:hover {
background-color: var(--studio-bg-error-hover);
}

.dark .border-red-200 {
border-color: var(--studio-border-error);
}
Expand All @@ -76,6 +115,55 @@
border-color: var(--studio-border-success);
}

/* Hover/other status borders (200-level is handled above) */
.dark .border-yellow-300 {
border-color: var(--studio-border-warning);
}

.dark .border-green-300 {
border-color: var(--studio-border-success);
}

.dark .border-red-300 {
border-color: var(--studio-border-error);
}

.dark .hover\:border-yellow-300:hover {
border-color: var(--studio-border-warning);
}

.dark .hover\:border-green-300:hover {
border-color: var(--studio-border-success);
}

.dark .hover\:border-red-300:hover {
border-color: var(--studio-border-error);
}

/* Status text colors – label (600-level) and value (700–900-level) */
.dark .text-yellow-600,
.dark .text-yellow-700,
.dark .text-yellow-800,
.dark .text-yellow-900 {
color: var(--studio-text-warning);
Comment on lines +143 to +148
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Status pills include text-gray-900 for cancelled and text-slate-900 for the fallback case (used by getStatusPillClass()), but dark-theme.css doesn’t override these 900-level gray/slate text utilities. In dark mode, text-*-900 is near-black and becomes unreadable on the overridden dark backgrounds (e.g. bg-gray-200--studio-bg-subtle). Add dark-mode overrides for text-gray-900 / text-slate-900 (or change the pill classes to semantic text tokens) to ensure adequate contrast.

Copilot uses AI. Check for mistakes.
}

.dark .text-green-600,
.dark .text-green-800,
.dark .text-green-900 {
color: var(--studio-text-success);
}

.dark .text-red-600,
.dark .text-red-800,
.dark .text-red-900 {
color: var(--studio-text-error);
}

.dark .text-blue-800 {
color: var(--studio-text-info);
}

.dark .text-red-700 {
color: var(--studio-text-error);
}
Expand All @@ -92,6 +180,28 @@
--tw-ring-color: var(--studio-ring-muted);
}

/* Status ring colors in dark mode */
.dark .ring-yellow-400,
.dark .ring-yellow-500 {
--tw-ring-color: var(--studio-ring-warning);
}

.dark .ring-green-400,
.dark .ring-green-500 {
--tw-ring-color: var(--studio-ring-success);
}

.dark .ring-red-400,
.dark .ring-red-500 {
--tw-ring-color: var(--studio-ring-error);
}

.dark .ring-gray-400,
.dark .ring-gray-500,
.dark .ring-slate-500 {
--tw-ring-color: var(--studio-ring-muted);
}

/* ---- Ring / shadow ---- */
.dark .ring-black\/5,
.dark .ring-opacity-5 {
Expand Down Expand Up @@ -358,6 +468,62 @@
}


/* ---- Task action button gradients (dark mode) ---- */
.dark .from-blue-500 {
--tw-gradient-from: #1d4ed8;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(29 78 216 / 0));
}

.dark .to-blue-600 {
--tw-gradient-to: #1e40af;
}

.dark .hover\:from-blue-600:hover {
--tw-gradient-from: #2563eb;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(37 99 235 / 0));
}

.dark .hover\:to-blue-700:hover {
--tw-gradient-to: #1d4ed8;
}

.dark .from-green-500 {
--tw-gradient-from: #15803d;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(21 128 61 / 0));
}

.dark .to-green-600 {
--tw-gradient-to: #166534;
}

.dark .hover\:from-green-600:hover {
--tw-gradient-from: #16a34a;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(22 163 74 / 0));
}

.dark .hover\:to-green-700:hover {
--tw-gradient-to: #15803d;
}

/* Red action buttons: pending cancel (dark mode) */
.dark .from-red-500 {
--tw-gradient-from: #b91c1c;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(185 28 28 / 0));
}

.dark .to-red-600 {
--tw-gradient-to: #991b1b;
}

.dark .hover\:from-red-600:hover {
--tw-gradient-from: #dc2626;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(220 38 38 / 0));
}

.dark .hover\:to-red-700:hover {
--tw-gradient-to: #b91c1c;
}

/* ---- Input placeholder contrast ---- */
.dark ::placeholder,
.dark .placeholder\:text-gray-400::placeholder {
Expand Down
30 changes: 30 additions & 0 deletions frontend/public/theme-variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,23 @@
--studio-bg-warning: #fefce8;
--studio-bg-success: #f0fdf4;
--studio-bg-info: #eff6ff;
--studio-bg-warning-active: #fef9c3;
--studio-bg-success-active: #dcfce7;
--studio-bg-error-active: #fee2e2;
--studio-bg-warning-hover: #fef08a;
--studio-bg-success-hover: #bbf7d0;
--studio-bg-error-hover: #fecaca;
--studio-border-error: #fecaca;
--studio-border-warning: #fde047;
--studio-border-success: #bbf7d0;
--studio-border-info: #bfdbfe;
--studio-text-error: #b91c1c;
--studio-text-warning: #92400e;
--studio-text-success: #15803d;
--studio-text-info: #1e40af;
--studio-ring-success: rgba(34, 197, 94, 0.2);
--studio-ring-warning: rgba(245, 158, 11, 0.2);
--studio-ring-error: rgba(239, 68, 68, 0.2);
--studio-ring-muted: rgba(75, 85, 99, 0.2);

/* Tooltip */
Expand Down Expand Up @@ -150,13 +160,23 @@
--studio-bg-warning: #422006;
--studio-bg-success: #052e16;
--studio-bg-info: #1e3a8a;
--studio-bg-warning-active: #713f12;
--studio-bg-success-active: #14532d;
--studio-bg-error-active: #7f1d1d;
--studio-bg-warning-hover: #4d2a0a;
--studio-bg-success-hover: #073b1c;
--studio-bg-error-hover: #500d0d;
--studio-border-error: #7f1d1d;
--studio-border-warning: #854d0e;
--studio-border-success: #14532d;
--studio-border-info: #1e40af;
--studio-text-error: #fca5a5;
--studio-text-warning: #fcd34d;
--studio-text-success: #86efac;
--studio-text-info: #93c5fd;
--studio-ring-success: rgba(34, 197, 94, 0.3);
--studio-ring-warning: rgba(252, 211, 77, 0.25);
--studio-ring-error: rgba(252, 165, 165, 0.25);
--studio-ring-muted: rgba(75, 85, 99, 0.4);

/* Tooltip */
Expand Down Expand Up @@ -229,13 +249,23 @@
--studio-bg-warning: #422006;
--studio-bg-success: #052e16;
--studio-bg-info: #1e3a8a;
--studio-bg-warning-active: #713f12;
--studio-bg-success-active: #14532d;
--studio-bg-error-active: #7f1d1d;
--studio-bg-warning-hover: #4d2a0a;
--studio-bg-success-hover: #073b1c;
--studio-bg-error-hover: #500d0d;
--studio-border-error: #7f1d1d;
--studio-border-warning: #854d0e;
--studio-border-success: #14532d;
--studio-border-info: #1e40af;
--studio-text-error: #fca5a5;
--studio-text-warning: #fcd34d;
--studio-text-success: #86efac;
--studio-text-info: #93c5fd;
--studio-ring-success: rgba(34, 197, 94, 0.3);
--studio-ring-warning: rgba(252, 211, 77, 0.25);
--studio-ring-error: rgba(252, 165, 165, 0.25);
--studio-ring-muted: rgba(75, 85, 99, 0.4);
--studio-tooltip-bg: #252525;
--studio-tooltip-text: #e8e8e8;
Expand Down
22 changes: 11 additions & 11 deletions frontend/src/task-by-name/task-by-name.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@
</div>
<div
v-if="numDocs > 0"
class="fixed bottom-0 left-0 right-0 z-10 px-4 py-4 bg-white border-t border-gray-200 shadow-[0_-4px_6px_-1px_rgba(0,0,0,0.1)]"
class="fixed bottom-0 left-0 right-0 z-10 px-4 py-4 bg-surface border-t border-edge shadow-[0_-4px_6px_-1px_rgba(0,0,0,0.1)]"
>
<div class="flex flex-wrap items-center justify-between gap-4 max-w-6xl mx-auto">
<div class="flex items-center gap-6">
<p class="text-sm text-gray-600">
<span class="font-medium text-gray-900">{{ Math.min((page - 1) * pageSize + 1, numDocs) }}–{{ Math.min(page * pageSize, numDocs) }}</span>
<p class="text-sm text-content-tertiary">
<span class="font-medium text-content">{{ Math.min((page - 1) * pageSize + 1, numDocs) }}–{{ Math.min(page * pageSize, numDocs) }}</span>
<span class="mx-1">of</span>
<span class="font-medium text-gray-900">{{ numDocs }}</span>
<span class="ml-1 text-gray-500">tasks</span>
<span class="font-medium text-content">{{ numDocs }}</span>
<span class="ml-1 text-content-tertiary">tasks</span>
</p>
<div class="flex items-center gap-2">
<label class="text-sm font-medium text-gray-700">Per page</label>
<label class="text-sm font-medium text-content-secondary">Per page</label>
<select
v-model.number="pageSize"
@change="onPageSizeChange"
class="border border-gray-300 rounded-md shadow-sm px-3 py-2 text-sm text-gray-700 bg-white hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-ultramarine-500 focus:border-ultramarine-500"
class="border border-edge rounded-md shadow-sm px-3 py-2 text-sm text-content-secondary bg-surface hover:border-edge-strong focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary"
>
<option v-for="n in pageSizeOptions" :key="n" :value="n">{{ n }}</option>
</select>
Expand All @@ -57,21 +57,21 @@
type="button"
:disabled="page <= 1"
@click="goToPage(page - 1)"
class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium rounded-md border transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-white bg-white text-gray-700 border-gray-300 hover:bg-gray-50 hover:border-gray-400"
class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium rounded-md border transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-surface bg-surface text-content-secondary border-edge hover:bg-page hover:border-edge-strong"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
Previous
</button>
<span class="px-4 py-2 text-sm text-gray-600 min-w-[7rem] text-center">
Page <span class="font-semibold text-gray-900">{{ page }}</span> of <span class="font-semibold text-gray-900">{{ Math.max(1, Math.ceil(numDocs / pageSize)) }}</span>
<span class="px-4 py-2 text-sm text-content-tertiary min-w-[7rem] text-center">
Page <span class="font-semibold text-content">{{ page }}</span> of <span class="font-semibold text-content">{{ Math.max(1, Math.ceil(numDocs / pageSize)) }}</span>
</span>
<button
type="button"
:disabled="page >= Math.ceil(numDocs / pageSize)"
@click="goToPage(page + 1)"
class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium rounded-md border transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-white bg-white text-gray-700 border-gray-300 hover:bg-gray-50 hover:border-gray-400"
class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium rounded-md border transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-surface bg-surface text-content-secondary border-edge hover:bg-page hover:border-edge-strong"
>
Next
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/task-single/task-single.html
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ <h3 class="text-lg font-medium text-content mb-4">Reschedule Task</h3>
class="w-full px-3 py-2 border border-edge-strong rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 mb-4"
/>
<div class="flex gap-3">
<button @click="confirmRescheduleTask" class="flex-1 bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 font-medium">Reschedule</button>
<button @click="confirmRescheduleTask" class="flex-1 bg-gradient-to-r from-blue-500 to-blue-600 text-white px-4 py-2 rounded-md hover:from-blue-600 hover:to-blue-700 font-medium">Reschedule</button>
<button @click="showRescheduleModal = false" class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Cancel</button>
</div>
</div>
Expand All @@ -132,7 +132,7 @@ <h3 class="text-lg font-medium text-content mb-4">Run Task Now</h3>
<p class="text-sm text-gray-600 mb-2">Run task <strong>{{ selectedTask?.id }}</strong> immediately?</p>
<p class="text-sm text-content-tertiary mb-4">This will execute the task right away, bypassing its scheduled time.</p>
<div class="flex gap-3">
<button @click="confirmRunTask" class="flex-1 bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700 font-medium">Run Now</button>
<button @click="confirmRunTask" class="flex-1 bg-gradient-to-r from-green-500 to-green-600 text-white px-4 py-2 rounded-md hover:from-green-600 hover:to-green-700 font-medium">Run Now</button>
<button @click="showRunModal = false" class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Cancel</button>
</div>
</div>
Expand All @@ -148,8 +148,8 @@ <h3 class="text-lg font-medium text-content mb-4">Cancel Task</h3>
<p class="text-sm text-gray-600 mb-2">Cancel task <strong>{{ selectedTask?.id }}</strong>?</p>
<p class="text-sm text-content-tertiary mb-4">This will permanently cancel the task and it cannot be undone.</p>
<div class="flex gap-3">
<button @click="confirmCancelTask" class="flex-1 bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 font-medium">Cancel Task</button>
<button @click="showCancelModal = false" class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Keep Task</button>
<button @click="confirmCancelTask" class="flex-1 bg-gradient-to-r from-red-500 to-red-600 text-white px-4 py-2 rounded-md hover:from-red-600 hover:to-red-700 font-medium">Cancel Task</button>
<button @click="showCancelModal = false" class="flex-1 bg-muted hover:bg-page text-content-secondary px-4 py-2 rounded-md border border-edge-strong font-medium">Keep Task</button>
</div>
</div>
</template>
Expand Down
Loading
Loading