From 3cad115155bf6b2c25e4faf4c8449b2c32556f18 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 11 Aug 2026 20:55:26 -0600 Subject: [PATCH] feat: make organization selector larger and searchable (#5052) Replaces the organization dropdown with a Popover + Command combobox: wider panel and a search input to filter organizations by name. Closes #5043 --- .../organization/handle-organization.tsx | 20 +- apps/dokploy/components/layouts/side.tsx | 270 ++++++++++-------- 2 files changed, 160 insertions(+), 130 deletions(-) diff --git a/apps/dokploy/components/dashboard/organization/handle-organization.tsx b/apps/dokploy/components/dashboard/organization/handle-organization.tsx index 1a3bd919d..d6aab6ebb 100644 --- a/apps/dokploy/components/dashboard/organization/handle-organization.tsx +++ b/apps/dokploy/components/dashboard/organization/handle-organization.tsx @@ -14,7 +14,6 @@ import { DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; -import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; import { Form, FormControl, @@ -103,16 +102,19 @@ export function AddOrganization({ organizationId }: Props) { {organizationId ? ( - e.preventDefault()} + ) : ( - e.preventDefault()} + )} diff --git a/apps/dokploy/components/layouts/side.tsx b/apps/dokploy/components/layouts/side.tsx index a53892e80..f84a9196f 100644 --- a/apps/dokploy/components/layouts/side.tsx +++ b/apps/dokploy/components/layouts/side.tsx @@ -53,14 +53,26 @@ import { CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, - DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; import { Separator } from "@/components/ui/separator"; import { SIDEBAR_COOKIE_NAME, @@ -565,6 +577,8 @@ function SidebarLogo() { const [_activeTeam, setActiveTeam] = useState< typeof activeOrganization | null >(null); + const [organizationSelectorOpen, setOrganizationSelectorOpen] = + useState(false); useEffect(() => { if (activeOrganization) { @@ -587,8 +601,11 @@ function SidebarLogo() { > {/* Organization Logo and Selector */} - - + + - - + - - Organizations - -
- {organizations?.map((org) => { - const isDefault = org.members?.[0]?.isDefault ?? false; - return ( -
- { - await authClient.organization.setActive({ - organizationId: org.id, - }); - window.location.reload(); - }} - className="flex min-w-0 flex-1 gap-2 p-2" - > -
- -
- {org.name} -
- -
- - {org.ownerId === session?.user?.id && ( - <> - - { - await deleteOrganization({ +
+
+ +
+ {org.name} +
+ +
e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + > + - - - )} -
-
- ); - })} -
- {(user?.role === "owner" || - user?.role === "admin" || - isCloud) && ( - <> - - - - )} - - + {isDefault ? ( + + ) : ( + + )} + + {org.ownerId === session?.user?.id && ( + <> + + { + await deleteOrganization({ + organizationId: org.id, + }) + .then(() => { + refetch(); + toast.success( + "Organization deleted successfully", + ); + }) + .catch((error) => { + toast.error( + error?.message || + "Error deleting organization", + ); + }); + }} + > + + + + )} +
+ + ); + })} + + + {(user?.role === "owner" || + user?.role === "admin" || + isCloud) && ( +
+ +
+ )} + +
+
{/* Notification Bell */}