Skip to content

fix: marketplace filter dropdown positioning on mobile (#38651)#38899

Open
JatinSharma222 wants to merge 3 commits into
RocketChat:developfrom
JatinSharma222:fix/38651-marketplace-mobile-filter-dropdown-positioning
Open

fix: marketplace filter dropdown positioning on mobile (#38651)#38899
JatinSharma222 wants to merge 3 commits into
RocketChat:developfrom
JatinSharma222:fix/38651-marketplace-mobile-filter-dropdown-positioning

Conversation

@JatinSharma222
Copy link
Copy Markdown

@JatinSharma222 JatinSharma222 commented Feb 22, 2026

Description

Fixes #38651

On mobile screen sizes (≤ 768px), the filter dropdowns in the Marketplace page
(Explore, Installed, Premium) were rendering in incorrect positions — dropdowns
would appear under the wrong filter trigger due to a positioning miscalculation.

Root Cause

The DropDownListWrapper component used usePosition with position: fixed,
which calculates dropdown position based on the viewport. On mobile, when the
flex container wraps filters across multiple lines, the fixed positioning loses
its reference point and attaches the dropdown to the wrong anchor element.

Changes

  • DropDownListWrapper.tsx — Replaced usePosition + fixed positioning
    with position: absolute + top: 100%
  • RadioDropDown.tsx — Wrapped in position: relative Box for isolated
    positioning context
  • CategoryDropDown.tsx — Same fix as RadioDropDown
  • AppsFilters.tsx — Separated search bar and filters into independent rows;
    filters stay horizontal on all screen sizes with proper spacing

After Fix

Screen.Recording.2026-02-22.at.7.05.31.PM.mov

Testing Steps

  1. Open Marketplace → Installed or Explore page
  2. Resize browser to ≤ 768px width
  3. Click any filter dropdown — opens correctly aligned to its own trigger

Summary by CodeRabbit

  • Refactor

    • Redesigned marketplace filter layout for improved responsiveness (breakpoint-aware sizing, vertical stacking, and a second row of controls).
    • Made filter inputs and dropdowns full-width and wrapped in consistent containers for stable alignment and spacing.
    • Simplified dropdown positioning and adjusted gaps between search and filters for cleaner layout.
  • Bug Fixes

    • Fixed dropdown positioning on mobile for reliable display.

@JatinSharma222 JatinSharma222 requested a review from a team as a code owner February 22, 2026 13:50
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot Bot commented Feb 22, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 22, 2026

🦋 Changeset detected

Latest commit: 65d42ae

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/apps Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/model-typings Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-client Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/ui-voip Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/models Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/server-fetch Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 22, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 22, 2026

No actionable comments were generated in the recent review. 🎉

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0815c2d and 65d42ae.

📒 Files selected for processing (1)
  • .changeset/forty-spoons-dance.md
🔇 Additional comments (1)
.changeset/forty-spoons-dance.md (1)

1-5: LGTM!

The changeset is correct: all modified source files live under apps/meteor, mapping to @rocket.chat/meteor, and patch is the appropriate bump level for a pure bug-fix with no API surface changes.


Walkthrough

This PR updates marketplace filter layout and dropdown containers to use Box wrappers with responsive sizing and explicit inline absolute positioning for dropdown lists, reorganizes filter rows for breakpoints, and adjusts child width handling to fix dropdown placement on small screens.

Changes

Cohort / File(s) Summary
Filter layout / AppsFilters
apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx
Replaces previous sizing logic with breakpoint-driven isLg and filterBoxProps; restructures filters into a column layout with two rows and adds row-gap; ensures dropdown children receive width="100%".
Dropdown root wrappers
apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx, apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx
Replaces fragment wrappers with Box (position='relative', width='100%'), moves anchors inside the Box and passes width props to anchors to create consistent positioning contexts.
Dropdown list positioning
apps/meteor/client/views/marketplace/components/DropDownListWrapper.tsx
Removes usePosition and computed style objects; applies explicit inline absolute positioning on the dropdown Box (top:100%, insetInlineStart:0, marginTop) while retaining useOutsideClick logic.
Changeset
.changeset/forty-spoons-dance.md
Adds changeset entry noting a patch release and the marketplace mobile dropdown positioning fix.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hopped through boxes, tucked each pane,
Anchors snug, no menus stray,
On tiny screens I set the line,
Dropdowns sit where they should stay,
A happy hop for layout day 🌿

🚥 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 PR title 'fix: marketplace filter dropdown positioning on mobile (#38651)' clearly and concisely describes the main change, matching the core objective of fixing dropdown positioning issues on mobile viewports.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #38651: replacing fixed positioning with absolute positioning in DropDownListWrapper.tsx, adding position:relative Box wrappers in RadioDropDown.tsx and CategoryDropDown.tsx, and restructuring AppsFilters.tsx to ensure proper dropdown alignment and spacing on mobile viewports.
Out of Scope Changes check ✅ Passed All changes in the PR are directly related to fixing the dropdown positioning issue on mobile; modifications to AppsFilters.tsx, CategoryDropDown.tsx, DropDownListWrapper.tsx, and RadioDropDown.tsx all contribute to the stated objective, with only a standard changeset entry added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 4 files

- Separate search bar from filter dropdowns into own row
- Wrap each dropdown in position:relative Box to anchor correctly
- Switch DropDownListWrapper from fixed to absolute positioning
- Filters stay horizontal on all screen sizes with proper gap

Fixes RocketChat#38651
@JatinSharma222 JatinSharma222 force-pushed the fix/38651-marketplace-mobile-filter-dropdown-positioning branch from ac90900 to 0815c2d Compare February 22, 2026 14:02
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

🧹 Nitpick comments (1)
apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx (1)

65-79: Redundant position='relative' on wrapper Box elements

Each RadioDropDown and CategoryDropDown now establishes its own position: relative context internally (via the Box position='relative' wrapper added in this PR). CSS position: absolute anchors to the nearest positioned ancestor, so DropDownListWrapper already anchors correctly to the component's own inner Box. The position='relative' on these outer wrapper boxes in AppsFilters has no effect and can be removed.

🛠️ Proposed cleanup
- <Box position='relative' flexGrow={1} flexShrink={1} flexBasis='x0' {...filterBoxProps}>
+ <Box flexGrow={1} flexShrink={1} flexBasis='x0' {...filterBoxProps}>
    <RadioDropDown group={freePaidFilterStructure} onSelected={freePaidFilterOnSelected} width='100%' />
  </Box>

(Apply the same removal to all four wrapper boxes at lines 65, 69, 73, and 77.)

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

In `@apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx` around lines
65 - 79, Remove the redundant position='relative' props from the outer Box
wrappers in AppsFilters that wrap RadioDropDown and CategoryDropDown (the four
Box instances around RadioDropDown group={freePaidFilterStructure},
RadioDropDown group={statusFilterStructure}, CategoryDropDown, and RadioDropDown
group={sortFilterStructure}); each dropdown already provides its own positioned
inner Box/DropDownListWrapper, so simply delete the position='relative'
attribute on those Box components and keep the rest of their props (flexGrow,
flexShrink, flexBasis, {...filterBoxProps}) unchanged.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3145c41 and a63a67d.

📒 Files selected for processing (4)
  • apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx
  • apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx
  • apps/meteor/client/views/marketplace/components/DropDownListWrapper.tsx
  • apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx
  • apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx
  • apps/meteor/client/views/marketplace/components/DropDownListWrapper.tsx
  • apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (1)
apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx (1)

31-38: LGTM — Wrapping in Box position='relative' correctly establishes the stacking context for DropDownListWrapper's position: absolute; top: 100%.

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

Inline comments:
In `@apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx`:
- Around line 61-63: The child filter row Box (Box with props display='flex'
flexDirection='row' flexWrap='wrap' alignItems='center' mbs={-16}) is using a
negative mbs that cancels the parent column Box's style={{ rowGap: '8px' }},
causing overlap; remove the mbs={-16} or replace it with a positive spacing
token consistent with the design system (e.g., use an existing positive spacing
prop or mbs={16}) so the rowGap on the parent Box and spacing tokens are aligned
and no negative margin is used.

In
`@apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx`:
- Around line 36-43: CategoryDropDownAnchor can miss width when callers don't
pass it because it only gets {...props}; make its width explicit like
RadioDropDownAnchor so it always fills the surrounding Box: update the
CategoryDropDown component to render <CategoryDropDownAnchor {...props}
width='100%' ref={reference} onClick={toggleCollapsed as any}
selectedCategoriesCount={selectedCategories.length} /> (i.e., ensure
width='100%' is set on CategoryDropDownAnchor rather than relying on callers to
supply it) so the anchor consistently stretches inside the Box.

In `@apps/meteor/client/views/marketplace/components/DropDownListWrapper.tsx`:
- Around line 6-9: Remove the unused forwardRef wrapper around
DropDownListWrapper and stop swallowing the caller's anchor ref: change the
component signature for CategoryDropDownListWrapper/DropDownListWrapper to
accept an optional anchorRef prop (e.g., anchorRef?: RefObject<HTMLElement>)
instead of a forwarded ref, keep the internal target = useRef<HTMLElement>(null)
for the Box, and call useOutsideClick([target, anchorRef], onClose) so the
anchor is excluded; then update callers (RadioDropDown, CategoryDropDown) to
pass anchorRef={reference} rather than ref={reference}.

---

Nitpick comments:
In `@apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx`:
- Around line 65-79: Remove the redundant position='relative' props from the
outer Box wrappers in AppsFilters that wrap RadioDropDown and CategoryDropDown
(the four Box instances around RadioDropDown group={freePaidFilterStructure},
RadioDropDown group={statusFilterStructure}, CategoryDropDown, and RadioDropDown
group={sortFilterStructure}); each dropdown already provides its own positioned
inner Box/DropDownListWrapper, so simply delete the position='relative'
attribute on those Box components and keep the rest of their props (flexGrow,
flexShrink, flexBasis, {...filterBoxProps}) unchanged.

Comment thread apps/meteor/client/views/marketplace/AppsPage/AppsFilters.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.

🧹 Nitpick comments (1)
apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx (1)

65-79: Redundant position='relative' on each filter wrapper Box.

Each RadioDropDown and CategoryDropDown now internally wraps its content in <Box position='relative'>, which becomes the nearest positioned ancestor for DropDownListWrapper's position: absolute. The extra position='relative' on the outer wrapper Box in AppsFilters (lines 65, 69, 73, 77) has no effect on dropdown placement and can be removed to simplify the tree.

♻️ Proposed refactor
- <Box position='relative' flexGrow={1} flexShrink={1} flexBasis='x0' {...filterBoxProps}>
+ <Box flexGrow={1} flexShrink={1} flexBasis='x0' {...filterBoxProps}>
    <RadioDropDown group={freePaidFilterStructure} onSelected={freePaidFilterOnSelected} width='100%' />
  </Box>
  ...
- <Box position='relative' flexGrow={1} flexShrink={1} flexBasis='x0' {...filterBoxProps}>
+ <Box flexGrow={1} flexShrink={1} flexBasis='x0' {...filterBoxProps}>
    <RadioDropDown group={statusFilterStructure} onSelected={statusFilterOnSelected} width='100%' />
  </Box>
  ...

(Apply the same removal to lines 73 and 77.)

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

In `@apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx` around lines
65 - 79, Remove the redundant position='relative' prop from the outer Box
wrappers that wrap RadioDropDown and CategoryDropDown in AppsFilters: the
dropdown components (RadioDropDown and CategoryDropDown) already include an
internal <Box position='relative'> so the outer Box position prop is
unnecessary; update the Boxes around freePaidFilterStructure,
statusFilterStructure, categories/selectedCategories, and sortFilterStructure
(the Box instances that pass filterBoxProps and width='100%') to omit
position='relative' while keeping all other props (flexGrow, flexShrink,
flexBasis, {...filterBoxProps}) intact.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a63a67d and 0815c2d.

📒 Files selected for processing (4)
  • apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx
  • apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx
  • apps/meteor/client/views/marketplace/components/DropDownListWrapper.tsx
  • apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/client/views/marketplace/components/DropDownListWrapper.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx
  • apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx
  • apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx
🧠 Learnings (1)
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx
🔇 Additional comments (1)
apps/meteor/client/views/marketplace/components/RadioDropDown/RadioDropDown.tsx (1)

30-39: LGTM — Box position='relative' correctly anchors the absolute-positioned dropdown list.

Explicit width='100%' on RadioDropDownAnchor (line 32) ensures the anchor always fills the wrapper, consistent with how other dropdown anchors are handled.

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

Duplicate comments:
In `@apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx`:
- Around line 61-63: The nested Box with filters uses mbs={-16} which conflicts
with the parent Box's rowGap: '8px' and causes overlap; update the filter row
(the inner Box that contains FilterByText and tag chips) to remove the negative
mbs prop or replace it with a positive Fuselage spacing token (e.g., mbs={16} or
an approved token) so spacing is controlled by the parent rowGap consistently;
keep references to the Box component around FilterByText and the setText handler
to locate the element to change.

In
`@apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.tsx`:
- Around line 36-43: CategoryDropDownAnchor is not explicitly given
width='100%', so if callers omit width via {...props} the anchor can be narrower
than its Box wrapper; update the JSX to pass width='100%' directly to
CategoryDropDownAnchor (e.g., <CategoryDropDownAnchor ref={reference}
width='100%' onClick={toggleCollapsed as any}
selectedCategoriesCount={selectedCategories.length} {...props} />) so the anchor
always fills the Box; keep the rest of props, ref, onClick, and
selectedCategoriesCount unchanged.

---

Nitpick comments:
In `@apps/meteor/client/views/marketplace/AppsPage/AppsFilters.tsx`:
- Around line 65-79: Remove the redundant position='relative' prop from the
outer Box wrappers that wrap RadioDropDown and CategoryDropDown in AppsFilters:
the dropdown components (RadioDropDown and CategoryDropDown) already include an
internal <Box position='relative'> so the outer Box position prop is
unnecessary; update the Boxes around freePaidFilterStructure,
statusFilterStructure, categories/selectedCategories, and sortFilterStructure
(the Box instances that pass filterBoxProps and width='100%') to omit
position='relative' while keeping all other props (flexGrow, flexShrink,
flexBasis, {...filterBoxProps}) intact.

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.

(MOBILE) Clicking One Filter Apprears to Open Dropdown Under Another Filter in marketplace

2 participants