* chore(ST-1112): add deps for task dialog Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): add shared zod schema for task dialog Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): add missing MD3 tokens for task dialog outline-variant, on-error-container, status-review (light + dark) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): add saveTask and deleteTask server actions for TaskDialog Unified create/edit action (saveTask) replaces separate formData-based actions for the new TaskDialog. Uses shared zod schema, structured SaveTaskResult union type, and context-aware revalidatePath for both sprint and backlog routes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): add TaskDialog component (create & edit mode) Builds the full TaskDialog on top of the existing @base-ui/react Dialog primitive. Covers create mode, edit mode (status field + created_at metadata + delete), dirty-check AlertDialog, delete confirm AlertDialog, Cmd+Enter submit, and per-field char counters. Uses react-hook-form + zodResolver against the shared taskSchema. Priority and status are extracted to PrioritySegmented and StatusSelect sub-components using MD3 tokens throughout. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): refactor task-list to open TaskDialog via URL params Replaces inline create/edit forms with router.push navigation: - Clicking a task row → ?editTask=<id> - "+ Taak" button → ?newTask=1&storyId=<storyId> Removes CreateTaskForm, EditSubmitButton, updateTaskAction, and createTaskAction from the component. Status toggle and DnD remain unchanged. Rows now have cursor-pointer and keyboard a11y. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): wire TaskDialog into sprint page via searchParams Sprint page now reads ?newTask, ?storyId, and ?editTask query params. For edit mode: fetches the task server-side with productAccessFilter scope (invalid/foreign IDs redirect to closePath). Renders TaskDialog when either param is present. closePath is the sprint route without query params. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): add Suspense skeleton for edit-mode task loading Extracts task fetch into EditTaskLoader (async server component) so the sprint board renders immediately while the task loads. TaskDialogSkeleton shows 3 grey bars during the fetch. Invalid or out-of-scope task IDs redirect to closePath. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): render description as markdown in task-detail-dialog Solo task detail now renders description via react-markdown + remark-gfm with prose styling. Sanitizes script/iframe elements. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(ST-1112): add saveTask/deleteTask server action tests Covers all three demo-policy layers and cross-tenant scope: demo blocked (403), unauthenticated blocked, validation 422, edit cross-tenant forbidden, create cross-tenant forbidden, and happy-path for both edit and create. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): add updateTaskStatusWithStoryPromotion helper Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1112): wire story-promotion into saveTask and PATCH /api/tasks/:id Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(ST-1112): add task-dialog doc and architecture note Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: extend allowed tools in settings.local.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1113): add 200ms animation-delay to TaskDialogSkeleton to prevent flicker Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1114): add DirtyCloseGuard reusable component for dirty-form close confirmation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ST-1114): add shared Markdown wrapper, apply to task-detail and story-dialog Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: allow grep -E pattern in settings.local.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
393 lines
12 KiB
CSS
393 lines
12 KiB
CSS
@custom-variant dark (&:is(.dark *));
|
|
|
|
:root {
|
|
--font-size: 16px;
|
|
|
|
/* MD3 Surface Colors */
|
|
--background: #fdfcff;
|
|
--foreground: #1b1b1f;
|
|
--surface: #fdfcff;
|
|
--surface-dim: #dbd9e0;
|
|
--surface-bright: #fdfcff;
|
|
--surface-container-lowest: #ffffff;
|
|
--surface-container-low: #f7f5fc;
|
|
--surface-container: #f1eff6;
|
|
--surface-container-high: #ebeaf0;
|
|
--surface-container-highest: #e6e3ea;
|
|
|
|
/* MD3 Primary Color (Blue - Productivity) */
|
|
--primary: #0061a4;
|
|
--primary-foreground: #ffffff;
|
|
--primary-container: #d1e4ff;
|
|
--primary-container-foreground: #001d36;
|
|
--on-primary: #ffffff;
|
|
|
|
/* MD3 Secondary Color (Purple - Planning) */
|
|
--secondary: #5b5e71;
|
|
--secondary-foreground: #ffffff;
|
|
--secondary-container: #dfe1f9;
|
|
--secondary-container-foreground: #181b2c;
|
|
--on-secondary: #ffffff;
|
|
|
|
/* MD3 Tertiary Color (Teal - Progress) */
|
|
--tertiary: #006874;
|
|
--tertiary-foreground: #ffffff;
|
|
--tertiary-container: #97f0ff;
|
|
--tertiary-container-foreground: #001f24;
|
|
|
|
/* Semantic State Colors */
|
|
--success: #006e1c;
|
|
--success-foreground: #ffffff;
|
|
--success-container: #92f894;
|
|
--success-container-foreground: #002204;
|
|
|
|
--warning: #735b00;
|
|
--warning-foreground: #ffffff;
|
|
--warning-container: #ffdf9d;
|
|
--warning-container-foreground: #231b00;
|
|
|
|
--error: #ba1a1a;
|
|
--error-foreground: #ffffff;
|
|
--error-container: #ffdad6;
|
|
--error-container-foreground: #410002;
|
|
|
|
--info: #006493;
|
|
--info-foreground: #ffffff;
|
|
--info-container: #c9e6ff;
|
|
--info-container-foreground: #001e2f;
|
|
|
|
/* Legacy shadcn mappings */
|
|
--card: var(--surface-container-low);
|
|
--card-foreground: var(--foreground);
|
|
--popover: var(--surface-container);
|
|
--popover-foreground: var(--foreground);
|
|
--muted: var(--surface-container-high);
|
|
--muted-foreground: #45464f;
|
|
--accent: var(--secondary-container);
|
|
--accent-foreground: var(--secondary-container-foreground);
|
|
--destructive: var(--error);
|
|
--destructive-foreground: var(--error-foreground);
|
|
--border: #c5c6d0;
|
|
--input: transparent;
|
|
--input-background: var(--surface-container);
|
|
--switch-background: #79767d;
|
|
--ring: var(--primary);
|
|
|
|
/* MD3 Outline Variant */
|
|
--outline-variant: #c5c6d0;
|
|
|
|
/* MD3 On-Error-Container */
|
|
--on-error-container: #410002;
|
|
|
|
/* Project Management Specific Colors */
|
|
--status-todo: #6750a4;
|
|
--status-in-progress: #0061a4;
|
|
--status-review: #7b5ea7;
|
|
--status-done: #006e1c;
|
|
--status-blocked: #ba1a1a;
|
|
|
|
--priority-critical: #ba1a1a;
|
|
--priority-high: #c75300;
|
|
--priority-medium: #735b00;
|
|
--priority-low: #006874;
|
|
|
|
/* Chart Colors */
|
|
--chart-1: var(--primary);
|
|
--chart-2: var(--secondary);
|
|
--chart-3: var(--tertiary);
|
|
--chart-4: var(--success);
|
|
--chart-5: var(--warning);
|
|
|
|
--font-weight-medium: 500;
|
|
--font-weight-normal: 400;
|
|
--radius: 0.75rem;
|
|
|
|
/* Sidebar */
|
|
--sidebar: var(--surface-container-low);
|
|
--sidebar-foreground: var(--foreground);
|
|
--sidebar-primary: var(--primary);
|
|
--sidebar-primary-foreground: var(--primary-foreground);
|
|
--sidebar-accent: var(--surface-container-high);
|
|
--sidebar-accent-foreground: var(--foreground);
|
|
--sidebar-border: var(--border);
|
|
--sidebar-ring: var(--primary);
|
|
}
|
|
|
|
.dark {
|
|
/* MD3 Dark Surface Colors */
|
|
--background: #1b1b1f;
|
|
--foreground: #e4e1e9;
|
|
--surface: #1b1b1f;
|
|
--surface-dim: #1b1b1f;
|
|
--surface-bright: #413f47;
|
|
--surface-container-lowest: #0f0e13;
|
|
--surface-container-low: #232227;
|
|
--surface-container: #27262b;
|
|
--surface-container-high: #322f36;
|
|
--surface-container-highest: #3d3a41;
|
|
|
|
/* MD3 Primary Color (Blue) */
|
|
--primary: #9fcbfa;
|
|
--primary-foreground: #003257;
|
|
--primary-container: #00497b;
|
|
--primary-container-foreground: #d1e4ff;
|
|
--on-primary: #003257;
|
|
|
|
/* MD3 Secondary Color (Purple) */
|
|
--secondary: #c3c4dd;
|
|
--secondary-foreground: #2c2f42;
|
|
--secondary-container: #434659;
|
|
--secondary-container-foreground: #dfe1f9;
|
|
--on-secondary: #2c2f42;
|
|
|
|
/* MD3 Tertiary Color (Teal) */
|
|
--tertiary: #4fd8eb;
|
|
--tertiary-foreground: #00363d;
|
|
--tertiary-container: #004f58;
|
|
--tertiary-container-foreground: #97f0ff;
|
|
|
|
/* Semantic State Colors */
|
|
--success: #77db77;
|
|
--success-foreground: #00390a;
|
|
--success-container: #005313;
|
|
--success-container-foreground: #92f894;
|
|
|
|
--warning: #efc047;
|
|
--warning-foreground: #3c2f00;
|
|
--warning-container: #574400;
|
|
--warning-container-foreground: #ffdf9d;
|
|
|
|
--error: #ffb4ab;
|
|
--error-foreground: #690005;
|
|
--error-container: #93000a;
|
|
--error-container-foreground: #ffdad6;
|
|
|
|
--info: #87ceff;
|
|
--info-foreground: #00344d;
|
|
--info-container: #004c6d;
|
|
--info-container-foreground: #c9e6ff;
|
|
|
|
/* Legacy shadcn mappings */
|
|
--card: var(--surface-container-low);
|
|
--card-foreground: var(--foreground);
|
|
--popover: var(--surface-container);
|
|
--popover-foreground: var(--foreground);
|
|
--muted: var(--surface-container-high);
|
|
--muted-foreground: #c5c6d0;
|
|
--accent: var(--secondary-container);
|
|
--accent-foreground: var(--secondary-container-foreground);
|
|
--destructive: var(--error);
|
|
--destructive-foreground: var(--error-container-foreground);
|
|
--border: #45464f;
|
|
--input: transparent;
|
|
--input-background: var(--surface-container);
|
|
--switch-background: #898790;
|
|
--ring: var(--primary);
|
|
|
|
/* MD3 Outline Variant */
|
|
--outline-variant: #45464f;
|
|
|
|
/* MD3 On-Error-Container */
|
|
--on-error-container: #ffdad6;
|
|
|
|
/* Project Management Specific Colors */
|
|
--status-todo: #cfbdfe;
|
|
--status-in-progress: #9fcbfa;
|
|
--status-review: #c9b6ef;
|
|
--status-done: #77db77;
|
|
--status-blocked: #ffb4ab;
|
|
|
|
--priority-critical: #ffb4ab;
|
|
--priority-high: #ffb68d;
|
|
--priority-medium: #efc047;
|
|
--priority-low: #4fd8eb;
|
|
|
|
/* Chart Colors */
|
|
--chart-1: var(--primary);
|
|
--chart-2: var(--secondary);
|
|
--chart-3: var(--tertiary);
|
|
--chart-4: var(--success);
|
|
--chart-5: var(--warning);
|
|
|
|
/* Sidebar */
|
|
--sidebar: var(--surface-container-low);
|
|
--sidebar-foreground: var(--foreground);
|
|
--sidebar-primary: var(--primary);
|
|
--sidebar-primary-foreground: var(--primary-container);
|
|
--sidebar-accent: var(--surface-container-high);
|
|
--sidebar-accent-foreground: var(--foreground);
|
|
--sidebar-border: var(--border);
|
|
--sidebar-ring: var(--primary);
|
|
}
|
|
|
|
@theme inline {
|
|
/* Base colors */
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
|
|
/* MD3 Surface colors */
|
|
--color-surface: var(--surface);
|
|
--color-surface-dim: var(--surface-dim);
|
|
--color-surface-bright: var(--surface-bright);
|
|
--color-surface-container-lowest: var(--surface-container-lowest);
|
|
--color-surface-container-low: var(--surface-container-low);
|
|
--color-surface-container: var(--surface-container);
|
|
--color-surface-container-high: var(--surface-container-high);
|
|
--color-surface-container-highest: var(--surface-container-highest);
|
|
|
|
/* MD3 Primary color */
|
|
--color-primary: var(--primary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
--color-primary-container: var(--primary-container);
|
|
--color-primary-container-foreground: var(--primary-container-foreground);
|
|
--color-on-primary: var(--on-primary);
|
|
|
|
/* MD3 Secondary color */
|
|
--color-secondary: var(--secondary);
|
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
--color-secondary-container: var(--secondary-container);
|
|
--color-secondary-container-foreground: var(--secondary-container-foreground);
|
|
--color-on-secondary: var(--on-secondary);
|
|
|
|
/* MD3 Tertiary color */
|
|
--color-tertiary: var(--tertiary);
|
|
--color-tertiary-foreground: var(--tertiary-foreground);
|
|
--color-tertiary-container: var(--tertiary-container);
|
|
--color-tertiary-container-foreground: var(--tertiary-container-foreground);
|
|
|
|
/* Semantic states */
|
|
--color-success: var(--success);
|
|
--color-success-foreground: var(--success-foreground);
|
|
--color-success-container: var(--success-container);
|
|
--color-success-container-foreground: var(--success-container-foreground);
|
|
|
|
--color-warning: var(--warning);
|
|
--color-warning-foreground: var(--warning-foreground);
|
|
--color-warning-container: var(--warning-container);
|
|
--color-warning-container-foreground: var(--warning-container-foreground);
|
|
|
|
--color-error: var(--error);
|
|
--color-error-foreground: var(--error-foreground);
|
|
--color-error-container: var(--error-container);
|
|
--color-error-container-foreground: var(--error-container-foreground);
|
|
--color-on-error-container: var(--on-error-container);
|
|
|
|
--color-info: var(--info);
|
|
--color-info-foreground: var(--info-foreground);
|
|
--color-info-container: var(--info-container);
|
|
--color-info-container-foreground: var(--info-container-foreground);
|
|
|
|
/* Legacy shadcn */
|
|
--color-card: var(--card);
|
|
--color-card-foreground: var(--card-foreground);
|
|
--color-popover: var(--popover);
|
|
--color-popover-foreground: var(--popover-foreground);
|
|
--color-muted: var(--muted);
|
|
--color-muted-foreground: var(--muted-foreground);
|
|
--color-accent: var(--accent);
|
|
--color-accent-foreground: var(--accent-foreground);
|
|
--color-destructive: var(--destructive);
|
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
--color-outline-variant: var(--outline-variant);
|
|
--color-border: var(--border);
|
|
--color-input: var(--input);
|
|
--color-input-background: var(--input-background);
|
|
--color-switch-background: var(--switch-background);
|
|
--color-ring: var(--ring);
|
|
|
|
/* Project management colors */
|
|
--color-status-todo: var(--status-todo);
|
|
--color-status-in-progress: var(--status-in-progress);
|
|
--color-status-review: var(--status-review);
|
|
--color-status-done: var(--status-done);
|
|
--color-status-blocked: var(--status-blocked);
|
|
|
|
--color-priority-critical: var(--priority-critical);
|
|
--color-priority-high: var(--priority-high);
|
|
--color-priority-medium: var(--priority-medium);
|
|
--color-priority-low: var(--priority-low);
|
|
|
|
/* Charts */
|
|
--color-chart-1: var(--chart-1);
|
|
--color-chart-2: var(--chart-2);
|
|
--color-chart-3: var(--chart-3);
|
|
--color-chart-4: var(--chart-4);
|
|
--color-chart-5: var(--chart-5);
|
|
|
|
/* Radius */
|
|
--radius-sm: calc(var(--radius) - 4px);
|
|
--radius-md: calc(var(--radius) - 2px);
|
|
--radius-lg: var(--radius);
|
|
--radius-xl: calc(var(--radius) + 4px);
|
|
|
|
/* Sidebar */
|
|
--color-sidebar: var(--sidebar);
|
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
--color-sidebar-primary: var(--sidebar-primary);
|
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
--color-sidebar-accent: var(--sidebar-accent);
|
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
--color-sidebar-border: var(--sidebar-border);
|
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border outline-ring/50;
|
|
}
|
|
|
|
body {
|
|
@apply bg-background text-foreground;
|
|
}
|
|
|
|
/**
|
|
* Default typography styles for HTML elements (h1-h4, p, label, button, input).
|
|
* These are in @layer base, so Tailwind utility classes (like text-sm, text-lg) automatically override them.
|
|
*/
|
|
|
|
html {
|
|
font-size: var(--font-size);
|
|
}
|
|
|
|
h1 {
|
|
font-size: var(--text-2xl);
|
|
font-weight: var(--font-weight-medium);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
h2 {
|
|
font-size: var(--text-xl);
|
|
font-weight: var(--font-weight-medium);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
h3 {
|
|
font-size: var(--text-lg);
|
|
font-weight: var(--font-weight-medium);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
h4 {
|
|
font-size: var(--text-base);
|
|
font-weight: var(--font-weight-medium);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
label {
|
|
font-size: var(--text-base);
|
|
font-weight: var(--font-weight-medium);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
button {
|
|
font-size: var(--text-base);
|
|
font-weight: var(--font-weight-medium);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
input {
|
|
font-size: var(--text-base);
|
|
font-weight: var(--font-weight-normal);
|
|
line-height: 1.5;
|
|
}
|
|
}
|