feat: add Reduced motion setting and polish chrome, files, and stack-detail (#1501)

A batch of UI/UX polish:

- New independent "Reduced motion" appearance setting (separate from Reduced
  effects). Drives framer-motion via MotionConfig and clamps CSS transitions via
  data-motion on <html>; toasts are unaffected. Defaults off (OS preference
  still honored).
- Stack-detail Files tab: rename "Files & Volumes" to "Files", add a persisted
  word-wrap toggle to the file viewer (default on), and add a fullscreen toggle
  that collapses the Command Center + Logs column so the editor fills the width.
- Create Stack > From Git: remove the nested scroll clamp so the deploy toggle
  and footer are reachable.
- Fleet: full-width tab band with icon-only Refresh / Export Dossier, icon-only
  Check-for-updates / Add-node on the Overview toolbar, theme-aware empty-state
  headings (calm drops the italic), and fix the Actions card body overlapping
  the action-row divider.
- Snapshots: restyle Restore and Restore all to the ghost button design used by
  View / Preview / Download, and right-align the per-stack Restore.
- Settings sidebar: App Store gradient active style and standard font size.
- Compose Doctor: dismiss the high-risk banner (and clear the tab dot) until the
  findings change, via a shared fingerprint-keyed hook.
- Stack-detail Storage: link the "no recent fleet snapshot" warning to the Fleet
  Snapshots tab (FleetView tabs are now controlled to support the deep link).
This commit is contained in:
Anso
2026-06-28 06:18:02 -04:00
committed by GitHub
parent 083442d5ea
commit b5810a9b55
27 changed files with 489 additions and 119 deletions
@@ -8,6 +8,7 @@ import { toast } from '@/components/ui/toast-store';
import { formatTimeAgo } from '@/lib/relativeTime';
import { useNodes } from '@/context/NodeContext';
import { useAuth } from '@/context/AuthContext';
import { SENCHO_NAVIGATE_EVENT, type SenchoNavigateDetail } from '@/components/NodeManager';
// Mirrors the backend /storage payload (the frontend never imports backend).
type PortabilityStatus = 'portable' | 'partially-portable' | 'node-bound' | 'unknown';
@@ -221,6 +222,17 @@ export default function StoragePanel({ stackName }: { stackName: string }) {
This stack has persistent storage but no fleet snapshot in the last 7 days.
</span>
</div>
{activeNode?.type !== 'remote' && (
<button
type="button"
onClick={() => window.dispatchEvent(new CustomEvent<SenchoNavigateDetail>(SENCHO_NAVIGATE_EVENT, {
detail: { view: 'fleet', fleetTab: 'snapshots' },
}))}
className="mt-1.5 text-[12px] font-medium text-brand hover:underline"
>
Take a fleet snapshot
</button>
)}
</div>
)}
{isAdmin && inventory.stateful && snapshot.recent && snapshot.at && (