-
Notifications
You must be signed in to change notification settings - Fork 268
/
DropdownMenu.svelte
60 lines (50 loc) · 1.77 KB
/
DropdownMenu.svelte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<script lang="ts">
import { faEllipsisVertical } from '@fortawesome/free-solid-svg-icons';
import type { IconDefinition } from '@fortawesome/free-solid-svg-icons';
import Fa from 'svelte-fa';
import DropDownMenuItems from './DropDownMenuItems.svelte';
export let icon: IconDefinition = faEllipsisVertical;
export let ariaLabel = 'drop-down-menu';
export let shownAsMenuActionItem = false;
// Show and hide the menu using clickOutside
let showMenu = false;
// If we touch outside the window, hide the menu
let outsideWindow: HTMLButtonElement;
// If we hit ESC while the menu is open, close it
function handleEscape({ key }: any) {
if (key === 'Escape') {
showMenu = false;
}
}
let clientY: number;
function toggleMenu() {
showMenu = !showMenu;
}
// If we click outside the menu, close the menu
function onWindowClick(e: any) {
showMenu = outsideWindow.contains(e.target);
}
</script>
<!-- Required in order for Svelte to track all key presses and if you pressed "ESC" -->
<svelte:window on:keyup="{handleEscape}" on:click="{onWindowClick}" />
<!-- Create a "kebab" menu for additional actions. -->
<div class="relative inline-block text-left">
<!-- Button for the dropdown menu -->
<button
on:click="{e => {
// keep track of the cursor position
clientY = e.clientY;
toggleMenu();
}}"
aria-label="{ariaLabel}"
bind:this="{outsideWindow}"
class="text-gray-400 {shownAsMenuActionItem
? 'bg-charcoal-800 px-3'
: 'hover:bg-charcoal-800 mr-2'} hover:text-purple-400 font-medium rounded-md inline-flex items-center px-2 py-2 text-center">
<Fa class="h-4 w-4" icon="{icon}" />
</button>
<!-- Dropdown menu for all other actions -->
{#if showMenu}
<DropDownMenuItems clientY="{clientY}"><slot /></DropDownMenuItems>
{/if}
</div>