diff --git a/src/app.css b/src/app.css index 1d9c74770e..02d7c97bf1 100644 --- a/src/app.css +++ b/src/app.css @@ -918,3 +918,15 @@ html.high-contrast:not(.dark) .shimmer { color: var(--color-gray-700); -webkit-text-fill-color: var(--color-gray-700); } + +@media (min-width: 601px) { + [data-sonner-toaster][data-x-position='right'] { + right: max( + env(safe-area-inset-right), + min( + calc(var(--offset) + var(--right-pane-width, 0px)), + calc(100vw - var(--width) - var(--offset)) + ) + ); + } +} diff --git a/src/lib/components/channel/Channel.svelte b/src/lib/components/channel/Channel.svelte index a3606485f7..0a83029574 100644 --- a/src/lib/components/channel/Channel.svelte +++ b/src/lib/components/channel/Channel.svelte @@ -15,6 +15,7 @@ user } from '$lib/stores'; import { getChannelById, getChannelMessages, sendMessage } from '$lib/apis/channels'; + import { trackRightPaneWidth } from '$lib/utils/rightPane'; import Messages from './Messages.svelte'; import MessageInput from './MessageInput.svelte'; @@ -266,6 +267,16 @@ let mediaQuery; let largeScreen = false; + let threadPaneEl: HTMLElement | null = null; + let untrackPaneWidth: (() => void) | null = null; + + const trackPaneWidth = (el: HTMLElement | null) => { + untrackPaneWidth?.(); + untrackPaneWidth = el ? trackRightPaneWidth(el) : null; + }; + + $: trackPaneWidth(threadPaneEl); + onMount(() => { if ($chatId) { chatId.set(''); @@ -292,6 +303,8 @@ updateLastReadAt(id); _channelId.set(null); $socket?.off('events:channel', channelEventHandler); + untrackPaneWidth?.(); + untrackPaneWidth = null; }); @@ -439,7 +452,7 @@ /> - +
void) | null = null; + + const trackPaneWidth = (el: HTMLElement | null) => { + untrackPaneWidth?.(); + untrackPaneWidth = el ? trackRightPaneWidth(el) : null; + }; + + $: trackPaneWidth(paneEl); + // Tab state for Controls+Files panel let activeTab = savedTab; // svelte-ignore reactive_declaration_module_script_dependency @@ -251,6 +262,8 @@ isDestroyed = true; paneReady = false; resizeObserver?.disconnect(); + untrackPaneWidth?.(); + untrackPaneWidth = null; if (!largeScreen) { showControls.set(false); } @@ -401,6 +414,7 @@ { if ($showControls && pane.isExpanded()) { diff --git a/src/lib/components/notes/NotePanel.svelte b/src/lib/components/notes/NotePanel.svelte index 4eedea0672..b2aa7974aa 100644 --- a/src/lib/components/notes/NotePanel.svelte +++ b/src/lib/components/notes/NotePanel.svelte @@ -3,6 +3,7 @@ import { Pane, PaneResizer } from 'paneforge'; import Drawer from '../common/Drawer.svelte'; + import { trackRightPaneWidth } from '$lib/utils/rightPane'; export let show = false; export let pane = null; @@ -14,6 +15,16 @@ let minSize = 0; + let paneEl: HTMLElement | null = null; + let untrackPaneWidth: (() => void) | null = null; + + const trackPaneWidth = (el: HTMLElement | null) => { + untrackPaneWidth?.(); + untrackPaneWidth = el ? trackRightPaneWidth(el) : null; + }; + + $: trackPaneWidth(paneEl); + const handleMediaQuery = async (e) => { if (e.matches) { largeScreen = true; @@ -58,6 +69,8 @@ onDestroy(() => { mediaQuery.removeEventListener('change', handleMediaQuery); + untrackPaneWidth?.(); + untrackPaneWidth = null; }); @@ -86,6 +99,7 @@ { diff --git a/src/lib/utils/rightPane.ts b/src/lib/utils/rightPane.ts new file mode 100644 index 0000000000..c4f2c2abda --- /dev/null +++ b/src/lib/utils/rightPane.ts @@ -0,0 +1,32 @@ +const CSS_VARIABLE = '--right-pane-width'; + +let owner: HTMLElement | null = null; + +export const trackRightPaneWidth = (el: HTMLElement) => { + owner = el; + + const publish = (width: number) => { + if (owner !== el) { + return; + } + document.documentElement.style.setProperty(CSS_VARIABLE, `${width}px`); + }; + + const observer = new ResizeObserver((entries) => { + for (const entry of entries) { + publish(entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width); + } + }); + + observer.observe(el); + publish(el.offsetWidth); + + return () => { + observer.disconnect(); + + if (owner === el) { + owner = null; + document.documentElement.style.removeProperty(CSS_VARIABLE); + } + }; +};