Skip to content

fix(frontend): prevent page shift when area it is scrollable #5546

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

Closed
wants to merge 19 commits into from
Closed
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
22 changes: 18 additions & 4 deletions frontend/src/lib/components/CenteredPage.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
<script>
import { twMerge } from 'tailwind-merge'
import Scroll from '$lib/components/Scroll.svelte'
import { layoutStore } from '$lib/layout-context'

export let useScroll = false
</script>

<div class="pb-8">
<div class={twMerge('max-w-7xl mx-auto px-4 sm:px-6 md:px-8', $$restProps.class)}>
<slot />
{#if useScroll}
<Scroll style={`height: calc(100vh - ${$layoutStore.topBarHeight}px)`}>
<div class="pb-8">
<div class={twMerge('max-w-7xl mx-auto px-4 sm:px-6 md:px-8', $$restProps.class)}>
<slot />
</div>
</div>
</Scroll>
{:else}
<div class="pb-8">
<div class={twMerge('max-w-7xl mx-auto px-4 sm:px-6 md:px-8', $$restProps.class)}>
<slot />
</div>
</div>
</div>
{/if}
17 changes: 17 additions & 0 deletions frontend/src/lib/components/Scroll.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script>
import { twMerge } from 'tailwind-merge'
</script>

<div
class={twMerge('h-full w-full overflow-y-auto scrollbar', $$props.class)}
style={$$props.style}
>
<slot />
</div>

<style>
div {
/* Prevent layout shift from scrollbar appearance */
scrollbar-gutter: stable both-edges;
}
</style>
15 changes: 15 additions & 0 deletions frontend/src/lib/layout-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { writable } from 'svelte/store'

export const LAYOUT_CONTEXT_KEY = 'layoutContext'

export interface LayoutContext {
topBarHeight: number
}

export const layoutStore = writable<LayoutContext>({
topBarHeight: 0
})

export const setTopBarHeight = (height: number) => {
layoutStore.update((state) => ({ ...state, topBarHeight: height }))
}
24 changes: 21 additions & 3 deletions frontend/src/routes/(root)/(logged)/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import { setContext } from 'svelte'
import { base } from '$app/paths'
import { Menubar } from '$lib/components/meltComponents'
import { setTopBarHeight } from '$lib/layout-context'

OpenAPI.WITH_CREDENTIALS = true
let menuOpen = false
Expand Down Expand Up @@ -340,6 +341,19 @@

muteSettings = { global: g_muted, workspace: ws_muted }
}

let topBarHeight = 0
let trackedHeight = 0
function updateTopBarHeight(newHeight: number) {
if (newHeight == trackedHeight) {
return
}
setTopBarHeight(newHeight)
trackedHeight = newHeight
}

// Track when the element is hidden based on conditions and media queries
$: updateTopBarHeight(devOnly || $userStore?.operator || innerWidth >= 768 ? 0 : topBarHeight)
</script>

<svelte:window bind:innerWidth />
Expand Down Expand Up @@ -613,12 +627,13 @@
)}
>
<main class="min-h-screen">
<div class="relative w-full h-full">
<div class="relative w-full h-full flex flex-col">
<div
class={classNames(
'py-2 px-2 sm:px-4 md:px-8 flex justify-between items-center shadow-sm max-w-7xl mx-auto md:hidden',
'py-2 px-2 sm:px-4 md:px-8 w-full justify-start shadow-sm max-w-7xl mx-auto md:hidden',
devOnly || $userStore?.operator ? 'hidden' : ''
)}
bind:clientHeight={topBarHeight}
>
<button
aria-label="Menu"
Expand All @@ -641,7 +656,10 @@
</svg>
</button>
</div>
<slot />

<div class="grow min-h-0">
<slot />
</div>
</div>
</main>
</div>
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/routes/(root)/(logged)/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { Building, ExternalLink, GitFork, Globe2, Loader2 } from 'lucide-svelte'
import { hubBaseUrlStore } from '$lib/stores'
import { base } from '$lib/base'
import { layoutStore } from '$lib/layout-context'

