feat(FN-2628): merge fusion/fn-2628
This commit is contained in:
110
packages/dashboard/app/components/TaskComments.css
Normal file
110
packages/dashboard/app/components/TaskComments.css
Normal file
@@ -0,0 +1,110 @@
|
||||
.comments-header-row {
|
||||
justify-content: space-between;
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.comments-author-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-actions-row {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-edit-form {
|
||||
display: grid;
|
||||
gap: var(--space-sm);
|
||||
margin-top: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-edit-actions {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.comments-outcome-text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.comments-compose-form {
|
||||
display: grid;
|
||||
gap: var(--space-sm);
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
.comments-type-toggle {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-guidance-hint {
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.comments-footer-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comments-char-count {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.comments-char-count--over {
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.comments-textarea {
|
||||
width: 100%;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
background: var(--surface);
|
||||
border: var(--btn-border-width) solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
color: var(--text);
|
||||
font-family: inherit;
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.5;
|
||||
resize: vertical;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.comments-textarea:focus,
|
||||
.comments-textarea:focus-visible {
|
||||
border-color: var(--todo);
|
||||
box-shadow: var(--focus-ring-strong);
|
||||
}
|
||||
|
||||
.comments-textarea::placeholder {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.comments-textarea:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.ai-guidance-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: calc(var(--space-xs) / 4) var(--space-sm);
|
||||
background: color-mix(in srgb, var(--color-info) 15%, transparent);
|
||||
color: var(--color-info);
|
||||
border-radius: var(--radius-pill);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.comments-textarea {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import type { Task, TaskComment } from "@fusion/core";
|
||||
import { getErrorMessage } from "@fusion/core";
|
||||
import "./TaskComments.css";
|
||||
import { addSteeringComment, updateTaskComment, deleteTaskComment } from "../api";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
|
||||
@@ -143,7 +144,7 @@ export function TaskComments({ task, onTaskUpdated, addToast, currentAuthor = "u
|
||||
value={editingText}
|
||||
onChange={(event) => setEditingText(event.target.value)}
|
||||
rows={3}
|
||||
className="spec-editor-feedback"
|
||||
className="comments-textarea"
|
||||
/>
|
||||
<div className="comments-edit-actions">
|
||||
<button
|
||||
@@ -183,7 +184,7 @@ export function TaskComments({ task, onTaskUpdated, addToast, currentAuthor = "u
|
||||
onKeyDown={handleKeyDown}
|
||||
rows={3}
|
||||
placeholder={placeholder}
|
||||
className="spec-editor-feedback"
|
||||
className="comments-textarea"
|
||||
/>
|
||||
<div className="comments-footer-row">
|
||||
<span className={`comments-char-count${isOverLimit ? " comments-char-count--over" : ""}`}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
||||
import { loadAllAppCssBaseOnly } from "../../test/cssFixture";
|
||||
import { TaskComments } from "../TaskComments";
|
||||
|
||||
vi.mock("../../api", () => ({
|
||||
@@ -215,4 +216,29 @@ describe("TaskComments", () => {
|
||||
expect(screen.getByText("Agent guidance")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("CSS styling", () => {
|
||||
const css = loadAllAppCssBaseOnly();
|
||||
|
||||
it.each([
|
||||
{
|
||||
selector: "comments-textarea",
|
||||
assertions: [/\.comments-textarea\s*\{[^}]*background:\s*var\(--surface\);/, /\.comments-textarea\s*\{[^}]*border:\s*var\(--btn-border-width\)\s+solid\s+var\(--border\);/],
|
||||
},
|
||||
{
|
||||
selector: "ai-guidance-badge",
|
||||
assertions: [/\.ai-guidance-badge\s*\{[^}]*color:\s*var\(--color-info\);/],
|
||||
},
|
||||
])("uses tokenized styles for $selector", ({ assertions }) => {
|
||||
for (const assertion of assertions) {
|
||||
expect(css).toMatch(assertion);
|
||||
}
|
||||
});
|
||||
|
||||
it("does not rely on spec-editor-feedback for comment textareas", () => {
|
||||
expect(css).toMatch(/\.comments-textarea\s*\{/);
|
||||
expect(css).not.toContain(".comments-compose-form .spec-editor-feedback");
|
||||
expect(css).not.toContain(".comments-edit-form .spec-editor-feedback");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1418,77 +1418,6 @@ input[type="range"]:focus-visible {
|
||||
}
|
||||
|
||||
|
||||
/* === Task Comments === */
|
||||
.comments-header-row {
|
||||
justify-content: space-between;
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.comments-author-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-actions-row {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-edit-form {
|
||||
display: grid;
|
||||
gap: var(--space-sm);
|
||||
margin-top: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-edit-actions {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.comments-outcome-text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.comments-compose-form {
|
||||
display: grid;
|
||||
gap: var(--space-sm);
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
/* Comment textareas use --surface so they remain visible against the
|
||||
task detail modal's --card / --bg panels (in light mode --bg and
|
||||
--card are both #ffffff, which made the box blend in). */
|
||||
.comments-compose-form .spec-editor-feedback,
|
||||
.comments-edit-form .spec-editor-feedback {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
.comments-type-toggle {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.comments-guidance-hint {
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.comments-footer-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comments-char-count {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.comments-char-count--over {
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
/* === PR Section === */
|
||||
.pr-section-icon {
|
||||
vertical-align: middle;
|
||||
|
||||
Reference in New Issue
Block a user