working sliding animation between tabs

This commit is contained in:
Keviin Åberg Kultalahti 2021-04-15 14:42:39 +02:00
parent 6960966cac
commit 7f05d74355
3 changed files with 70 additions and 12 deletions

View File

@ -1,13 +1,26 @@
<script> <script>
import { getContext } from 'svelte' import { getContext, onMount } from 'svelte'
import Portal from "svelte-portal" import Portal from "svelte-portal"
export let title export let title
export let icon = ''; export let icon = '';
const selected = getContext('tab') const selected = getContext('tab')
let tab;
let tabInfo
const setTabInfo = () => {
tabInfo = tab.getBoundingClientRect()
if ($selected.title === title) {
$selected.info = tabInfo
}
}
onMount(() => {
setTabInfo()
})
</script> </script>
<div on:click={() => $selected = title } class:is-selected={$selected === title} class="spectrum-Tabs-item" tabindex="0"> <div bind:this={tab} on:click={() => $selected = {...$selected, title, info: tab.getBoundingClientRect()} } class:is-selected={$selected.title === title} class="spectrum-Tabs-item" tabindex="0">
{#if icon} {#if icon}
<svg class="spectrum-Icon spectrum-Icon--sizeM" focusable="false" aria-hidden="true" aria-label="Folder"> <svg class="spectrum-Icon spectrum-Icon--sizeM" focusable="false" aria-hidden="true" aria-label="Folder">
<use xlink:href="#spectrum-icon-18-{icon}" /> <use xlink:href="#spectrum-icon-18-{icon}" />
@ -15,8 +28,8 @@
{/if} {/if}
<span class="spectrum-Tabs-itemLabel">{title}</span> <span class="spectrum-Tabs-itemLabel">{title}</span>
</div> </div>
{#if $selected === title} {#if $selected.title === title}
<Portal target=".spectrum-Tabs-content"> <Portal target=".spectrum-Tabs-content-{$selected.id}">
<slot /> <slot />
</Portal> </Portal>
{/if} {/if}

View File

@ -1,23 +1,69 @@
<script> <script>
import "@spectrum-css/tabs/dist/index-vars.css" import "@spectrum-css/tabs/dist/index-vars.css"
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
import { setContext } from 'svelte' import { onMount, setContext } from 'svelte'
export let selected; export let selected;
export let vertical = false export let vertical = false
let _id = id()
const tab = writable(selected) const tab = writable({title: selected, id: _id})
setContext('tab', tab) setContext('tab', tab)
$: selected = $tab
let container;
$: selected = $tab.title
let top, left, width, height;
$: calculateIndicatorLength($tab)
$: calculateIndicatorOffset($tab)
function calculateIndicatorLength() {
if (!vertical) {
width = $tab.info?.width + 24 + 'px'
height = $tab.info?.height
} else {
height = $tab.info?.height + 4 + 'px'
width = $tab.info?.width
}
}
function calculateIndicatorOffset() {
console.log(container?.getBoundingClientRect())
if (!vertical) {
left = $tab.info?.left - container?.getBoundingClientRect().left - 12 + 'px'
top = $tab.info?.top
} else {
top = $tab.info?.top - container?.getBoundingClientRect().top + 'px'
left = $tab.info?.left
}
}
onMount(() => {
calculateIndicatorLength()
calculateIndicatorOffset()
})
function id() {
return (
"_" +
Math.random()
.toString(36)
.substr(2, 9)
)
}
</script> </script>
<div class="spectrum-Tabs spectrum-Tabs--{vertical ? 'vertical' : 'horizontal'}"> <div bind:this={container} class="selected-border spectrum-Tabs spectrum-Tabs--{vertical ? 'vertical' : 'horizontal'}">
<slot /> <slot />
<div class="spectrum-Tabs-selectionIndicator indicator-transition" style="width: {width}; height: {height}; left: {left}; top: {top};"></div>
</div> </div>
<div class="spectrum-Tabs-content" /> <div class="spectrum-Tabs-content spectrum-Tabs-content-{_id}" />
<style> <style>
.spectrum-Tabs-content { .spectrum-Tabs-content {
margin-top: var(--spectrum-global-dimension-static-size-150); margin-top: var(--spectrum-global-dimension-static-size-150);
} }
.indicator-transition {
transition: all 200ms
}
</style> </style>

View File

@ -3,7 +3,7 @@
import AppList from "components/start/AppList.svelte" import AppList from "components/start/AppList.svelte"
import { get } from "builderStore/api" import { get } from "builderStore/api"
import CreateAppModal from "components/start/CreateAppModal.svelte" import CreateAppModal from "components/start/CreateAppModal.svelte"
import { Button, Heading, Modal, Spacer, Tabs, Tab } from "@budibase/bbui" import { Button, Heading, Modal, Spacer, Tabs, Tab, Divider } from "@budibase/bbui"
import TemplateList from "components/start/TemplateList.svelte" import TemplateList from "components/start/TemplateList.svelte"
import analytics from "analytics" import analytics from "analytics"
import Banner from "/assets/orange-landscape.png" import Banner from "/assets/orange-landscape.png"
@ -75,7 +75,6 @@
<!-- <TemplateList onSelect={selectTemplate} /> --> <!-- <TemplateList onSelect={selectTemplate} /> -->
<AppList /> <AppList />
</div>
<Modal bind:this={modal} padding={false} width="600px" on:hide={closeModal}> <Modal bind:this={modal} padding={false} width="600px" on:hide={closeModal}>
<CreateAppModal {hasKey} {template} /> <CreateAppModal {hasKey} {template} />