From 47d799fe5fca488af0233b199635c96af4ac5b2f Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Mon, 17 Aug 2026 20:38:28 +0530 Subject: [PATCH] expense list: clickable month pill + fix scroll-to-month - make the floating month pill interactive (button role, hover, focus ring) and jump to the active month's header on click/Enter - scroll via a non-sticky month anchor + window.scrollTo instead of scrollIntoView, which no-ops on sticky headers that are always already in view --- src/Expense/ExpenseList.tsx | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Expense/ExpenseList.tsx b/src/Expense/ExpenseList.tsx index 93b00c2..801ca1f 100644 --- a/src/Expense/ExpenseList.tsx +++ b/src/Expense/ExpenseList.tsx @@ -8,6 +8,7 @@ import { } from "@mui/material"; import { alpha } from "@mui/material/styles"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import { ListCellRenderer, CurrencyField, applyDisplayFormat, formatCurrency } from "../../react-openapi"; import type { ExpenseItem, ExpenseFieldConfigs } from "./types"; import { isExpense, monthKey, monthLabel, parseOccurredAt } from "./types"; @@ -139,6 +140,27 @@ export function ExpenseList({ items, fields }: ExpenseListProps) { setExpandedId((prev) => (prev === id ? null : id)); }, []); + const jumpToActiveMonth = useCallback(() => { + if (!activeMonth) return; + const anchor = listRef.current?.querySelector( + `[data-month-anchor="${activeMonth}"]`, + ); + if (!anchor) return; + const offset = window.matchMedia("(min-width: 900px)").matches ? 64 : 56; + const top = anchor.getBoundingClientRect().top + window.scrollY - offset; + window.scrollTo({ top, behavior: "smooth" }); + }, [activeMonth]); + + const handlePillKeyDown = useCallback( + (event: React.KeyboardEvent) => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + jumpToActiveMonth(); + } + }, + [jumpToActiveMonth], + ); + useEffect(() => { const root = listRef.current; if (!root || groups.length === 0) return; @@ -179,6 +201,7 @@ export function ExpenseList({ items, fields }: ExpenseListProps) { {groups.map((group) => ( +