Files
homarr/.cursor/plans/widget_refresh_indicator_ffb2b58d.plan.md
T
Thomas Camlong cb5ae65f8a refactor(ui): simplify indicator to status dot on board logo
Use Mantine Indicator with processing animation instead of custom CSS.
Switch from HoverCard to Menu with grouped sections. Remove beep,
position dot next to board logo, hide in edit mode.
2026-05-28 18:07:03 +02:00

4.5 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
Widget Refresh Indicator Add a board-header refresh indicator for widget/server-state queries using TanStack Query as the shared state source, then continue the PR #5768 pattern by removing widget-level blocking spinners where needed.
id content status
switch-branch After approval, switch the workspace to `agent/cebd0dad` and confirm the PR diff is present. completed
id content status
cache-hook Create a TanStack Query cache-inspection hook that returns refresh counts and normalized query status rows. completed
id content status
header-ui Add the hoverable orange/green header indicator immediately before the board edit button. completed
id content status
calendar-cleanup Reconcile the calendar widget PR change with the new global indicator, removing redundant widget-local loading UI if appropriate. completed
id content status
verify Run targeted typechecks and manually validate refresh, completion, hover details, and beep behavior. completed
false

Widget Refresh Indicator Plan

Findings

Implementation Approach

  • Add a small client hook/component, likely apps/nextjs/src/components/layout/header/query-refresh-indicator.tsx, that reads from useQueryClient() and subscribes to the query cache.
  • Derive a normalized list from cached queries: query path/key, fetching status, status, dataUpdatedAt, stale state via the query object, error state, and integration IDs found in query inputs/data where present.
  • Count active refreshes with fetchStatus === "fetching", using a useIsFetching() value as a cheap re-render trigger and cache subscription for details.
  • Render a Mantine HeaderButton/ActionIcon with a tiny Indicator: orange while one or more relevant queries are fetching, green briefly after a refresh batch completes, then idle/disabled when nothing is active.
  • Use a Mantine HoverCard for the details: overall status, number of refreshing queries, last updated/stale state, and a compact list of current integration/widget query entries.
  • Add a small Web Audio beep when the indicator transitions from fetching to complete. It should be best-effort and fail silently if the browser blocks audio before user interaction.
  • Add translation keys only to packages/translation/src/lang/en.json; other locales fall back to English through the existing merge in packages/translation/src/request.ts.

Widget Migration Scope

  • Keep PR #5768’s calendar behavior, but remove the widget-local loader if the header indicator fully replaces it.
  • Do not attempt to convert all useSuspenseQuery widgets in the same pass unless the branch goal expands. The first version can show global activity for all query cache entries, while follow-up widget migrations replace blocking useSuspenseQuery with useQuery where each widget can render meaningful stale/empty content.

Verification

  • Run a targeted typecheck such as pnpm -F nextjs typecheck and pnpm -F widgets typecheck after implementation.
  • Skip lint cleanup unless explicitly requested, matching your preference to ignore linter errors.