Problem / Motivation
As part of Phase 3 (Expenses Analytics & Filters), multiple filter mechanisms (search, categories, members, date ranges) are being added to the Expenses List screen. Implementing all of these directly on the main screen would severely clutter the UI, violating the "Whitespace" and "Premium" pillars of the Horizon Narrative design language. A unified orchestration mechanism is required to hold complex filters in a bottom sheet and manage the unified active filter state.
Note: To keep the expenses list screen as clean as possible, only the search bar should remain on the main screen. The category chips (#1501) should also be moved into this bottom sheet filter. In the future, the search bar could become omni-functional and suggest categories dynamically as the user types.
Proposed Solution
- Create a new domain data class,
ExpenseFilterCriteria, to hold the active filter state (search query, selected categories, selected members, date range).
- In
ExpensesViewModel, expose a MutableStateFlow<ExpenseFilterCriteria> and use combine with the expensesFlow to apply the filters in-memory on Dispatchers.Default.
- Create a new UI component (e.g.,
ExpenseFilterBottomSheet) using the ActionBottomSheet from :core:design-system to house the complex filters (Categories, Members, Dates) to keep the main screen clean.
- Ensure the active filter state is bundled into the MVI
UiState so the UI can accurately reflect active filter badges and provide a "Clear Filters" action.
Acceptance Criteria
Out of Scope
Related Issues / PRs
Problem / Motivation
As part of Phase 3 (Expenses Analytics & Filters), multiple filter mechanisms (search, categories, members, date ranges) are being added to the Expenses List screen. Implementing all of these directly on the main screen would severely clutter the UI, violating the "Whitespace" and "Premium" pillars of the Horizon Narrative design language. A unified orchestration mechanism is required to hold complex filters in a bottom sheet and manage the unified active filter state.
Note: To keep the expenses list screen as clean as possible, only the search bar should remain on the main screen. The category chips (#1501) should also be moved into this bottom sheet filter. In the future, the search bar could become omni-functional and suggest categories dynamically as the user types.
Proposed Solution
ExpenseFilterCriteria, to hold the active filter state (search query, selected categories, selected members, date range).ExpensesViewModel, expose aMutableStateFlow<ExpenseFilterCriteria>and usecombinewith theexpensesFlowto apply the filters in-memory onDispatchers.Default.ExpenseFilterBottomSheet) using theActionBottomSheetfrom:core:design-systemto house the complex filters (Categories, Members, Dates) to keep the main screen clean.UiStateso the UI can accurately reflect active filter badges and provide a "Clear Filters" action.Acceptance Criteria
ExpenseFilterCriteriamodel is created.ExpensesViewModelsuccessfully filters expenses in-memory based on the active criteria usingDispatchers.Default.ExpenseFilterBottomSheetis created (usingActionBottomSheet) and can be opened/closed from the Expenses List screen.ExpensesViewModelfiltering logic.make fast-checkpasses during iterative development (~15–30s).make check > build.log 2>&1 && echo "Check passed successfully" || (tail -n 100 build.log && exit 1)passes with 0 failures before merging.Out of Scope
Related Issues / PRs