Skip to content

feat[mobile]: soup filters as drawer#2229

Merged
peterchinman merged 13 commits intomainfrom
peter/mobile-new-soup-filter-bar
Mar 27, 2026
Merged

feat[mobile]: soup filters as drawer#2229
peterchinman merged 13 commits intomainfrom
peter/mobile-new-soup-filter-bar

Conversation

@peterchinman
Copy link
Copy Markdown
Contributor

@peterchinman peterchinman commented Mar 26, 2026

On mobile, instead of using the filter drop down, the filter button opens a drawer.

@peterchinman peterchinman requested a review from a team as a code owner March 26, 2026 22:13
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b9843aae-715d-4a84-aca9-755bd8c1a360

📥 Commits

Reviewing files that changed from the base of the PR and between d1fddb0 and 4fd101a.

📒 Files selected for processing (1)
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Mobile filter drawer with slide-up UI, accordion categories, assignee search, and active-filter badges.
    • Responsive filter interface that switches between mobile drawer and desktop controls.
    • Drawer footer with active filter chips and clear/remove controls.
  • Style

    • Improved icon and tab label styling for better mobile presentation.
  • Enhancements

    • More customizable filter chip display (classing and optional category label).

Walkthrough

Adds a mobile bottom-sheet filter UI and related type/prop adjustments: new MobileFilterDrawer component, conditional mobile rendering in the filters bar, ActiveFilterChips prop extensions, a stronger-typed FilterOption.id, a dependency addition, and minor UI style tweaks.

Changes

Cohort / File(s) Summary
Dependency Addition
js/app/package.json
Added @corvu/drawer at ^0.2.4.
Mobile Filter Drawer
js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx
Added exported MobileFilterDrawer component: bottom slide-up drawer, accordion per filter category, assignee search section for tasks, active-filter chips in footer, and toggle handlers calling soup.filters.toggle.
Filters Bar Integration
js/app/packages/app/component/next-soup/soup-view/filters-bar/soup-filters-bar.tsx
Conditional rendering: use MobileFilterDrawer when isMobile() is true; otherwise render desktop dropdown and ActiveFilterChips. Added Show import and wired new component.
Active Filter Chips
js/app/packages/app/component/next-soup/soup-view/filters-bar/active-filter-chips.tsx
Extended ActiveFilterChipsProps and FilterChip props with optional chipClass?: string and hideCategoryLabel?: boolean; propagate these props and conditionally apply chipClass and hide category label in chip rendering.
Unified Filter Dropdown & Types
js/app/packages/app/component/next-soup/soup-view/filters-bar/unified-filter-dropdown.tsx
Changed exported FilterOption.id type from string to FilterID; introduced internal SearchableOption type and updated searchable submenus/assignee options to use it. Updated toggleFilter to pass option id directly to soup.filters.toggle.
Create Button Styling
js/app/packages/app/component/next-soup/soup-view/soup-view-create-button.tsx
Added class="mobile:size-6" to EntityIcon for responsive icon sizing on non-import options.
Tabs Styling
js/app/packages/app/component/next-soup/soup-view/soup-view-tabs.tsx
Adjusted KSegmentedControl.ItemLabel layout: removed block, added mobile:min-h-11 and flex items-center justify-center for centered flex layout on mobile.

Possibly related PRs

  • macro#2117: Modifies the same soup-filters-bar.tsx file for border styling adjustments in the filters-bar component.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: implementing a mobile-specific drawer UI for soup filters instead of the desktop dropdown.
