Skip to content

[Feature] Frontend: missing error boundary, inconsistent loading states, a11y gaps #38

@chronoai-shining

Description

@chronoai-shining

Severity: Medium

A grab-bag of resilience + accessibility improvements that an industry-standard React app of this size would already have.

1. No error boundary anywhere

A throw inside GraphView's nodeThreeObject callback or WorkflowVisualizer's YAML parser crashes the whole tree to a white screen. Components with try/catch (e.g. WorkflowEditorPage) silently swallow errors instead of logging or surfacing.

Fix: wrap the routed Outlet in a top-level <ErrorBoundary fallback={ErrorPage}>. Surface nested errors to oncall via Sentry / equivalent.

2. Loading-state hygiene inconsistent

  • RunDetailView, TriggerHistoryPage, UploadHistoryPage show a spinner with no max-wait timeout.
  • WorkflowListPage's loadData uses Promise.all([fetchWorkflows, fetchConnectors]) — a slow connector fetch hangs the entire workflows list, when only fetchWorkflows is on the critical path.
  • No skeleton UI; the spinner-vs-content flash is jarring.

Fix: add a 30s timeout to data-fetching effects (clear with AbortController.abort()), unblock independent fetches with Promise.allSettled, add skeleton placeholders for the high-traffic pages.

3. Accessibility gaps

  • Most icon-only <button> controls (close X, refresh, trash, expand chevrons across WorkflowEditorPage, GraphView, NodeDetailsPanel, CompilePopup) lack aria-label.
  • State indicated only by color (var(--neon-green) / var(--neon-red) for run status) — fails colorblind users + screen readers.
  • No :focus-visible styling.
  • Popups (syncSteps, popup, CompilePopup, viewingConnector) are not focus-trapped and have no role="dialog" / aria-modal.

Fix: add aria-label to icon buttons, pair color with text labels for run status, define :focus-visible outline globally, use a dialog primitive (Radix UI / Headless UI) for popups.

4. Smaller fixes (group them)

  • SlashCommandTextarea.tsx:79loadedRef2 guards a one-shot fetch keyed on initial token; if the user re-auths during the session, the popup never refreshes.
  • GraphView initial state uses window.innerWidth — wrong if the panel is narrower than the window. Causes a resize flash on mount.
  • ResearchStream.tsx:133-137, 237-239 — auto-collapse re-fires every time a finished round's isCurrent toggles; bottomRef.current?.scrollIntoView({ behavior: 'smooth' }) fires on every event causing animation stacking. Use a didAutoCollapse ref + throttle scroll.
  • GraphView.tsx:111, 176linkColor={(link: any) => ...} inline arrow functions every render prevent react-force-graph memoization. Wrap in useCallback.

Metadata

Metadata

Labels

dxDeveloper experienceenhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions