Merge pull request #13724 from Budibase/tab-dynamic-resizing
Observe size changes in tabs
This commit is contained in:
commit
a2f0049ee4
3 changed files with 48 additions and 60 deletions
|
@ -1,51 +1,54 @@
|
|||
<script>
|
||||
import { getContext, onMount, createEventDispatcher } from "svelte"
|
||||
import { getContext, onDestroy } from "svelte"
|
||||
import Portal from "svelte-portal"
|
||||
|
||||
export let title
|
||||
export let icon = ""
|
||||
export let id
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let selected = getContext("tab")
|
||||
let tab_internal
|
||||
let tabInfo
|
||||
let observer
|
||||
let ref
|
||||
|
||||
$: isSelected = $selected.title === title
|
||||
$: {
|
||||
if (isSelected && ref) {
|
||||
observe()
|
||||
} else {
|
||||
stopObserving()
|
||||
}
|
||||
}
|
||||
|
||||
const setTabInfo = () => {
|
||||
// If the tabs are being rendered inside a component which uses
|
||||
// a svelte transition to enter, then this initial getBoundingClientRect
|
||||
// will return an incorrect position.
|
||||
// We just need to get this off the main thread to fix this, by using
|
||||
// a 0ms timeout.
|
||||
setTimeout(() => {
|
||||
tabInfo = tab_internal?.getBoundingClientRect()
|
||||
if (tabInfo && $selected.title === title) {
|
||||
const tabInfo = ref?.getBoundingClientRect()
|
||||
if (tabInfo) {
|
||||
$selected.info = tabInfo
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
setTabInfo()
|
||||
})
|
||||
|
||||
//Ensure that the underline is in the correct location
|
||||
$: {
|
||||
if ($selected.title === title && tab_internal) {
|
||||
if ($selected.info?.left !== tab_internal.getBoundingClientRect().left) {
|
||||
setTabInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onClick = () => {
|
||||
$selected = {
|
||||
...$selected,
|
||||
title,
|
||||
info: tab_internal.getBoundingClientRect(),
|
||||
info: ref.getBoundingClientRect(),
|
||||
}
|
||||
dispatch("click")
|
||||
}
|
||||
|
||||
const observe = () => {
|
||||
if (!observer) {
|
||||
observer = new ResizeObserver(setTabInfo)
|
||||
observer.observe(ref)
|
||||
}
|
||||
}
|
||||
|
||||
const stopObserving = () => {
|
||||
if (observer) {
|
||||
observer.unobserve(ref)
|
||||
observer = null
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(stopObserving)
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
|
@ -53,11 +56,12 @@
|
|||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<div
|
||||
{id}
|
||||
bind:this={tab_internal}
|
||||
bind:this={ref}
|
||||
on:click={onClick}
|
||||
class:is-selected={$selected.title === title}
|
||||
on:click
|
||||
class="spectrum-Tabs-item"
|
||||
class:emphasized={$selected.title === title && $selected.emphasized}
|
||||
class:is-selected={isSelected}
|
||||
class:emphasized={isSelected && $selected.emphasized}
|
||||
tabindex="0"
|
||||
>
|
||||
{#if icon}
|
||||
|
@ -72,7 +76,8 @@
|
|||
{/if}
|
||||
<span class="spectrum-Tabs-itemLabel">{title}</span>
|
||||
</div>
|
||||
{#if $selected.title === title}
|
||||
|
||||
{#if isSelected}
|
||||
<Portal target=".spectrum-Tabs-content-{$selected.id}">
|
||||
<slot />
|
||||
</Portal>
|
||||
|
|
|
@ -105,10 +105,6 @@
|
|||
}
|
||||
|
||||
onMount(async () => {
|
||||
document.fonts.onloadingdone = e => {
|
||||
builderStore.loadFonts(e.fontfaces)
|
||||
}
|
||||
|
||||
if (!hasSynced && application) {
|
||||
try {
|
||||
await API.syncApp(application)
|
||||
|
@ -149,7 +145,6 @@
|
|||
/>
|
||||
</span>
|
||||
<Tabs {selected} size="M">
|
||||
{#key $builderStore?.fonts}
|
||||
{#each $layout.children as { path, title }}
|
||||
<TourWrap stepKeys={[`builder-${title}-section`]}>
|
||||
<Tab
|
||||
|
@ -161,7 +156,6 @@
|
|||
/>
|
||||
</TourWrap>
|
||||
{/each}
|
||||
{/key}
|
||||
</Tabs>
|
||||
</div>
|
||||
<div class="topcenternav">
|
||||
|
|
|
@ -14,7 +14,6 @@ export const INITIAL_BUILDER_STATE = {
|
|||
tourKey: null,
|
||||
tourStepKey: null,
|
||||
hoveredComponentId: null,
|
||||
fonts: null,
|
||||
}
|
||||
|
||||
export class BuilderStore extends BudiStore {
|
||||
|
@ -37,16 +36,6 @@ export class BuilderStore extends BudiStore {
|
|||
this.websocket
|
||||
}
|
||||
|
||||
loadFonts(fontFaces) {
|
||||
const ff = fontFaces.map(
|
||||
fontFace => `${fontFace.family}-${fontFace.weight}`
|
||||
)
|
||||
this.update(state => ({
|
||||
...state,
|
||||
fonts: [...(state.fonts || []), ...ff],
|
||||
}))
|
||||
}
|
||||
|
||||
init(app) {
|
||||
if (!app?.appId) {
|
||||
console.error("BuilderStore: No appId supplied for websocket")
|
||||
|
|
Loading…
Reference in a new issue