Skip to content

Tracker Features

The Tracker page is more than a list — it carries visual signals (sparklines, drift badges, autopay trust), URL-backed state (sorting, filtering, search panel), and accessibility features (keyboard navigation, reduced-motion respect) that make the monthly planning loop faster.

This page documents those features in detail and links them to the underlying services. For the basic layout (rows, columns, buckets), see Plan a Month in the Tracker.

What does the sparkline on a Tracker row mean?

Each Tracker row renders a 44 × 16 px inline SVG polyline of the last six months of actual payment totals for that bill, oldest-to-newest, normalized to the row's own min/max range.

Property Value
Size 44 × 16 px
Render Inline SVG <polyline> — no chart library
Data source trackerService.fetchSparklines
Query Single batched GROUP BY bill_id, month_str for all bill IDs at once
Visibility Renders only when two or more months of data exist

The sparkline is computed on the server for every active bill in the current tracker request — it is not a per-bill lazy fetch. As a result, the Tracker load time grows by one additional query, not by N.

What the sparkline tells you

A flat polyline near the top of the cell means a bill like Verizon has held steady at its expected amount for six months. A polyline that dips in the last segment tells you the most recent payment was lower than the prior five — a candidate for a one-time amount override.

What does the "Changed" badge mean?

When the drift service flags a bill — the current month's amount differs from the prior month's by more than the configured threshold — the Tracker amount column shows a small amber Changed badge with a TrendingUp icon.

Property Value
Data source Existing useDriftReport() data already fetched by TrackerPage
Network cost None — isDrifted is derived per row from the bill ID set
Hover behaviour Tooltip repeats the same expected → actual delta shown in the price-change insights panel

The badge is intentionally a thin visual signal: it does not block the row, and clicking it jumps to the same update flow as the insights panel. The drift threshold is per-bill and editable in Add and Manage Bills.

How do I sort the Tracker?

Click any column header on the desktop table to toggle sort direction. The filter bar exposes a compact sort selector for mobile and tablet. The URL is bookmarkable: /tracker?year=2026&month=5&sort=due_day&dir=asc captures the active view.

You can sort by:

Sort key What it shows
name Bill name (alphabetical)
due_day Due day within the current month, then by name
expected Effective amount (expected with override applied)
last_month_paid Total paid last month
paid Total paid in the current cycle
remaining Amount remaining in the current cycle
paid_date Most recent paid date in the cycle
status Lifecycle order (see below)

Manual bill reordering is automatically disabled while a sorted view is active. The two modes are mutually exclusive — Pin Due, sort, and manual reorder are three different ways to organize the same rows, and the UI clearly tells you which is active.

Status sort is lifecycle-aware, not alphabetical

See the next question.

What order does the Status sort use?

status sort uses the lifecycle order rather than plain alphabetical labels:

missed → late → due_soon → upcoming → autodraft → paid → skipped

The values match the Status field on each row, so a user who "sorts by status" gets a visual walk through the urgency gradient — overdue first, already-paid last — not a textbook A-Z list.

Why do some screens animate?

framer-motion powers the Tracker:

Surface Animation
Page transitions Shared PageTransition wrapper drives user/admin route content (opacity + small Y offset)
Dialogs and AlertDialogs Framer entry motion (fade + scale-in)
Tracker bucket rows LayoutGroup so sorted and reordered bill groups move smoothly between positions
Mobile rows motion.div per row; quick-pay tap is debounced while a save is in progress
Bucket headers Wrap cleanly on narrow screens without layout shift

The animation respects useReducedMotion() — users with reduced-motion preferences see content appear without motion. The animations are tuned to be additive, not blocking: the row is interactive during the animation, and a double-tap on Pay Now is intentionally debounced.

How do I collapse the search and filter panel?

Click the chevron in the search bar header. The expanded/collapsed state is stored in the per-user search_bars_collapsed setting via the shared useSearchPanelPreference hook, the same hook used by the Bills and Subscriptions pages.

Property Value
Default Expanded
Persistence Per-user setting, shared across Tracker, Bills, and Subscriptions
Hook useSearchPanelPreference in client/hooks/useSearchPanelPreference.js
Component SearchFilterPanel (shared)

When the panel is collapsed, only the search input and a "Filters" toggle button are visible; advanced filters open inline when toggled.

How do I navigate the Tracker with a keyboard?

Tracker rows are keyboard-navigable. Each row carries tabIndex={0}, data-tracker-row, aria-rowindex, and an aria-label that announces the bill name, status, and due day.

Key Action
/ j Focus the next row (crosses bucket boundaries)
/ k Focus the previous row
Enter Open the edit modal for the focused bill
P Toggle paid / unpaid (skipped bills ignored)
Esc Blur the row

Cmd+P / Ctrl+P is intentionally passed through to the browser so users can still print. The handler guards against firing on nested interactive elements (if (e.target !== e.currentTarget) return).

How do I work through overdue bills faster?

A collapsible command center appears at the top of the Tracker when there is at least one overdue bill. Each overdue bill exposes:

  • Pay Now — opens the payment dialog with the bill prefilled
  • Skip — marks the bill skipped for the current month
  • Snooze — 1 / 3 / 7 day options, persisted server-side

Snoozed bills are hidden from the overdue list with a count hint in the header so the user can see how many bills are temporarily suppressed without expanding the panel.

See also

Next steps