- Inline grouped tool-call rendering in chat surfaces and update summary logic for clearer aggregation
- Refine chat, quick FAB, settings, and agents UI styles/behavior with matching test coverage updates
- Extend dashboard TUI state/controller flow with status and shortcut improvements
- Update engine and dashboard route handling related to agent runs, settings memory sync, and remote access adapters
Fusion-Task-Id: FN-2926
- Add attachment-first chat compose flow with paperclip picker, drag-and-drop, and paste support in ChatView input
- Render pending attachment preview chips with per-file remove actions and drag-over visual affordance
- Display sent message attachments with image/file presentation and accessible focus/interaction styling
- Update ChatView tests and icon mocks to cover attachment-only sends, file selection, and preview behavior
Fusion-Task-Id: FN-2911
- Remove btn-icon styling from ChatView render toggle controls and apply dedicated borderless toggle styling
- Update ChatView and QuickChatFAB behavior so quick chat streaming state is preserved when resuming sessions
- Add regression tests for QuickChatFAB and useQuickChat to cover resume and streaming-state handling
Fusion-Task-Id: FN-2906
- Add a shared useMobileKeyboard hook that tracks visualViewport overlap on mobile browsers
- Apply keyboard overlap CSS variables to QuickChatFAB so fullscreen mobile panels resize above the virtual keyboard
- Apply the same keyboard-aware sizing to ChatView mobile thread layout and auto-scroll messages when keyboard opens
- Expand ChatView, QuickChatFAB, and hook test coverage for mobile keyboard detection and viewport-resize behavior
- Track plain-text render mode per assistant message (including streaming output) in ChatView state
- Add inline mobile-only Eye/EyeOff toggle buttons on assistant bubbles to switch markdown vs plain text per message
- Hide the header markdown/plain toggle on mobile and polish inline toggle sizing, focus, and hover styles in ChatView.css
- Extend ChatView tests with mobile viewport coverage for toggle rendering, per-message isolation, round-trip toggling, and mobile CSS contract checks
- ChatView mobile: hide the top sidebar header's "New Chat" button on
<=768px and show the existing footer button as a pinned full-width
action with safe-area padding. Both buttons existed in JSX; only
CSS was needed.
- styles.css: comments compose/edit textareas use var(--surface) so
they remain visible against the task detail modal's --card panel
(in light theme --bg and --card both resolve to #ffffff).
- Includes resolved-conflict changes from fusion/fn-2469 in
ModelOnboardingModal and SettingsModal (and the related test).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 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>
Split app/styles.css from ~40k lines down to ~4.5k. Created 56 co-located
component CSS files in app/components/, each imported by its owning .tsx.
The remainder of styles.css holds genuinely global rules (design tokens,
.btn/.card/.modal/.form-input primitives, cross-component @media overrides).
- Lazy-load 13 heavy views (AgentsView, RoadmapsView, NodesView, etc.) via
React.lazy + Suspense; prefetch all chunks on idle so first navigation is
instant. Initial JS bundle: 1.58 MB → 1.16 MB (-26%). Initial CSS bundle:
635 kB → 471 kB (-26%); the rest splits into 13 per-view chunks.
- Add app/test/cssFixture.ts exposing loadAllAppCss() + loadAllAppCssBaseOnly()
so CSS regression tests load the full per-component bundle (mirroring Vite
source order). Migrate 30+ tests off direct readFileSync('../styles.css').
- Enable test.css: { include: [/.+/] } in vitest.config.ts so component CSS
imports actually inject styles in jsdom (fixes getComputedStyle assertions).
- Add ESLint rule (no-restricted-syntax) banning direct styles.css reads in
dashboard test files; points at loadAllAppCss() instead.
- Restore lost utility classes (.text-muted, .text-secondary, .text-dim,
.form-input) and rescue dropped chat tool-call rules into QuickChatFAB.css.
- Mobile fixes along the way: scroll containment for view containers
(min-height:0 + -webkit-overflow-scrolling), QuickChatFAB full-screen on
mobile (with safe-area-inset for iOS home bar), AgentsView single-row
header layout, ActivityLogModal close button on right, model-combobox
z-index above the mobile quick-chat panel.
- Bug fix: SkillsView toggle was display:none which hid the input from the
accessibility tree; replaced with the visually-hidden pattern so screen
readers + getByRole still find the checkbox.
- Bug fix: standalone Delete button in TaskDetailModal for triage-column
tasks (Actions dropdown is hidden in triage state, so previously no way
to delete a freshly-created task without status change first).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>