fix(FN-1302): theme GitHub import issue list with proper dark/light mode support
- Replace hardcoded colors with CSS custom properties (theme tokens) across GitHub import components - Add accent-color to radio buttons using --in-progress token - Add explicit light theme overrides via [data-theme="light"] selectors for tabs, toolbar, issues list, preview, labels, and state panels - Style filter input with theme-aware border, background, focus ring, and placeholder colors - Fix form-error background to use color-mix instead of hardcoded rgba
This commit is contained in:
@@ -26,6 +26,11 @@
|
|||||||
- For conditionally rendered mobile inputs in dashboard components, prefer React `autoFocus` on the input over effect+`setTimeout` focus logic keyed to open-state booleans; mount timing is more reliable and simpler.
|
- For conditionally rendered mobile inputs in dashboard components, prefer React `autoFocus` on the input over effect+`setTimeout` focus logic keyed to open-state booleans; mount timing is more reliable and simpler.
|
||||||
- Checkout leasing is explicit: use `checkoutTask`/`releaseTask` (or `/api/tasks/:id/checkout` + `/release`) for ownership, treat 409 conflicts as non-retryable contention, and let `HeartbeatMonitor.executeHeartbeat()` only validate `checkedOutBy` (never auto-acquire leases).
|
- Checkout leasing is explicit: use `checkoutTask`/`releaseTask` (or `/api/tasks/:id/checkout` + `/release`) for ownership, treat 409 conflicts as non-retryable contention, and let `HeartbeatMonitor.executeHeartbeat()` only validate `checkedOutBy` (never auto-acquire leases).
|
||||||
|
|
||||||
|
## Color Theme System
|
||||||
|
|
||||||
|
- There are **34 unique color themes** in `packages/dashboard/app/styles.css` (ocean, forest, sunset, berry, monochrome, slate, ash, graphite, silver, zen, high-contrast, industrial, solarized, factory, ayu, one-dark, nord, dracula, gruvbox, tokyo-night, catppuccin-mocha, github-dark, everforest, rose-pine, kanagawa, night-owl, palenight, monokai-pro, slime, brutalist, neon-city, parchment, terminal, glass). Each has a dark variant `[data-color-theme="<name>"]` and a light variant `[data-color-theme="<name>"][data-theme="light"]`.
|
||||||
|
- When adding CSS custom properties that should be theme-aware (like `--accent`, `--status-*-bg`), add them to all 34 theme blocks plus `:root` and `[data-theme="light"]` base blocks. The test in `status-colors-theme.test.ts` iterates all blocks programmatically to prevent regressions.
|
||||||
|
|
||||||
## Pitfalls
|
## Pitfalls
|
||||||
|
|
||||||
- `vi.fn<Parameters<SomeType>, ReturnType<SomeType>>()` works in Vitest runtime but causes TypeScript build errors (`TS2558: Expected 0-1 type arguments, but got 2`). Always use the cast pattern instead.
|
- `vi.fn<Parameters<SomeType>, ReturnType<SomeType>>()` works in Vitest runtime but causes TypeScript build errors (`TS2558: Expected 0-1 type arguments, but got 2`). Always use the cast pattern instead.
|
||||||
|
|||||||
@@ -6343,6 +6343,27 @@ body {
|
|||||||
.github-import-toolbar__zone--filter input {
|
.github-import-toolbar__zone--filter input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
background: var(--card);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
color: var(--text);
|
||||||
|
padding: var(--space-sm) var(--space-md);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-import-toolbar__zone--filter input:focus {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(var(--color-primary-rgb), 0.2);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-import-toolbar__zone--filter input:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-import-toolbar__zone--filter input::placeholder {
|
||||||
|
color: var(--text-dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
.github-import-toolbar__zone--action {
|
.github-import-toolbar__zone--action {
|
||||||
@@ -6568,7 +6589,7 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-md);
|
gap: var(--space-md);
|
||||||
padding: var(--space-lg);
|
padding: var(--space-lg);
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 60%), var(--card);
|
background: var(--card);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
}
|
}
|
||||||
@@ -6704,7 +6725,7 @@ body {
|
|||||||
.form-error {
|
.form-error {
|
||||||
margin: var(--space-md) 0;
|
margin: var(--space-md) 0;
|
||||||
padding: var(--space-sm) var(--space-md);
|
padding: var(--space-sm) var(--space-md);
|
||||||
background: rgba(248, 81, 73, 0.1);
|
background: color-mix(in srgb, var(--color-error) 10%, transparent);
|
||||||
border: 1px solid var(--color-error);
|
border: 1px solid var(--color-error);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
color: var(--color-error);
|
color: var(--color-error);
|
||||||
@@ -6813,6 +6834,12 @@ body {
|
|||||||
.issue-item input[type="radio"] {
|
.issue-item input[type="radio"] {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
accent-color: var(--in-progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-item.imported input[type="radio"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.issue-item:hover:not(.imported) {
|
.issue-item:hover:not(.imported) {
|
||||||
@@ -6925,6 +6952,65 @@ body {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Light theme overrides for GitHub import components */
|
||||||
|
[data-theme="light"] .github-import-tabs {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .github-import-tab.active {
|
||||||
|
background: var(--card);
|
||||||
|
border-color: var(--border);
|
||||||
|
box-shadow: 0 1px 3px rgba(31, 35, 40, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .github-import-toolbar {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-bottom-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .github-import-toolbar__zone--filter input {
|
||||||
|
background: var(--card);
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .github-import-toolbar__zone--filter input:focus {
|
||||||
|
border-color: var(--color-primary, var(--todo));
|
||||||
|
box-shadow: 0 0 0 2px rgba(var(--in-progress-rgb), 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .issues-list {
|
||||||
|
background: var(--card);
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .issue-item:hover:not(.imported) {
|
||||||
|
background: var(--card-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .issue-item.selected {
|
||||||
|
background: rgba(var(--in-progress-rgb), 0.08);
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(var(--in-progress-rgb), 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .issue-item.imported input[type="radio"] {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .github-import-state {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .issue-preview {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] .label-chip {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
/* Responsive breakpoints */
|
/* Responsive breakpoints */
|
||||||
@media (max-width: 860px) {
|
@media (max-width: 860px) {
|
||||||
.github-import-modal {
|
.github-import-modal {
|
||||||
|
|||||||
Reference in New Issue
Block a user