fix(client): keep space switcher dropdown inside its popover (#2392)

This commit is contained in:
Philip Okugbe
2026-08-14 02:08:28 +01:00
committed by GitHub
parent ea59912c7e
commit c093c18bf3
2 changed files with 17 additions and 5 deletions
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { useDebouncedValue } from "@mantine/hooks"; import { useDebouncedValue } from "@mantine/hooks";
import { Group, Select, SelectProps, Text } from "@mantine/core"; import { Group, Select, SelectProps, Text } from "@mantine/core";
import { useGetSpacesQuery } from "@/features/space/queries/space-query.ts"; import { useGetSpacesQuery } from "@/features/space/queries/space-query.ts";
@@ -14,6 +14,7 @@ interface SpaceSelectProps {
width?: number; width?: number;
opened?: boolean; opened?: boolean;
clearable?: boolean; clearable?: boolean;
withinPortal?: boolean;
} }
const renderSelectOption: SelectProps["renderOption"] = ({ option }) => ( const renderSelectOption: SelectProps["renderOption"] = ({ option }) => (
@@ -41,6 +42,7 @@ export function SpaceSelect({
width, width,
opened, opened,
clearable, clearable,
withinPortal = true,
}: SpaceSelectProps) { }: SpaceSelectProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const [searchValue, setSearchValue] = useState(""); const [searchValue, setSearchValue] = useState("");
@@ -50,9 +52,13 @@ export function SpaceSelect({
limit: 50, limit: 50,
}); });
const [data, setData] = useState([]); const [data, setData] = useState([]);
const fetchedSpaces = useRef(new Map<string, ISpace>());
useEffect(() => { useEffect(() => {
if (spaces) { if (spaces) {
spaces.items.forEach((space: ISpace) =>
fetchedSpaces.current.set(space.slug, space),
);
const spaceData = spaces?.items const spaceData = spaces?.items
.filter((space: ISpace) => space.slug !== value) .filter((space: ISpace) => space.slug !== value)
.map((space: ISpace) => { .map((space: ISpace) => {
@@ -83,14 +89,19 @@ export function SpaceSelect({
onSearchChange={setSearchValue} onSearchChange={setSearchValue}
clearable={clearable} clearable={clearable}
variant="filled" variant="filled"
onChange={(slug) => onChange={(slug) => {
onChange(spaces.items?.find((item) => item.slug === slug)) // options accumulate across fetches; resolve against everything
// fetched, not just the latest query result
const space = slug && fetchedSpaces.current.get(slug);
if (space) {
onChange(space);
} }
}}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
nothingFoundMessage={t("No space found")} nothingFoundMessage={t("No space found")}
limit={50} limit={50}
checkIconPosition="right" checkIconPosition="right"
comboboxProps={{ width, withinPortal: true, position: "bottom", keepMounted: false, dropdownPadding: 0 }} comboboxProps={{ width, withinPortal, position: "bottom", keepMounted: false, dropdownPadding: 0 }}
dropdownOpened={opened} dropdownOpened={opened}
/> />
); );
@@ -70,6 +70,7 @@ export function SwitchSpace({
onChange={(space) => handleSelect(space.slug)} onChange={(space) => handleSelect(space.slug)}
width={300} width={300}
opened={true} opened={true}
withinPortal={false}
/> />
</Popover.Dropdown> </Popover.Dropdown>
</Popover> </Popover>