feat: show secondary search filters only when applied

Created by and Labels now stay hidden until they hold a value; a Filter
button at the right end of the bar lists the hidden ones and opens the
picked filter's dropdown immediately.
This commit is contained in:
Philipinho
2026-08-24 21:19:58 +01:00
parent cdfb48141f
commit da58bb382e
3 changed files with 99 additions and 22 deletions
@@ -21,6 +21,8 @@ type CreatorFilterMenuProps = {
| "top-end"
| "top";
zIndex?: number;
opened?: boolean;
onOpenChange?: (opened: boolean) => void;
};
export function CreatorFilterMenu({
@@ -30,6 +32,8 @@ export function CreatorFilterMenu({
width = 280,
position = "bottom-end",
zIndex,
opened,
onOpenChange,
}: CreatorFilterMenuProps) {
const { t } = useTranslation();
const [searchQuery, setSearchQuery] = useState("");
@@ -46,7 +50,14 @@ export function CreatorFilterMenu({
const users: IUser[] = (suggestion?.users as IUser[]) ?? [];
return (
<Menu shadow="md" width={width} position={position} zIndex={zIndex}>
<Menu
shadow="md"
width={width}
position={position}
zIndex={zIndex}
opened={opened}
onChange={onOpenChange}
>
<Menu.Target>{children}</Menu.Target>
<Menu.Dropdown>
<TextInput
@@ -27,6 +27,8 @@ type LabelFilterMenuProps = {
| "top-end"
| "top";
zIndex?: number;
opened?: boolean;
onOpenChange?: (opened: boolean) => void;
};
export function LabelFilterMenu({
@@ -36,6 +38,8 @@ export function LabelFilterMenu({
width = 280,
position = "bottom-end",
zIndex,
opened,
onOpenChange,
}: LabelFilterMenuProps) {
const { t } = useTranslation();
const scheme = useComputedColorScheme("light");
@@ -61,6 +65,8 @@ export function LabelFilterMenu({
width={width}
position={position}
zIndex={zIndex}
opened={opened}
onChange={onOpenChange}
closeOnItemClick={false}
>
<Menu.Target>{children}</Menu.Target>
@@ -11,6 +11,7 @@ import {
import {
IconChevronDown,
IconBuilding,
IconPlus,
IconFileDescription,
IconCheck,
IconUser,
@@ -52,6 +53,7 @@ export function SearchSpotlightFilters({
null
);
const [selectedLabelIds, setSelectedLabelIds] = useState<string[]>([]);
const [openedFilter, setOpenedFilter] = useState<string | null>(null);
const [workspace] = useAtom(workspaceAtom);
const { data: spacesData } = useGetSpacesQuery({ limit: 100 });
@@ -104,6 +106,24 @@ export function SearchSpotlightFilters({
}
};
const showCreatorFilter = !!selectedCreatorId || openedFilter === "creator";
const showLabelFilter =
contentType !== "attachment" &&
(selectedLabelIds.length > 0 || openedFilter === "labels");
const addableFilters: { key: string; label: string; icon: typeof IconUser }[] =
[];
if (!showCreatorFilter) {
addableFilters.push({
key: "creator",
label: t("Created by"),
icon: IconUser,
});
}
if (contentType !== "attachment" && !showLabelFilter) {
addableFilters.push({ key: "labels", label: t("Labels"), icon: IconTag });
}
return (
<div className={classes.filtersContainer}>
{workspace?.settings?.ai?.search === true && (
@@ -219,35 +239,41 @@ export function SearchSpotlightFilters({
</Menu.Dropdown>
</Menu>
<CreatorFilterMenu
value={selectedCreatorId}
onChange={handleCreatorSelect}
position="bottom-start"
width={250}
zIndex={getDefaultZIndex("max")}
>
<Button
variant="subtle"
color="gray"
size="sm"
rightSection={<IconChevronDown size={14} />}
leftSection={<IconUser size={16} />}
className={classes.filterButton}
fw={500}
{showCreatorFilter && (
<CreatorFilterMenu
value={selectedCreatorId}
onChange={handleCreatorSelect}
position="bottom-start"
width={250}
zIndex={getDefaultZIndex("max")}
opened={openedFilter === "creator"}
onOpenChange={(opened) => setOpenedFilter(opened ? "creator" : null)}
>
{selectedCreatorId
? `${t("Created by")}: ${selectedCreatorName || t("Unknown")}`
: `${t("Created by")}: ${t("Anyone")}`}
</Button>
</CreatorFilterMenu>
<Button
variant="subtle"
color="gray"
size="sm"
rightSection={<IconChevronDown size={14} />}
leftSection={<IconUser size={16} />}
className={classes.filterButton}
fw={500}
>
{selectedCreatorId
? `${t("Created by")}: ${selectedCreatorName || t("Unknown")}`
: `${t("Created by")}: ${t("Anyone")}`}
</Button>
</CreatorFilterMenu>
)}
{contentType !== "attachment" && (
{showLabelFilter && (
<LabelFilterMenu
value={selectedLabelIds}
onChange={handleLabelsSelect}
position="bottom-start"
width={250}
zIndex={getDefaultZIndex("max")}
opened={openedFilter === "labels"}
onOpenChange={(opened) => setOpenedFilter(opened ? "labels" : null)}
>
<Button
variant="subtle"
@@ -264,6 +290,40 @@ export function SearchSpotlightFilters({
</Button>
</LabelFilterMenu>
)}
{addableFilters.length > 0 && (
<Menu
shadow="md"
width={200}
position="bottom-end"
zIndex={getDefaultZIndex("max")}
>
<Menu.Target>
<Button
variant="subtle"
color="gray"
size="sm"
leftSection={<IconPlus size={16} />}
className={classes.filterButton}
style={{ marginLeft: "auto" }}
fw={500}
>
{t("Filter")}
</Button>
</Menu.Target>
<Menu.Dropdown>
{addableFilters.map((filter) => (
<Menu.Item
key={filter.key}
leftSection={<filter.icon size={16} />}
onClick={() => setOpenedFilter(filter.key)}
>
{filter.label}
</Menu.Item>
))}
</Menu.Dropdown>
</Menu>
)}
</div>
);
}