From 664eb072010ed6c7dbf9aebec705f2d88db077a1 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 4 May 2026 17:44:39 -0400 Subject: [PATCH] Polish workspace organization selector --- frontend/src/layouts/main/SidebarUserMenu.vue | 4 +- .../src/layouts/main/WorkspaceSelector.vue | 118 +++++++++++++----- 2 files changed, 89 insertions(+), 33 deletions(-) diff --git a/frontend/src/layouts/main/SidebarUserMenu.vue b/frontend/src/layouts/main/SidebarUserMenu.vue index ce42709..18ce123 100644 --- a/frontend/src/layouts/main/SidebarUserMenu.vue +++ b/frontend/src/layouts/main/SidebarUserMenu.vue @@ -165,7 +165,9 @@ .sidebar-workspace-menu { @apply absolute bottom-[calc(100%+0.5rem)] left-0 right-0 z-30 flex flex-col gap-1 rounded-[1.25rem] border p-2; - background: rgba(255, 255, 255, 0.98); + isolation: isolate; + background: #fffdf8; + background-clip: padding-box; border-color: rgba(23, 32, 51, 0.08); box-shadow: 0 18px 40px rgba(23, 32, 51, 0.12); } diff --git a/frontend/src/layouts/main/WorkspaceSelector.vue b/frontend/src/layouts/main/WorkspaceSelector.vue index 727a94d..a9fb399 100644 --- a/frontend/src/layouts/main/WorkspaceSelector.vue +++ b/frontend/src/layouts/main/WorkspaceSelector.vue @@ -13,6 +13,7 @@ mdiChevronDown, mdiCogOutline, mdiPlus, + mdiSwapHorizontal, } from '@mdi/js'; const router = useRouter(); @@ -22,6 +23,7 @@ const authStore = useAuthStore(); const isWorkspaceMenuOpen = ref(false); + const isOrganizationListOpen = ref(false); const workspaceMenuRef = ref(null); const activeOrganization = computed(() => organizationStore.activeOrganization); @@ -36,6 +38,11 @@ }); const canSwitchWorkspaces = computed(() => visibleWorkspaces.value.length > 1); const canSwitchOrganizations = computed(() => organizationStore.organizations.length > 1); + const switchableOrganizations = computed(() => + organizationStore.organizations.filter( + organization => organization.id !== organizationStore.selectedOrganizationId + ) + ); const canManageWorkspaces = computed(() => activeOrganization.value?.currentUserPermissions?.includes(organizationPermissions.createWorkspaces) || activeOrganization.value?.currentUserPermissions?.includes(organizationPermissions.manageWorkspaces) || @@ -57,11 +64,13 @@ } isWorkspaceMenuOpen.value = !isWorkspaceMenuOpen.value; + isOrganizationListOpen.value = false; } function chooseWorkspace(workspaceId) { workspaceStore.setActiveWorkspace(workspaceId); isWorkspaceMenuOpen.value = false; + isOrganizationListOpen.value = false; } function chooseOrganization(organizationId) { @@ -71,21 +80,29 @@ workspace => workspace.organizationId === organizationId ); workspaceStore.setActiveWorkspace(nextWorkspace?.id ?? null); + isOrganizationListOpen.value = false; + } + + function toggleOrganizationList() { + isOrganizationListOpen.value = !isOrganizationListOpen.value; } async function openCreateWorkspace() { isWorkspaceMenuOpen.value = false; + isOrganizationListOpen.value = false; await router.push({ name: 'workspace-create' }); } async function openOrganizationSettings(organizationId) { isWorkspaceMenuOpen.value = false; + isOrganizationListOpen.value = false; await router.push({ name: 'organization-settings', params: { organizationId } }); } function handleDocumentClick(event) { if (workspaceMenuRef.value && !workspaceMenuRef.value.contains(event.target)) { isWorkspaceMenuOpen.value = false; + isOrganizationListOpen.value = false; } } @@ -154,36 +171,57 @@ -
-
- {{ t('workspaceSelector.organizationLabel') }} - {{ activeOrganizationName }} +
+
+
- + +
@@ -279,18 +317,18 @@ border-color: rgba(23, 32, 51, 0.08); } - .organization-switcher-label { - @apply flex flex-col gap-0.5 px-3 py-2; + .organization-current-row { + @apply flex w-full min-w-0 flex-col gap-1; } - .organization-switcher-label span { - @apply text-xs font-bold uppercase tracking-[0.18em]; - color: #7a8799; + .organization-current { + @apply w-full min-w-0 border; + background: rgba(23, 32, 51, 0.04); + border-color: rgba(23, 32, 51, 0.08); } - .organization-switcher-label strong { - @apply truncate text-sm; - color: #172033; + .organization-current:hover { + background: rgba(23, 32, 51, 0.07); } .organization-mark { @@ -299,7 +337,23 @@ color: #172033; } - .organization-settings-link { - @apply justify-between; + .organization-action-icon { + @apply flex-shrink-0 text-base; + color: #526178; + } + + .organization-swap-button { + @apply flex w-full items-center justify-between gap-3 rounded-[0.9rem] border px-3 py-2.5 text-sm font-semibold transition-colors; + background: rgba(23, 32, 51, 0.04); + border-color: rgba(23, 32, 51, 0.08); + color: #172033; + } + + .organization-swap-button:hover { + background: rgba(23, 32, 51, 0.08); + } + + .organization-options { + @apply flex flex-col gap-1; }