summaryrefslogtreecommitdiffstats
path: root/apps/web-shared/src/components/menu/menu.svelte
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-06-01 22:10:32 +0200
committerivarlovlie <git@ivarlovlie.no>2022-06-01 22:10:32 +0200
commita640703f2da8815dc26ad1600a6f206be1624379 (patch)
treedbda195fb5783d16487e557e06471cf848b75427 /apps/web-shared/src/components/menu/menu.svelte
downloadgreatoffice-a640703f2da8815dc26ad1600a6f206be1624379.tar.xz
greatoffice-a640703f2da8815dc26ad1600a6f206be1624379.zip
feat: Initial after clean slate
Diffstat (limited to 'apps/web-shared/src/components/menu/menu.svelte')
-rw-r--r--apps/web-shared/src/components/menu/menu.svelte54
1 files changed, 54 insertions, 0 deletions
diff --git a/apps/web-shared/src/components/menu/menu.svelte b/apps/web-shared/src/components/menu/menu.svelte
new file mode 100644
index 0000000..33b1160
--- /dev/null
+++ b/apps/web-shared/src/components/menu/menu.svelte
@@ -0,0 +1,54 @@
+<script lang="ts">
+ import {random_string} from "$shared/lib/helpers";
+
+ export let id = "__menu_" + random_string(3);
+ export let trigger: HTMLElement;
+ export let show = false;
+
+ let windowInnerWidth = 0;
+ let windowInnerHeight = 0;
+ let menu: HTMLMenuElement;
+
+ $: if (show && menu && trigger) {
+ const
+ selectedTriggerPosition = trigger.getBoundingClientRect(),
+ menuOnTop = (windowInnerHeight - selectedTriggerPosition.bottom) < selectedTriggerPosition.top,
+ left = selectedTriggerPosition.left,
+ right = (windowInnerWidth - selectedTriggerPosition.right),
+ isRight = (windowInnerWidth < selectedTriggerPosition.left + menu.offsetWidth),
+ vertical = menuOnTop
+ ? "bottom: " + (windowInnerHeight - selectedTriggerPosition.top) + "px;"
+ : "top: " + selectedTriggerPosition.bottom + "px;";
+
+ let horizontal = isRight ? "right: " + right + "px;" : "left: " + left + "px;";
+
+ // check right position is correct -> otherwise set left to 0
+ if (isRight && (right + menu.offsetWidth) > windowInnerWidth) horizontal = ("left: " + (windowInnerWidth - menu.offsetWidth) / 2 + "px;");
+ const maxHeight = menuOnTop ? selectedTriggerPosition.top - 20 : windowInnerHeight - selectedTriggerPosition.bottom - 20;
+ menu.setAttribute("style", horizontal + vertical + "max-height:" + Math.floor(maxHeight) + "px;");
+ }
+
+ function on_window_click(event) {
+ if (!event.target.closest("#" + id) && !event.target.closest("[aria-controls='" + id + "']")) show = false;
+ }
+
+ function on_window_touchend(event) {
+ if (!event.target.closest("#" + id) && !event.target.closest("[aria-controls='" + id + "']")) show = false;
+ }
+</script>
+
+<svelte:window
+ on:click={on_window_click}
+ on:touchend={on_window_touchend}
+ bind:innerWidth={windowInnerWidth}
+ bind:innerHeight={windowInnerHeight}
+/>
+
+<menu class="menu"
+ id="{id}"
+ bind:this={menu}
+ class:menu--is-visible={show}
+ aria-expanded="{show}"
+ aria-haspopup="true">
+ <slot name="options"/>
+</menu>