Commit Graph

14 Commits

Author SHA1 Message Date
gsxdsm
16d20063bf FN-5673: keep mobile nav and footer pinned when keyboard opens
Prevent keyboard viewport shifts from displacing mobile bottom bars while preserving iOS hide safeguards.

- Split executor footer keyboard behavior into separate hide and pinning controls
- Add keyboard-open CSS overrides to keep mobile nav/footer bottom at 0 instead of offsetting upward
- Wire App to pass distinct keyboard props and expand component/CSS contract tests for keyboard-open classes and rule ordering

Files changed:
 packages/dashboard/app/App.tsx                     |  3 ++-
 packages/dashboard/app/__tests__/mobile-bottom-bars-keyboard-layout.test.ts | 30 ++++++++++++++++++++++
 packages/dashboard/app/components/ExecutorStatusBar.css |  6 +++++
 packages/dashboard/app/components/ExecutorStatusBar.tsx | 14 +++++-----
 packages/dashboard/app/components/MobileNavBar.css |  3 ++-
 packages/dashboard/app/components/__tests__/ExecutorStatusBar.test.tsx | 17 ++++++++++++
 packages/dashboard/app/components/__tests__/MobileNavBar.test.tsx |  6 +++--
 7 files changed, 69 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-5673

Fusion-Task-Lineage: 7c2dc749-214a-48ab-af58-5638ea27ae47
2026-05-29 09:32:22 -07:00
gsxdsm
a7ad30f22a fix(dashboard): keep mobile nav bar pinned when iOS keyboard opens
The visualViewport ICB compensation (intended for Android ICB-stuck-large
and pinch-zoom) was also reacting to iOS soft-keyboard shrinkage, pushing
the mobile bottom nav up above the keyboard. Pass the existing
`keyboardOpen` prop through to a `mobile-nav-bar--keyboard-open` modifier
class that pins `bottom: 0` so the keyboard simply covers the bar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 02:50:37 -07:00
gsxdsm
ba9d6326e4 fix(dashboard): floor mobile nav inset so Android Chrome gesture bar can't overlap
Android Chrome under viewport-fit=cover intermittently reports
env(safe-area-inset-bottom) as 0 while the address bar is visible or
during URL-bar collapse, causing the bottom nav to render beneath the
system gesture pill. Floor the inset to 12px in MobileNavBar's own
padding and the matching content-padding rules so the bar always clears
the gesture area; devices that report a larger inset are unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 20:48:09 -07:00
gsxdsm
d37bebf8bf feat(FN-5516): merge fusion/fn-5516 2026-05-22 17:24:38 -07:00
gsxdsm
e138289a80 fix(dashboard): compensate Android Chrome inflated ICB for fixed-position UI
Some Android Chrome builds (multi-window / split-screen / certain WebViews)
leave window.innerWidth/Height stuck larger than the actual rendered canvas.
DOM, body, and visualViewport report the true dimensions, but position:fixed
uses the ICB, pinning fixed-bottom elements offscreen below the visible area.
JS-side meta override (setAttribute and full replacement) does not force
Chrome to recompute the ICB on those builds.

index.html now publishes the ICB→visualViewport delta as CSS variables
(--icb-bottom-offset, --icb-right-offset) on <html>. MobileNavBar.css and
ExecutorStatusBar.css consume them so the bars pin to the visible viewport
edge regardless of ICB drift. Math is visualViewport-relative so it also
handles pinch-zoom in (offsets compensate) and pinch-zoom out (clamp at 0).
Healthy browsers see 0px and behave unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:55:20 -07:00
gsxdsm
ed4d021d3d fix(dashboard): keep mobile nav visible on Android landscape and during keyboard
- Broaden mobile media query to include (max-height: 480px) so landscape
  phones (which exceed 768 CSS px wide) still render the bottom nav and
  mobile board layout instead of desktop horizontally-scrollable columns.
- Guard useMobileKeyboard against pinch-zoom (vv.scale > 1) — Android
  Chrome ignores user-scalable=no, and a focused textarea + zoom was
  false-positiving keyboard-open and hiding MobileNavBar.
- Read documentElement.clientHeight instead of stale window.innerHeight
  when computing keyboard overlap (Android multi-window can leave
  innerHeight cached at a wildly different value than the actual layout
  viewport — observed 2848 while html was 797).
- Add interactive-widget=resizes-content to the viewport meta so Android
  Chrome shrinks the layout viewport with the soft keyboard, matching iOS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:12:36 -07:00
Fusion
142839a5ac feat(FN-3558): add action-gate reload endpoint for reloadable exempt-tools
Adds a reload endpoint for exempt agent tools (FN-3731), enabling runtime refresh of action-gate configuration without restart, with corresponding dashboard routes and tests. Also fixes mobile nav colors to properly respect design tokens (FN-3558).

Fusion-Task-Id: FN-3558
2026-05-08 07:28:58 -07:00
Fusion
3df6dab652 docs(FN-3408): document shell connection chrome contracts
- Add architecture notes describing shell connection chrome contracts
- Expand dashboard README with shell chrome expectations and integration details
- Add desktop README note aligning desktop shell behavior with documented contracts

Fusion-Task-Id: FN-3408
2026-05-08 00:40:15 -07:00
Fusion
d2b840bd92 feat(FN-3604): add chat unread indicator to header and mobile nav
Implements a chat unread indicator across the header and mobile nav bar, driven by a new unread-response tracker in the app state, with tests and a docs update for the feature.

Fusion-Task-Id: FN-3604
2026-05-06 18:47:25 -07:00
gsxdsm
55823070b9 fix(dashboard): extend mobile nav bar surface into iOS safe area
Icons in the installed PWA were overlapped by the iOS home indicator and a
body-colored gap appeared between the nav bar and the executor status bar
(whose `bottom` already includes safe-area-inset-bottom + standalone-bottom-gap).
Adding matching `padding-bottom` to `.mobile-nav-bar` lifts icons above the
indicator and closes the gap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 07:25:14 -07:00
Fusion
73cee930b0 feat(FN-3232): add standalone bottom-gap token and mobile CSS contract test
This merge bundles six feature steps across mobile PWA spacing, test infrastructure, MissionManager tokenization, and Insights coverage. Key changes include restoring the `--standalone-bottom-gap` CSS token contract for iOS home indicator spacing, a refactored `test-changed.mjs` script with workflow

Fusion-Task-Id: FN-3232
2026-05-03 05:57:25 -07:00
Fusion
b969b01b1c fix(FN-2672): harden automation execution and scheduling flows
- Improve automation startup diagnostics and route handling for manual execution steps
- Add support for full manual automation step execution in dashboard and engine flows
- Expand due-schedule coverage in automation store and dashboard route tests
- Add cron runner regression tests for edge cases and document the automation execution fix via changeset
2026-04-27 03:07:58 -07:00
Fusion
394960f251 feat(FN-2613): tokenize standalone mobile footer spacing
- Replace hardcoded mobile footer offset with --executor-footer-height in MobileNavBar content padding
- Move standalone display-mode behavior to a :root token override and remove global #root standalone padding
- Scope standalone bottom-gap application to mobile layout containers (project content and executor status bar)
- Update mobile nav and PWA CSS tests to assert tokenized spacing and scoped standalone rules
2026-04-26 22:00:36 -07:00
gsxdsm
c3d1716fdd refactor(dashboard): split monolithic styles.css into per-component files
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>
2026-04-24 19:39:20 -07:00