Description check ✅ Passed The description directly relates to the changeset, accurately summarizing the core mobile-focused filter behavior change implemented across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@peterchinman peterchinman changed the title peter/mobile new soup filter bar feat[mobile]: soup filters as drawer Mar 26, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx`:
- Around line 62-64: The toggleFilter call casts optionId to FilterID to silence
a mismatch—remove that cast and fix the source types so FilterOption.id is
strongly typed as FilterID (or introduce a typed category/value object) so only
valid FilterIDs flow into soup.filters.toggle; update the FilterOption type
definition (and any factories/creators that construct option ids) to return
FilterID instead of string, then remove the `as FilterID` in toggleFilter and
other similar sites so the type system enforces correctness when calling
soup.filters.toggle.

In `@js/app/packages/app/component/next-soup/soup-view/soup-view.tsx`:
- Around line 651-669: The current init block skips applying
props.initialClientFilters when persistenceDisabled is true, so ensure
initialClientFilters are applied regardless of persistence state: after checking
persistenceDisabled and reading persistedState, if no persisted initial is
applied (or persistenceDisabled is true) and props.initialClientFilters exists
then call soup.filters.set(props.initialClientFilters) (and any equivalent
client-side initializations that the persisted path would set) — update the
logic around persistenceDisabled, persistedState, props.initialClientFilters and
the soup.filters.set / setQueryFilters / other setters so
props.initialClientFilters is applied even when persistenceDisabled is true.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6ed49f0b-b594-48bc-ad67-dee4aa7ea1c1

📥 Commits

Reviewing files that changed from the base of the PR and between f67aa1d and 7a8ac9e.

⛔ Files ignored due to path filters (1)
  • js/app/bun.lock is excluded by !**/*.lock, !**/bun.lock
📒 Files selected for processing (7)
  • js/app/package.json
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/active-filter-chips.tsx
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/soup-filters-bar.tsx
  • js/app/packages/app/component/next-soup/soup-view/soup-view-create-button.tsx
  • js/app/packages/app/component/next-soup/soup-view/soup-view-tabs.tsx
  • js/app/packages/app/component/next-soup/soup-view/soup-view.tsx

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
js/app/packages/app/component/next-soup/soup-view/filters-bar/unified-filter-dropdown.tsx (1)

505-510: ⚠️ Potential issue | 🟠 Major

Keep all filter helper signatures typed to FilterOption['id'], not string.

FilterOption.id is strongly typed to FilterID, but multiple helpers widen it back to string. This gives up the compiler protection. Note that mobile-filter-drawer.tsx already uses the correct signature for toggleFilter, establishing the pattern.

The issue exists in two files:

  1. unified-filter-dropdown.tsx (lines 505, 509)
  2. use-filter-refinements.ts (lines 174, 178) — also has unnecessary as FilterID casts (lines 179, 185–186) that can be removed once parameters are properly typed
♻️ Proposed fixes

unified-filter-dropdown.tsx:

-  const isOptionActive = (optionId: string) => {
+  const isOptionActive = (optionId: FilterOption['id']) => {
     return soup.filters.isActive(optionId);
   };
 
-  const toggleFilter = (optionId: string) => {
+  const toggleFilter = (optionId: FilterOption['id']) => {
     soup.filters.toggle({ or: [optionId] });
   };

use-filter-refinements.ts:

-  const isOptionActive = (optionId: string) => {
+  const isOptionActive = (optionId: FilterOption['id']) => {
     return soup.filters.isActive(optionId);
   };
 
-  const removeFilter = (optionId: string) => {
-    soup.filters.toggle({ or: [optionId as FilterID] });
+  const removeFilter = (optionId: FilterOption['id']) => {
+    soup.filters.toggle({ or: [optionId] });
   };
 
   const swapFilter = (oldOptionId: string, newOptionId: string) => {

(Also remove as FilterID casts on lines 185–186 when swapFilter parameters are updated similarly.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@js/app/packages/app/component/next-soup/soup-view/filters-bar/unified-filter-dropdown.tsx`
around lines 505 - 510, Update the helper function signatures to use
FilterOption['id'] (the FilterID) instead of string: change
isOptionActive(optionId: string) => isOptionActive(optionId: FilterOption['id'])
and toggleFilter(optionId: string) => toggleFilter(optionId: FilterOption['id'])
in unified-filter-dropdown.tsx, and similarly update swapFilter/toggle helpers
in use-filter-refinements.ts to accept FilterOption['id']; after that remove the
unnecessary `as FilterID` casts (lines noted) because the parameter types now
match the expected FilterID. Ensure you update all related call sites to keep
types consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx`:
- Around line 181-189: The Accordion.Trigger elements remove the native focus
ring via the "outline-none" class, leaving keyboard focus invisible; update the
Accordion.Trigger (the element with class "w-full flex items-center ...
outline-none") to either remove "outline-none" or replace it with accessible
focus styles (e.g., add focus-visible:ring, focus-visible:ring-offset, and
focus-visible:ring-accent or a clear focus-visible:outline class) so the header
shows a visible focus indicator when tabbing; apply the same change to the other
Accordion.Trigger instance used in this file so both triggers regain an
accessible keyboard focus style.
- Around line 127-149: Drawer.Content is rendered without an accessible name
because the visible "Filters" header is commented out; add an accessible name by
giving Drawer.Content either an aria-label="Filters" or aria-labelledby that
references the header element (or restore the commented header and set
aria-labelledby to its id). Update the Drawer.Content props (the element named
Drawer.Content) to include the chosen attribute so screen readers announce the
drawer.

---

Outside diff comments:
In
`@js/app/packages/app/component/next-soup/soup-view/filters-bar/unified-filter-dropdown.tsx`:
- Around line 505-510: Update the helper function signatures to use
FilterOption['id'] (the FilterID) instead of string: change
isOptionActive(optionId: string) => isOptionActive(optionId: FilterOption['id'])
and toggleFilter(optionId: string) => toggleFilter(optionId: FilterOption['id'])
in unified-filter-dropdown.tsx, and similarly update swapFilter/toggle helpers
in use-filter-refinements.ts to accept FilterOption['id']; after that remove the
unnecessary `as FilterID` casts (lines noted) because the parameter types now
match the expected FilterID. Ensure you update all related call sites to keep
types consistent.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b55550a9-d8a7-4dd4-8664-1d15a2c639d2

📥 Commits

Reviewing files that changed from the base of the PR and between 7a8ac9e and e6fbbb0.

📒 Files selected for processing (2)
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/unified-filter-dropdown.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx`:
- Around line 227-229: The category option label span currently uses className
cn('flex-1 truncate') and lacks the active/inactive text color logic used for
assignees; update the span rendering {option.label} in the category options (the
span with class cn('flex-1 truncate')) to include the same conditional class
logic as the assignee option (apply 'text-ink' when option.active/selected and
'text-ink-muted' otherwise) by extending the cn call to include the conditional
text color so both category and assignee labels render consistently.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ace811b0-c055-45ba-b9c3-32c4df6023c9

