Enhance custom filter functionality and UI updates#643
Conversation
- Updated to conditionally apply active class based on filter tone. - Modified interface to include an optional property. - Improved logic to handle filter replacements and clearing. - Added computed properties for managing active filters and empty states across various pages (borrow, earn, explore, lend, portfolio). - Replaced static empty state messages with dynamic components for better user experience.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds shared empty-state components, updates custom-filter tone handling and reset behavior, and switches borrow, earn, explore, lend, and portfolio screens to shared empty-state rendering with filter-clearing actions where applicable. ChangesEmpty-state and filter flow
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/ui/UiCustomFilterChips.vue (1)
16-31: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winMake removable chips real buttons.
The filter chip is still a clickable
div, so it can't be focused or triggered with Enter/Space. That blocks keyboard users from clearing individual filters.Suggested fix
- <div + <button + type="button" v-for="filter in filters" :key="filter.id" class="ui-select__chip" :class="[ chipClass, { 'ui-select__chip--active': filter.tone !== 'neutral' }, ]" `@click`="emit('remove', filter.id)" > {{ filter.label }} <UiIcon name="close" class="ui-select__chip-icon" /> - </div> + </button>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/ui/UiCustomFilterChips.vue` around lines 16 - 31, The filter chips in UiCustomFilterChips are rendered as clickable divs, which makes them inaccessible to keyboard users. Update the chip element in the filter loop to use a real button in the same template, keep the existing chip styling/class bindings, and wire the remove action through the button’s click handler so it can be focused and activated with Enter/Space.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@composables/useCustomFilters.ts`:
- Around line 15-27: The addCustomFilter/removeCustomFilter flow in
useCustomFilters is dropping the seeded neutral default without restoring it
when the replacement is deleted. Update removeCustomFilter so that, when
removing a custom filter that had replaced a neutral seed for the same metric,
it restores the original neutral filter from initialFilters instead of leaving
customFilters empty; keep clearCustomFilters behavior unchanged and use the
existing addCustomFilter, removeCustomFilter, and initialFilters symbols to
locate the logic.
In `@pages/earn/index.vue`:
- Around line 228-245: The empty-state logic in pages/earn/index.vue should
distinguish between a truly empty base earn dataset and results hidden by active
filters. Update the computed state used by the empty view (including
hasActiveFilters, emptyStateTitle, emptyStateDescription, and the Clear filters
CTA) so the filtered “No earn vaults found” copy only appears when there is at
least one earn vault in the base list and an active filter/search is narrowing
it down. Keep the “No earn vaults yet” state when the underlying list is empty,
even if searchQuery or URL-backed filters are set, and apply the same gating to
the duplicate empty-state block around the later section referenced by the
review.
In `@pages/explore/index.vue`:
- Around line 293-314: Update the empty-state logic in the explore page so the
filtered message only appears when active filters are hiding existing explore
data; in the computed values for hasExploreMarkets, emptyStateTitle, and
emptyStateDescription, stop using hasExploreMarkets as a trigger for “No markets
found” and the clear-filters CTA, and base that state only on hasActiveFilters
when there is actually data to filter. Keep clearExploreFilters and the related
empty-state rendering consistent with this behavior so networks with no product
groups show the plain “No markets yet” state instead.
In `@pages/lend/index.vue`:
- Around line 281-302: The empty-state logic in the lend page should only show
the “Clear filters”/filtered variant when filters can actually reveal markets;
update the computed state used by the empty state (such as hasActiveFilters,
hasLendMarkets, emptyStateTitle, and emptyStateDescription in the lend page
setup) so that if borrowableVaults is empty, seeded search/URL filters do not
switch it to the filtered copy. Keep clearLendFilters and the related action
visible only when there are available lend markets and active filters that can
change the result set.
In `@pages/portfolio/saving.vue`:
- Around line 74-78: The empty-state logic in PortfolioEmptyState usage still
relies only on isConnected, so spy-mode users can see disconnected copy in
saving even though the active-session contract elsewhere uses isConnected ||
isSpyMode. Update the active binding in the affected PortfolioEmptyState blocks
in saving.vue to treat spy mode as active, matching the pattern already used in
pages/portfolio/index.vue and pages/portfolio/rewards.vue.
---
Outside diff comments:
In `@components/ui/UiCustomFilterChips.vue`:
- Around line 16-31: The filter chips in UiCustomFilterChips are rendered as
clickable divs, which makes them inaccessible to keyboard users. Update the chip
element in the filter loop to use a real button in the same template, keep the
existing chip styling/class bindings, and wire the remove action through the
button’s click handler so it can be focused and activated with Enter/Space.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9d09063e-7785-4db1-bfae-4ff10c4703f1
📒 Files selected for processing (13)
components/entities/portfolio/PortfolioEmptyState.vuecomponents/ui/UiCustomFilterChips.vuecomponents/ui/UiEmptyState.vuecomponents/ui/UiEmptyStateIcon.vuecomponents/ui/modals/customFilter.types.tscomposables/useCustomFilters.tspages/borrow/index.vuepages/earn/index.vuepages/explore/index.vuepages/lend/index.vuepages/portfolio/index.vuepages/portfolio/rewards.vuepages/portfolio/saving.vue
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #643
Verdict: COMMENT — no blocking issues found at head ab8913991a496ce040adc91da0b286cfa29e5c74.
Scope reviewed
- Custom filter state handling, including neutral/default filter tone and reset behaviour.
- New shared empty-state components and their use across Borrow, Earn, Explore, Lend, Portfolio, Rewards, and Saving pages.
- Desktop and mobile filtered-empty UI states.
- Public-repo hygiene / malicious-code sweep over the diff.
- Active bot feedback: CodeRabbit had only the generated walkthrough/summary visible; no material inline claim needed action.
Validation
npm run typecheck— passed.npm run test:run— passed: 94 files, 959 tests; 1 file/test skipped by suite configuration.npm run build— passed, with existing large-chunk / module-preload style warnings only.- Browser visual smoke — passed on local PR build:
- Desktop
/earn?network=1&search=zzzz-pr643-empty-state: filtered empty state displayed, screenshot content verified,Clear filtersreturned the route to unfiltered content. - Mobile
/borrow?network=1&search=zzzz-pr643-empty-state: filtered empty state displayed, screenshot content verified,Clear filtersreturned the route to unfiltered content.
- Desktop
Screenshot evidence
Raw raster URLs verified immediately before posting:
Scalability / maintainability hygiene pass
The PR moves the visual empty-state treatment into reusable UiEmptyState / UiEmptyStateIcon components and reuses PortfolioEmptyState for the repeated portfolio empty panels. That is the right direction: this does not look like a one-off patch to only the originally visible Earn surface.
Sibling-surface check:
- Borrow, Earn, Explore, and Lend all now expose filtered empty states with a clear action.
- Portfolio borrow, rewards, and saving reuse the same portfolio empty-state component rather than duplicating the old icon/text block.
- Borrow’s neutral default liquidity filter gets explicit handling so it is not counted as a clearable user filter; the other list pages do not currently pass neutral initial filters.
One non-blocking gap: there are still no focused tests around useCustomFilters initial/default filter semantics, especially “neutral default → user replacement → clear/reset”. The current diff behaved correctly in the smoke paths I exercised, but the composable is now doing more business logic than before. A small unit test would be a tidy guardrail if this filter model keeps growing.
Notes / caveats
- Wallet/AppKit signing was not exercised; this was disconnected browser visual smoke only.
- Console noise observed during local smoke was limited to disconnected wallet/AppKit configuration and unrelated rewards proxy noise; it did not block the reviewed empty-state flows.
|
🚅 Deployed to the euler-lite-pr-643 environment in euler-lite
|
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #643
Verdict: Request changes (1 blocking correctness issue)
Reviewed current head: cef1cfc
What changed:
- Custom filter state now keeps seeded/default filters in the same array as user filters, including replacing neutral defaults and resetting back to the initial set.
- Borrow/Lend/Explore/Earn empty states moved toward shared
UiEmptyStatecopy/actions. - Portfolio saving now uses the shared
PortfolioEmptyStateactive-session pattern, including spy mode.
Blocking finding:
- Earn still shows the filtered empty-state copy/CTA whenever a search/filter is present, even when the underlying earn vault list is empty. In that case “Clear filters” cannot reveal any earn vaults, so the page should stay on the true empty state. I left this inline on
pages/earn/index.vue.
Bot/reviewer comment pass:
- Verified CodeRabbit comments against current head. The neutral-default filter restoration, Explore gating, Lend gating, and Portfolio spy-mode comments are addressed in
cef1cfc. - The Earn empty-state gating comment remains valid and is the blocker above.
Scalability / maintainability hygiene:
- The PR mostly improves reuse by moving repeated empty-state markup to shared empty-state components.
- The remaining Earn issue is a sibling-surface consistency gap: Explore/Lend now gate “filtered empty” on both active filters and a non-empty base dataset; Earn should use the same invariant.
- Non-blocking guardrail:
useCustomFiltersnow has more lifecycle semantics (initial -> replace neutral -> remove -> restore neutral -> clear). The current suite/build pass, but a focused composable test for these transitions would make future filter changes less fragile.
Validation performed:
npm run typecheck— passed.npm run test:run— passed: 94 test files passed, 1 skipped; 959 tests passed, 1 skipped.npm run build— passed.- Browser visual smoke on the PR Railway preview — passed for the filtered-empty happy path:
/borrow?network=1&search=zzzz-no-market-pr643desktop: showedNo borrow markets found+Clear filters./earn?network=1&search=zzzz-no-earn-pr643mobile: showedNo earn vaults found+Clear filterswhen base earn data exists./explore?network=1&search=zzzz-no-market-pr643desktop: showedNo markets found+Clear filters./lend?network=1&search=zzzz-no-lend-pr643mobile: showedNo lend markets found+Clear filters.
- Smoke coverage: browser visual smoke + mobile smoke; disconnected wallet only. Wallet/AppKit/signing flows were not exercised.
Screenshot evidence:
Tighten filtered empty-state handling for earn and simplify shared empty-state visuals.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #643
Verdict: COMMENT — no blocking issues found at head efb678e10eb4bd7ed33dced298651768314548c3.
Scope reviewed
- Custom filter lifecycle in
useCustomFilters, including neutral/default filter replacement, removal, and reset behaviour. - Shared
UiEmptyState/UiEmptyStateIconrendering and reduced-motion styling. - Borrow, Earn, Explore, Lend filtered-empty copy/action gates.
- Portfolio / rewards / saving empty states, especially spy-mode vs disconnected copy.
- Public-repo hygiene / malicious-code sweep over the diff.
- Active bot/reviewer feedback: verified the outstanding CodeRabbit comments against the current head.
Validation
git diff --check origin/development...HEAD✅npm run typecheck✅npm run test:run✅ — 959 passed, 1 skippednpm run build✅- Browser visual smoke on a local PR-head production build, headed Chromium under Xvfb:
- Desktop
/borrow?network=1&search=pr643-no-match: filtered empty state showedNo borrow markets found+Clear filters; clearing returned to populated borrow content. ✅ - Desktop
/earn?network=1&search=pr643-no-match: filtered empty state showedNo earn vaults found+Clear filters; clearing returned to earn content. ✅ - Mobile
/earn?network=1&search=pr643-no-match: same filtered-empty/clear flow passed. ✅ - Mobile
/portfolio/saving?network=1&spy=<test-address>: active-session saving empty-state surface rendered without falling back to disconnected copy. ✅
- Desktop
Console caveat: local smoke emitted expected AppKit/Reown warnings from the intentionally blank wallet project configuration; no page crash or PR-specific runtime error was observed.
Screenshot evidence
- Desktop borrow filtered empty state:

- Desktop earn filtered empty state:

- Mobile earn filtered empty state:

- Mobile portfolio saving spy empty state:

Scalability / maintainability hygiene pass
The patch is now reasonably reusable for the current scope:
UiEmptyStatecentralizes the new visual empty-state shell across Borrow/Earn/Explore/Lend.PortfolioEmptyStatecentralizes the repeated portfolio connected/spy/disconnected copy pattern across portfolio, rewards, and saving surfaces.- The earlier one-off risk around Earn’s filtered-empty gate is fixed: Earn now requires both active filters and a non-empty base earn list before showing the “filters hid results” copy/action.
- Sibling filter surfaces were checked: Borrow, Earn, Explore, and Lend each gate the
Clear filtersaction on a clearable/active-filter condition plus the relevant base data where needed. I did not find a remaining sibling surface carrying the old misleading empty-state behaviour.
Non-blocking note: the page-level hasActiveFilters / showFilteredEmptyState pattern is still repeated in Earn/Explore/Lend and specialized in Borrow. That is acceptable at this size because the base-data predicate differs by page, but if another round adds more list pages, this is a good candidate for a small shared helper with focused tests.
Bot feedback verification
The active CodeRabbit comments appear stale/fixed on this head:
- Neutral seed restoration after removing an overriding custom filter is handled in
removeCustomFilter. - Earn, Explore, and Lend now distinguish “base list is empty” from “filters hid existing results” before showing filtered copy/clear action.
- Portfolio saving now treats spy mode as an active session, aligned with portfolio index and rewards.
No blockers from me. Wallet/signing smoke was not run; this PR changes read-only/filter and empty-state UI, not transaction construction or signing paths.


Summary by CodeRabbit
activevsneutralbehavior, correcting add/remove/clear logic, and fixing filter chip highlighting to reflect true active selections.