aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Layout
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-04-21 19:51:49 -0700
committerFuwn <[email protected]>2024-04-21 19:51:49 -0700
commiteebeaa378d49cc8adb597d00fd05bcc314779888 (patch)
treed2862e4f952525280a341e44810c261548a07a3f /src/lib/Layout
parentrefactor(TextTransition): move to Layout (diff)
downloaddue.moe-eebeaa378d49cc8adb597d00fd05bcc314779888.tar.xz
due.moe-eebeaa378d49cc8adb597d00fd05bcc314779888.zip
refactor(lib): move componenets to modules
Diffstat (limited to 'src/lib/Layout')
-rw-r--r--src/lib/Layout/Dropdown.svelte127
-rw-r--r--src/lib/Layout/Popup.svelte59
2 files changed, 186 insertions, 0 deletions
diff --git a/src/lib/Layout/Dropdown.svelte b/src/lib/Layout/Dropdown.svelte
new file mode 100644
index 00000000..dd48af45
--- /dev/null
+++ b/src/lib/Layout/Dropdown.svelte
@@ -0,0 +1,127 @@
+<script lang="ts">
+ interface Item {
+ name: string;
+ url: string;
+ onClick?: () => void;
+ preventDefault?: boolean;
+ }
+
+ export let items: Item[] = [];
+ export let title: string | undefined = undefined;
+ export let header = true;
+ export let center = false;
+
+ let open = false;
+
+ const handleClickOutside = (event: any) => {
+ if (!event.target.closest('.dropdown')) open = false;
+ };
+</script>
+
+<svelte:window on:click={handleClickOutside} />
+
+<div
+ class="dropdown"
+ id="dropdown"
+ style={`--dropdown-left: ${center ? '50%' : 'unset'}; --dropdown-transform: ${
+ center ? 'translateX(-50%)' : 'unset'
+ };`}
+>
+ <span
+ class={`${header ? 'header-item' : ''} dropdown-toggle`}
+ id="dropdown-toggle"
+ on:click|preventDefault={() => (open = !open)}
+ on:keydown={() => {}}
+ role="button"
+ tabindex="0"
+ >
+ {#if title}
+ {title}
+ {:else}
+ <slot name="title" />
+ {/if}
+ </span>
+
+ <div class={`dropdown-content card card-small ${open ? 'dropdown-open' : ''}`}>
+ {#each items as item}
+ <a
+ href={item.url}
+ class="header-item"
+ on:click={(e) => {
+ if (item.preventDefault) e.preventDefault();
+ if (item.onClick) item.onClick();
+ }}
+ >
+ {item.name}
+ </a>
+ {/each}
+ </div>
+</div>
+
+<style lang="scss">
+ a {
+ color: var(--base06);
+ }
+
+ .header-item {
+ margin: 0 0.5rem;
+ }
+
+ .header-item:hover {
+ text-decoration: none;
+ }
+
+ .header-item:active {
+ outline: none;
+ }
+
+ .dropdown {
+ position: relative;
+ display: inline-block;
+ }
+
+ .dropdown-content {
+ display: block;
+ position: absolute;
+ min-width: max-content;
+ padding: 0.5em 0;
+ opacity: 0;
+ transform: translateY(-20px);
+ visibility: hidden;
+ $delay: 0.25s;
+ transition: opacity $delay ease, transform $delay ease, visibility 0s linear $delay;
+ left: var(--dropdown-left);
+ transform: var(--dropdown-transform);
+ z-index: 1;
+ }
+
+ .dropdown-open {
+ opacity: 1;
+ transform: translateY(0);
+ visibility: visible;
+ transition-delay: 0s, 0s, 0s;
+ left: var(--dropdown-left);
+ transform: var(--dropdown-transform);
+ }
+
+ .dropdown:hover .dropdown-content {
+ opacity: 1;
+ transform: translateY(0);
+ visibility: visible;
+ transition-delay: 0s, 0s, 0s;
+ left: var(--dropdown-left);
+ transform: var(--dropdown-transform);
+ }
+
+ .dropdown-content a {
+ padding: 0.5em 0.75em;
+ text-decoration: none;
+ display: block;
+ }
+
+ .dropdown-content a:hover {
+ border-radius: 8px;
+ backdrop-filter: blur(160px);
+ background-color: var(--base01);
+ }
+</style>
diff --git a/src/lib/Layout/Popup.svelte b/src/lib/Layout/Popup.svelte
new file mode 100644
index 00000000..be55adf0
--- /dev/null
+++ b/src/lib/Layout/Popup.svelte
@@ -0,0 +1,59 @@
+<script lang="ts">
+ import { browser } from '$app/environment';
+ import { onMount } from 'svelte';
+
+ export let onLeave = () => {
+ return;
+ };
+ export let card = true;
+ export let smallCard = false;
+ export let fullscreen = false;
+ export let show = true;
+ export let locked = false;
+ export let center = false;
+
+ const handleClickOutside = (event: any) => {
+ if (!locked && event.target.classList.contains('popup')) {
+ show = false;
+
+ onLeave();
+ }
+ };
+
+ onMount(() => {
+ if (browser) document.body.style.overflow = 'auto';
+ });
+
+ $: {
+ if (browser) {
+ document.body.style.overflow = 'auto';
+
+ if (show) document.body.style.overflow = 'hidden';
+ else document.body.style.overflow = 'auto';
+ }
+ }
+</script>
+
+<svelte:window on:click={handleClickOutside} />
+
+{#if show}
+ <div class={`popup ${fullscreen ? 'popup-fullscreen' : ''}`}>
+ <span
+ class={`${card ? `card ${smallCard ? 'card-small' : ''}` : ''} ${center ? 'centered' : ''}`}
+ >
+ <slot />
+ </span>
+ </div>
+{/if}
+
+<style>
+ .popup {
+ z-index: 3;
+ }
+
+ .centered {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+</style>