Skip to content

Enhance custom filter functionality and UI updates#643

Open
kanvgupta wants to merge 3 commits into
developmentfrom
feature/lite-106-missing-no-earn-vaults-empty-state
Open

Enhance custom filter functionality and UI updates#643
kanvgupta wants to merge 3 commits into
developmentfrom
feature/lite-106-missing-no-earn-vaults-empty-state

Conversation

@kanvgupta

@kanvgupta kanvgupta commented Jun 26, 2026

Copy link
Copy Markdown
Contributor
  • 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.

Summary by CodeRabbit

  • New Features
    • Added reusable empty-state components with icon support and reduced-motion styling, now powering empty screens across borrowing, lending, exploring, earning, and portfolio.
    • Empty states use context-aware titles/descriptions and optionally show a Clear filters action when filters/search are active.
  • Bug Fixes
    • Improved custom filter handling by introducing active vs neutral behavior, correcting add/remove/clear logic, and fixing filter chip highlighting to reflect true active selections.
  • UI Improvements
    • Portfolio empty states now better reflect connected vs spy sessions.

- 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.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-643 June 26, 2026 14:20 Destroyed
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3d5d67bc-882d-4a6d-b6ff-c13d56026f7c

📥 Commits

Reviewing files that changed from the base of the PR and between cef1cfc and efb678e.

📒 Files selected for processing (4)
  • components/ui/UiEmptyState.vue
  • components/ui/UiEmptyStateIcon.vue
  • pages/earn/index.vue
  • pages/portfolio/saving.vue
🚧 Files skipped from review as they are similar to previous changes (3)
  • pages/portfolio/saving.vue
  • pages/earn/index.vue
  • components/ui/UiEmptyState.vue

📝 Walkthrough

Walkthrough

Adds 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.

Changes

Empty-state and filter flow

Layer / File(s) Summary
Empty-state primitives
components/ui/UiEmptyState.vue, components/ui/UiEmptyStateIcon.vue
UiEmptyState and UiEmptyStateIcon add the reusable empty-state layout, decorative icon, optional action slot, and reduced-motion handling.
Custom filter tone handling
components/ui/modals/customFilter.types.ts, components/ui/UiCustomFilterChips.vue, composables/useCustomFilters.ts, pages/borrow/index.vue
CustomFilter gains tone, neutral chips no longer render as active, custom-filter state now seeds from initialFilters and matches against the current list, and the borrow page marks its default liquidity filter neutral.
Borrow empty state
pages/borrow/index.vue
The borrow page derives active-filter and empty-state text state, adds a clear handler, and replaces the static empty message with UiEmptyState and a conditional clear action.
Earn, explore, and lend empty states
pages/earn/index.vue, pages/explore/index.vue, pages/lend/index.vue
These pages derive active-filter and market-availability state, add page-specific clear handlers, and replace static no-results blocks with UiEmptyState plus conditional clear actions.
Portfolio empty states
components/entities/portfolio/PortfolioEmptyState.vue, pages/portfolio/index.vue, pages/portfolio/rewards.vue, pages/portfolio/saving.vue
PortfolioEmptyState is added and the portfolio positions, rewards, and saving pages switch from inline messages to the shared component with session-based active and inactive copy.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Seranged
  • kasperpawlowski

Poem

I hopped through empty states, both tidy and bright,
With neutral chips mellowing into the night.
A clear-filters button went thump in the breeze,
And wallets and vaults now speak with more ease.
🐰 Hop, hop — the UI sings just right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main theme of custom filter behavior and UI/empty-state updates, though it is broader than the specific implementation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/lite-106-missing-no-earn-vaults-empty-state

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Make 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

📥 Commits

Reviewing files that changed from the base of the PR and between 95e79c2 and ab89139.

📒 Files selected for processing (13)
  • components/entities/portfolio/PortfolioEmptyState.vue
  • components/ui/UiCustomFilterChips.vue
  • components/ui/UiEmptyState.vue
  • components/ui/UiEmptyStateIcon.vue
  • components/ui/modals/customFilter.types.ts
  • composables/useCustomFilters.ts
  • pages/borrow/index.vue
  • pages/earn/index.vue
  • pages/explore/index.vue
  • pages/lend/index.vue
  • pages/portfolio/index.vue
  • pages/portfolio/rewards.vue
  • pages/portfolio/saving.vue

Comment thread composables/useCustomFilters.ts
Comment thread pages/earn/index.vue
Comment thread pages/explore/index.vue
Comment thread pages/lend/index.vue
Comment thread pages/portfolio/saving.vue
@kanvgupta kanvgupta marked this pull request as draft June 26, 2026 14:31

@LeonardEulerXYZ LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 filters returned the route to unfiltered content.
    • Mobile /borrow?network=1&search=zzzz-pr643-empty-state: filtered empty state displayed, screenshot content verified, Clear filters returned the route to unfiltered content.

Screenshot evidence

Raw raster URLs verified immediately before posting:

Desktop Earn filtered empty state

Mobile Borrow filtered empty state

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.

@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-643 June 26, 2026 14:42 Destroyed
@kanvgupta kanvgupta marked this pull request as ready for review June 26, 2026 14:42
@railway-app

railway-app Bot commented Jun 26, 2026

Copy link
Copy Markdown

🚅 Deployed to the euler-lite-pr-643 environment in euler-lite

Service Status Web Updated (UTC)
dev-build ✅ Success (View Logs) Web Jun 27, 2026 at 12:35 pm

@LeonardEulerXYZ LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 UiEmptyState copy/actions.
  • Portfolio saving now uses the shared PortfolioEmptyState active-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: useCustomFilters now 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-pr643 desktop: showed No borrow markets found + Clear filters.
    • /earn?network=1&search=zzzz-no-earn-pr643 mobile: showed No earn vaults found + Clear filters when base earn data exists.
    • /explore?network=1&search=zzzz-no-market-pr643 desktop: showed No markets found + Clear filters.
    • /lend?network=1&search=zzzz-no-lend-pr643 mobile: showed No 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 LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 / UiEmptyStateIcon rendering 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 skipped
  • npm 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 showed No borrow markets found + Clear filters; clearing returned to populated borrow content. ✅
    • Desktop /earn?network=1&search=pr643-no-match: filtered empty state showed No 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. ✅

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 borrow filtered empty state
  • Desktop earn filtered empty state: Desktop earn filtered empty state
  • Mobile earn filtered empty state: Mobile earn filtered empty state
  • Mobile portfolio saving spy empty state: Mobile portfolio saving spy empty state

Scalability / maintainability hygiene pass

The patch is now reasonably reusable for the current scope:

  • UiEmptyState centralizes the new visual empty-state shell across Borrow/Earn/Explore/Lend.
  • PortfolioEmptyState centralizes 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 filters action 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants