From fefc8c62a00fe7a39f3104091e08087cd7c37afb Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 10 Mar 2026 18:25:09 +0000 Subject: [PATCH] fix: teams selection not sticking in workspace settings (#8309) Fix portal class mismatch in clickOutside that caused premature dropdown closing, and simplify TeamSelector/ChannelSelector state sync to use getter/setter bindings instead of bidirectional $effect chains. Co-authored-by: Claude Opus 4.6 --- .../src/lib/components/ChannelSelector.svelte | 38 +++++++++---------- .../src/lib/components/TeamSelector.svelte | 38 ++++++++++--------- frontend/src/lib/utils.ts | 2 +- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/frontend/src/lib/components/ChannelSelector.svelte b/frontend/src/lib/components/ChannelSelector.svelte index 6dfc204fc6..3211fe914a 100644 --- a/frontend/src/lib/components/ChannelSelector.svelte +++ b/frontend/src/lib/components/ChannelSelector.svelte @@ -26,7 +26,7 @@ let { disabled = false, placeholder = 'Select channel', - selectedChannel = $bindable(undefined), + selectedChannel = $bindable(), containerClass = 'w-64', minWidth = '160px', channels = undefined, @@ -40,8 +40,6 @@ let loadedChannels = $state([]) let loadedForTeamId = $state(undefined) - let selectedChannelId = $state(selectedChannel?.channel_id) - const searchMode = $derived(!channels && !!teamId) let displayChannels = $derived.by(() => { @@ -55,21 +53,17 @@ return baseChannels }) - $effect(() => { - const newChannel = selectedChannelId - ? displayChannels.find((c) => c.channel_id === selectedChannelId) - : undefined - - if (newChannel?.channel_id !== selectedChannel?.channel_id) { - selectedChannel = newChannel + // Single setter to bridge Select's string value -> selectedChannel object. + function setSelectedChannelById(newId: string | undefined) { + if (newId) { + const channel = displayChannels.find((c) => c.channel_id === newId) + if (channel && channel.channel_id !== selectedChannel?.channel_id) { + selectedChannel = channel + } + } else if (selectedChannel !== undefined) { + selectedChannel = undefined } - }) - - $effect(() => { - if (selectedChannel?.channel_id !== selectedChannelId) { - selectedChannelId = selectedChannel?.channel_id - } - }) + } let previousChannelId = $state(undefined) @@ -136,7 +130,10 @@ clearable disabled={disabled || !teamId} loading={isFetching} - bind:value={selectedChannelId} + bind:value={ + () => selectedChannel?.channel_id, + (newId) => setSelectedChannelById(newId) + } /> {:else} selectedTeam?.team_id, + (newId) => setSelectedTeamById(newId) + } /> {/if} diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index 496dba427b..49a9568312 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -293,7 +293,7 @@ export function validatePassword(password: string): boolean { return re.test(password) } -const portalDivs = ['#app-editor-select', '.select-dropdown-portal', '[data-context-menu]'] +const portalDivs = ['#app-editor-select', '.dropdown-portal', '[data-context-menu]'] interface ClickOutsideOptions { capture?: boolean