import ItemsList from '$lib/components/home/ItemsList.svelte'
import CreateActionsApp from '$lib/components/flows/CreateActionsApp.svelte'
Expand All @@ -23,6 +24,7 @@
import { setQuery } from '$lib/navigation'
import { page } from '$app/stores'
import { goto, replaceState } from '$app/navigation'
import Scroll from '$lib/components/Scroll.svelte'

type Tab = 'hub' | 'workspace'

Expand Down Expand Up @@ -213,7 +215,7 @@
</DrawerContent>
</Drawer>

<div>
<Scroll style={`height: calc(100vh - ${$layoutStore.topBarHeight}px)`}>
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8 h-fit-content">
{#if $workspaceStore == 'admins'}
<div class="my-4"></div>
Expand Down Expand Up @@ -314,8 +316,8 @@
</div>
</div>
</div>
</div>

{#if tab == 'workspace'}
<ItemsList bind:filter bind:subtab />
{/if}
{#if tab == 'workspace'}
<ItemsList bind:filter bind:subtab />
{/if}
</Scroll>
2 changes: 1 addition & 1 deletion frontend/src/routes/(root)/(logged)/folders/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Folders"
tooltip="Folders allow to group items such as scripts/flows/resources/schedule together and to grant homogenous RBAC permissions to groups and individual users towards them."
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/(root)/(logged)/groups/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Groups"
tooltip="Group users together to grant roles and homegenous permissions. Same users can be in many groups at the same time."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Kafka triggers"
tooltip="Windmill can consume kafka events and trigger scripts or flows based on them."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
/>

<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="MQTT triggers"
tooltip="Windmill can connect to an MQTT broker, subscribe to specific topics, and trigger scripts or flows based on those topics."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="NATS triggers"
tooltip="Windmill can consume NATS events and trigger scripts or flows based on them."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
/>

<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Postgres triggers"
tooltip="Windmill enables real-time responsiveness by listening to specific database transactions—such as inserts, updates, and deletes—and automatically triggering scripts or workflows in response."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Resources"
tooltip="Save and permission rich objects (JSON) including credentials obtained through OAuth."
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/routes/(root)/(logged)/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,19 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Custom HTTP routes"
tooltip="Every script and flow already has a canonical HTTP API endpoint/webhook attached to it, this is to create additional parametrizable ones."
documentationLink="https://www.windmill.dev/docs/core_concepts/http_routing"
>
{#if $userStore?.is_admin || $userStore?.is_super_admin}
<Button size="md" startIcon={{ icon: Plus }} on:click={() => routeEditor.openNew(false)}>
New&nbsp;route
</Button>
{/if}
<div class="min-h-[41px]">
{#if $userStore?.is_admin || $userStore?.is_super_admin}
<Button size="md" startIcon={{ icon: Plus }} on:click={() => routeEditor.openNew(false)}>
New&nbsp;route
</Button>
{/if}
</div>
</PageHeader>
<div class="w-full h-full flex flex-col">
<div class="w-full pb-4 pt-6">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Schedules"
tooltip="Trigger Scripts and Flows according to a cron schedule"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
/>

<CenteredPage>
<CenteredPage useScroll>
<PageHeader title="SQS triggers" tooltip="SQS trigger">
<Button size="md" startIcon={{ icon: Plus }} on:click={() => sqsTriggerEditor.openNew(false)}>
New&nbsp;SQS trigger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Variables"
tooltip="Save and permission strings to be reused in Scripts and Flows."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
/>

<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="WebSocket triggers"
tooltip="Windmill can listen to WebSocket events and trigger scripts or flows based on them."
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/(root)/(logged)/workers/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@
<p>Page not available for operators</p>
</div>
{:else}
<CenteredPage>
<CenteredPage useScroll>
<PageHeader
title="Workers"
tooltip="The workers are the dutiful servants that execute the jobs."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@
<S3FilePicker bind:this={s3FileViewer} readOnlyMode={false} fromWorkspaceSettings={true} />
</Portal>

<CenteredPage>
<CenteredPage useScroll>
{#if $userStore?.is_admin || $superadmin}
<PageHeader title="Workspace settings: {$workspaceStore}"
>{#if $superadmin}
Expand Down