new popover component in the breadcrumbs menu

This commit is contained in:
Kiril Videlov 2023-03-03 00:36:08 +01:00
parent c087e57158
commit 35b7cd780b
4 changed files with 98 additions and 2 deletions

View File

@ -5,9 +5,11 @@
import { getContext } from 'svelte';
import type { Writable } from 'svelte/store';
import { IconHome, IconChevronRight } from '@tabler/icons-svelte';
import Popover from '$lib/components/Popover';
let project: Writable<Project | null | undefined> = getContext('project');
let session: Writable<Session | null | undefined> = getContext('session');
let projects: Writable<any> = getContext('projects');
</script>
<div class="flex flex-row items-center space-x-1 bg-zinc-900 text-zinc-400 h-8">
@ -16,7 +18,28 @@
</a>
{#if $project}
<IconChevronRight class="w-5 h-5 text-zinc-700" />
<a class="hover:text-zinc-200" href="/projects/{$project.id}">{$project.title}</a>
<div class="flex flex-col">
<Popover>
<div slot="button">
{$project.title}
</div>
<div class="flex flex-col space-y-2">
<ul class="flex flex-col space-y-2">
{#each $projects || [] as project}
<a
href="/projects/{project.id}"
class="p-2 rounded hover:bg-zinc-700 cursor-pointer truncate"
>
{project.title}</a
>
{/each}
</ul>
<span class="w-full border-t border-zinc-700" />
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="p-2 rounded hover:bg-zinc-700 cursor-pointer">Add project...</div>
</div>
</Popover>
</div>
{/if}
{#if $project && $session}
<IconChevronRight class="w-5 h-5 text-zinc-700" />

View File

@ -0,0 +1,69 @@
<script lang="ts">
import { slide } from 'svelte/transition';
import { cubicOut } from 'svelte/easing';
let showPopover: boolean = false;
let anchor: HTMLButtonElement | undefined = undefined;
let bottom: number;
let left: number;
const initPosition = () =>
({ bottom, left } = anchor?.getBoundingClientRect() ?? { bottom: 0, left: 0 });
$: anchor, initPosition();
function clickOutside(element: HTMLElement, callback: () => void) {
const handleClick = (event: Event) => {
const target = event.target as HTMLElement;
if (!target) {
return;
}
if (!element.contains(target)) {
callback();
}
};
document.body.addEventListener('click', handleClick);
return {
update(newCallback: () => void) {
callback = newCallback;
},
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
}
</script>
<svelte:window on:resize={initPosition} on:keydown={() => (showPopover = false)} />
<div use:clickOutside={() => (showPopover = false)}>
<button on:click={() => (showPopover = !showPopover)} bind:this={anchor} class="text-zinc-50"
><slot name="button" /></button
>
<!-- svelte-ignore a11y-click-events-have-key-events -->
{#if showPopover}
<div
role="dialog"
aria-labelledby="Title"
aria-describedby="Description"
aria-orientation="vertical"
transition:slide={{ duration: 150, easing: cubicOut }}
on:click|stopPropagation
class="wrapper z-50 bg-zinc-800 border border-zinc-700 text-zinc-50 rounded shadow-2xl min-w-[180px] max-w-[512px]"
style="--popover-top: {`${bottom}px`}; --popover-left: {`${left}px`}"
>
<slot />
</div>
{/if}
</div>
<style>
.wrapper {
position: absolute;
top: calc(var(--popover-top) + 4px);
left: var(--popover-left);
}
</style>

View File

@ -0,0 +1,3 @@
import { default as Popover } from './Popover.svelte';
export default Popover;

View File

@ -9,10 +9,11 @@
import Breadcrumbs from '$lib/components/Breadcrumbs.svelte';
export let data: LayoutData;
const { user, posthog } = data;
const { user, posthog, projects } = data;
setContext('project', writable(null));
setContext('session', writable(null));
setContext('projects', projects);
user.subscribe(posthog.identify);
</script>