Skip to content

Popups and Tooltips in full screen mode #8933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/ui/src/components/Popup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,29 @@
import PopupInstance from './PopupInstance.svelte'

export let contentPanel: HTMLElement | undefined = undefined
export let fullScreen: boolean = false

const instances: PopupInstance[] = []

export function fitPopupInstance (): void {
instances.forEach((p) => p.fitPopupInstance())
}

$: instances.length = $popups.filter((p) => p.dock !== true).length
const shouldDisplayPopup = (popup: any): boolean => {
return (
(fullScreen && document.fullscreenElement != null && popup.element !== 'full-centered') ||
(!fullScreen && document.fullscreenElement != null && popup.element === 'full-centered') ||
(!fullScreen && document.fullscreenElement == null)
)
}

$: instances.length = $popups.filter((p) => p.dock !== true && shouldDisplayPopup(p)).length
</script>

{#if $popups.length > 0}
<slot name="popup-header" />
{/if}
{#each $popups.filter((p) => p.dock !== true) as popup, i (popup.id)}
{#each $popups.filter((p) => p.dock !== true && shouldDisplayPopup(p)) as popup, i (popup.id)}
<PopupInstance
bind:this={instances[i]}
is={popup.is}
Expand Down
269 changes: 141 additions & 128 deletions packages/ui/src/components/TooltipInstance.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import { capitalizeFirstLetter, formatKey } from '../utils'
import { testing } from '..'

export let fullScreen: boolean = false

let tooltipHTML: HTMLElement
let nubHTML: HTMLElement
let dir: TooltipAlignment
Expand Down Expand Up @@ -64,6 +66,8 @@
visibility: 'hidden',
classList: ''
}
const shouldHideTooltip = (): boolean =>
(fullScreen && document.fullscreenElement == null) || (!fullScreen && document.fullscreenElement != null)

const clearStyles = (): void => {
shown = false
Expand Down Expand Up @@ -248,6 +252,7 @@
}

const hideTooltip = (): void => {
if (shouldHideTooltip()) return
if (tooltipHTML) options.visibility = 'hidden'
shown = false
closeTooltip()
Expand All @@ -256,7 +261,7 @@
$: shownTooltip = $tooltip.element && tooltipHTML

const whileShow = (ev: MouseEvent): void => {
if (!$tooltip.element) return
if (!$tooltip.element || shouldHideTooltip()) return
const rectP = tooltipHTML.getBoundingClientRect()
rect = $tooltip.element.getBoundingClientRect()
const dT: number = dir === 'bottom' && $tooltip.kind !== 'submenu' ? 12 : 0
Expand All @@ -270,12 +275,13 @@
}
}

$: if (kind === 'submenu') {
$: if (kind === 'submenu' && !shouldHideTooltip()) {
options = fitSubmenu()
} else {
} else if (!shouldHideTooltip()) {
options = fitTooltip(tooltipHTML, clWidth)
}
afterUpdate(() => {
if (shouldHideTooltip()) return
if (kind === 'submenu') {
options = fitSubmenu()
} else {
Expand All @@ -287,18 +293,6 @@
})
</script>

{#if $tooltip.kind === 'popup'}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="modal-overlay antiOverlay"
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
on:click|stopPropagation|preventDefault={() => {
closeTooltip()
}}
on:keydown|stopPropagation|preventDefault={() => {}}
/>
{/if}

<svelte:window
bind:innerWidth={docWidth}
bind:innerHeight={docHeight}
Expand All @@ -318,48 +312,8 @@
}
}}
/>
{#if $tooltip.component && $tooltip.kind !== 'submenu'}
<div
class="popup-tooltip {options.classList} {$tooltip.style}"
class:testing
class:shown
class:doublePadding={$tooltip.label}
use:resizeObserver={(element) => {
clWidth = element.clientWidth
options = fitTooltip(tooltipHTML, clWidth)
}}
style:top={options.top}
style:bottom={options.bottom}
style:left={options.left}
style:right={options.right}
style:width={options.width}
style:height={options.height}
style:transform={options.transform}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
bind:this={tooltipHTML}
>
{#if $tooltip.label}
<div class="fs-title mb-4">
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
</div>
{/if}
{#if typeof $tooltip.component === 'string'}
<Component
is={$tooltip.component}
props={$tooltip.props}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{:else}
<svelte:component
this={$tooltip.component}
{...$tooltip.props}
on:tooltip={(evt) => {
$modals = [...$modals.filter((t) => t.type !== 'tooltip'), { ...$tooltip, ...evt.detail }]
}}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{/if}
</div>

{#if !fullScreen}
<svg class="svg-mask">
<clipPath id="nub-bg">
<path
Expand All @@ -372,83 +326,142 @@
/>
</clipPath>
</svg>
{#if !$tooltip.noArrow}
{/if}

{#if (fullScreen && document.fullscreenElement != null) || (!fullScreen && document.fullscreenElement == null)}
{#if $tooltip.kind === 'popup'}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
bind:this={nubHTML}
class="modal-overlay antiOverlay"
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
class="nub {nubDirection ?? ''}"
class:testing
class:shown
on:click|stopPropagation|preventDefault={() => {
closeTooltip()
}}
on:keydown|stopPropagation|preventDefault={() => {}}
/>
{/if}
{:else if $tooltip.label && $tooltip.kind !== 'submenu'}
<div
class="tooltip {dir ?? ''} {options.classList}"
bind:this={tooltipHTML}
style:top={options.top}
style:bottom={options.bottom}
style:left={options.left}
style:right={options.right}
style:width={options.width}
style:height={options.height}
style:max-width={options.maxWidth}
style:transform={options.transform}
style:visibility={options.visibility}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
>
<span class="label">
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
</span>
{#if $tooltip.keys !== undefined}
<div class="keys">
{#each $tooltip.keys as key, i}
{#if i !== 0}
<div class="mr-1 ml-1">/</div>
{/if}
{#each formatKey(key) as k, jj}
<div class="key">
{#each k as kk, j}
{#if j !== 0}
+
{/if}
{capitalizeFirstLetter(kk.trim())}
{/each}
</div>
{/each}
{/each}
</div>
{/if}
</div>
{:else if $tooltip.kind === 'submenu'}
<div
class="submenu-container {dir ?? ''} {options.classList}"
use:resizeObserver={(element) => {
clWidth = element.clientWidth
}}
style:top={options.top}
style:bottom={options.bottom}
style:left={options.left}
style:right={options.right}
style:width={options.width}
style:height={options.height}
style:transform={options.transform}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
bind:this={tooltipHTML}
>
{#if typeof $tooltip.component === 'string'}
<Component
is={$tooltip.component}
props={$tooltip.props}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{:else}
<svelte:component
this={$tooltip.component}
{...$tooltip.props}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}

{#if $tooltip.component && $tooltip.kind !== 'submenu'}
<div
class="popup-tooltip {options.classList} {$tooltip.style}"
class:testing
class:shown
class:doublePadding={$tooltip.label}
use:resizeObserver={(element) => {
clWidth = element.clientWidth
options = fitTooltip(tooltipHTML, clWidth)
}}
style:top={options.top}
style:bottom={options.bottom}
style:left={options.left}
style:right={options.right}
style:width={options.width}
style:height={options.height}
style:transform={options.transform}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
bind:this={tooltipHTML}
>
{#if $tooltip.label}
<div class="fs-title mb-4">
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
</div>
{/if}
{#if typeof $tooltip.component === 'string'}
<Component
is={$tooltip.component}
props={$tooltip.props}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{:else}
<svelte:component
this={$tooltip.component}
{...$tooltip.props}
on:tooltip={(evt) => {
$modals = [...$modals.filter((t) => t.type !== 'tooltip'), { ...$tooltip, ...evt.detail }]
}}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{/if}
</div>

{#if !$tooltip.noArrow}
<div
bind:this={nubHTML}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
class="nub {nubDirection ?? ''}"
class:testing
class:shown
/>
{/if}
</div>
{:else if $tooltip.label && $tooltip.kind !== 'submenu'}
<div
class="tooltip {dir ?? ''} {options.classList}"
bind:this={tooltipHTML}
style:top={options.top}
style:bottom={options.bottom}
style:left={options.left}
style:right={options.right}
style:width={options.width}
style:height={options.height}
style:max-width={options.maxWidth}
style:transform={options.transform}
style:visibility={options.visibility}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
>
<span class="label">
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
</span>
{#if $tooltip.keys !== undefined}
<div class="keys">
{#each $tooltip.keys as key, i}
{#if i !== 0}
<div class="mr-1 ml-1">/</div>
{/if}
{#each formatKey(key) as k, jj}
<div class="key">
{#each k as kk, j}
{#if j !== 0}
+
{/if}
{capitalizeFirstLetter(kk.trim())}
{/each}
</div>
{/each}
{/each}
</div>
{/if}
</div>
{:else if $tooltip.kind === 'submenu'}
<div
class="submenu-container {dir ?? ''} {options.classList}"
use:resizeObserver={(element) => {
clWidth = element.clientWidth
}}
style:top={options.top}
style:bottom={options.bottom}
style:left={options.left}
style:right={options.right}
style:width={options.width}
style:height={options.height}
style:transform={options.transform}
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
bind:this={tooltipHTML}
>
{#if typeof $tooltip.component === 'string'}
<Component
is={$tooltip.component}
props={$tooltip.props}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{:else}
<svelte:component
this={$tooltip.component}
{...$tooltip.props}
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
/>
{/if}
</div>
{/if}
{/if}

<style lang="scss">
Expand Down
Loading
Loading