fix(dashboard): chat mobile single-pane, comment-box theme, ChatView FOUC

- ChatView mobile: add @media (max-width: 768px) so the session-list
  sidebar goes full-width and the thread is hidden when the sidebar
  is visible (and vice-versa). The component already had the state,
  back-button (ChevronLeft), and visibility toggling — only the CSS
  was missing.
- TaskComments compose/edit textareas now use var(--surface) for
  background. The base .spec-editor-feedback uses var(--bg), which
  in light theme resolves to #ffffff — the same as the task detail
  modal's --card panel — making the comment box invisible.
- ChatView CSS is now imported eagerly from App.tsx so it bundles
  into the main CSS file. Previously the lazy ChatView JS chunk
  loaded its CSS via an async <link> tag, producing a brief flash
  of unstyled chat UI on first render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-24 20:35:58 -07:00
parent 1979a72d03
commit 9664f78077
4 changed files with 36 additions and 1 deletions

View File

@@ -51,6 +51,11 @@ const AgentsView = lazy(() => import("./components/AgentsView").then((m) => ({ d
const DocumentsView = lazy(() => import("./components/DocumentsView").then((m) => ({ default: m.DocumentsView })));
const InsightsView = lazy(() => import("./components/InsightsView").then((m) => ({ default: m.InsightsView })));
const NodesView = lazy(() => import("./components/NodesView").then((m) => ({ default: m.NodesView })));
// ChatView's CSS is imported eagerly here (rather than via the lazy
// component) so the styles are bundled into the main CSS file. Without
// this, the lazy JS chunk loaded its own CSS link asynchronously, which
// produced a brief flash of unstyled chat UI on first render.
import "./components/ChatView.css";
const ChatView = lazy(() => import("./components/ChatView").then((m) => ({ default: m.ChatView })));
const RoadmapsView = lazy(() => import("./components/RoadmapsView").then((m) => ({ default: m.RoadmapsView })));
const SkillsView = lazy(() => import("./components/SkillsView").then((m) => ({ default: m.SkillsView })));

View File

@@ -637,3 +637,24 @@
color: var(--text-muted);
}
/* === Mobile: one pane at a time =========================================
Sidebar (session list) and thread are siblings of .chat-view. On mobile
we show whichever one is "active" full-width: when the sidebar is
visible, the thread is hidden; when the sidebar is hidden (a session is
open), the sidebar is collapsed via .chat-sidebar--hidden and the
thread takes the full viewport. The thread already renders a back
button (ChevronLeft) on mobile to flip back to the session list. */
@media (max-width: 768px) {
.chat-sidebar {
width: 100%;
min-width: 0;
border-right: none;
}
/* When the sidebar is shown, the thread is hidden so only the session
list is visible. When the sidebar is hidden, the thread fills the
viewport. Adjacent-sibling selector keeps logic in CSS only. */
.chat-sidebar:not(.chat-sidebar--hidden) + .chat-thread {
display: none;
}
}

View File

@@ -1,4 +1,5 @@
import "./ChatView.css";
// ChatView.css is imported eagerly from App.tsx to avoid a flash of
// unstyled content when the lazy chunk loads. Do not re-import here.
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import {
MessageSquare,

View File

@@ -2164,6 +2164,14 @@ input[type="range"]:focus-visible {
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);