📥 Commits

Reviewing files that changed from the base of the PR and between e6fbbb0 and d1fddb0.

⛔ Files ignored due to path filters (1)
  • js/app/bun.lock is excluded by !**/*.lock, !**/bun.lock
📒 Files selected for processing (2)
  • js/app/package.json
  • js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx

Comment on lines +227 to +229
<span class={cn('flex-1 truncate')}>
{option.label}
</span>
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.

🧹 Nitpick | 🔵 Trivial

Minor styling inconsistency between category and assignee options.

Category filter option labels (line 227-229) don't apply conditional text color, while assignee option labels (lines 301-305) use text-ink when active and text-ink-muted when inactive. Consider aligning the styling for visual consistency:

-                                    <span class={cn('flex-1 truncate')}>
+                                    <span class={cn('flex-1 truncate', active() ? 'text-ink' : 'text-ink-muted')}>
                                       {option.label}
                                     </span>

Also applies to: 301-305

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@js/app/packages/app/component/next-soup/soup-view/filters-bar/mobile-filter-drawer.tsx`
around lines 227 - 229, The category option label span currently uses className
cn('flex-1 truncate') and lacks the active/inactive text color logic used for
assignees; update the span rendering {option.label} in the category options (the
span with class cn('flex-1 truncate')) to include the same conditional class
logic as the assignee option (apply 'text-ink' when option.active/selected and
'text-ink-muted' otherwise) by extending the cn call to include the conditional
text color so both category and assignee labels render consistently.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant