feat!: added selection component
mellbacon committed
Jul 12, 2023 at 18:53 UTC
e57e1e8bc403ef1b9c74e4fa529ccb3cb050b99b
1 file changed
+134
src/lib/utility/Select.svelte
new
+134
@@ -0,0 +1,134 @@
1
+<script lang="ts">
2
+ import { ChevronDown } from "carbon-icons-svelte";
3
+ import { afterUpdate, createEventDispatcher } from "svelte";
4
+ const dispatch = createEventDispatcher();
5
+
6
+ export let label: string;
7
+ export let items = [
8
+ {id: 0, name: "No items listed"},
9
+ ];
10
+
11
+ let open = false;
12
+ let button;
13
+ let list;
14
+ export let selected = items[0].name;
15
+ const default_value = selected;
16
+
17
+ function handleSelect(name) {
18
+ selected = name;
19
+ dispatch("select", {selection: name});
20
+ }
21
+
22
+ afterUpdate(() => {
23
+ if (open && list) {
24
+ const { _ , width } = button.getBoundingClientRect();
25
+ list.style.width = `${width}px`;
26
+ }
27
+ })
28
+
29
+ $: selected = items[0].name;
30
+</script>
31
+
32
+<svelte:window on:click={(e) => {
33
+ if (open && !button.contains(e.target)) {
34
+ open = false;
35
+ }
36
+}}></svelte:window>
37
+
38
+<div class="select">
39
+ <label for="selectButton" class="label">{label}:</label>
40
+ <div class="select-list" class:open>
41
+ <button name="selectButton" bind:this={button} on:click={() => {open = !open}}>
42
+ <span>{selected}</span>
43
+ <span class="arrow"><ChevronDown></ChevronDown></span>
44
+ </button>
45
+ {#if open}
46
+ <div bind:this={list} class="item-list">
47
+ {#each items as item}
48
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
49
+ <div id={item.id.toString()} class="item" on:click={() => {
50
+ handleSelect(item.name);
51
+ open = false;
52
+ }}>
53
+ {item.name}
54
+ {#if default_value === item.name}
55
+ <span class="default">default</span>
56
+ {/if}
57
+ </div>
58
+ {/each}
59
+ </div>
60
+ {/if}
61
+ </div>
62
+</div>
63
+
64
+<style lang="scss">
65
+ .select {
66
+ display: flex;
67
+ flex-direction: column;
68
+ align-items: flex-start;
69
+ justify-content: center;
70
+ margin: 10px 0;
71
+ }
72
+ .label {
73
+ font-size: 0.9rem;
74
+ }
75
+ .open {
76
+ .arrow {
77
+ transform: rotateZ(180deg) !important;
78
+ }
79
+ }
80
+ .select-list {
81
+ min-width: 7rem;
82
+ button {
83
+ color: white;
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ min-height: 2rem;
88
+ width: 100%;
89
+ background-color: #333;
90
+ padding: 0 20px;
91
+ span {
92
+ display: flex;
93
+ align-items: center;
94
+ &:nth-child(1) {
95
+ margin-right: 5px;
96
+ }
97
+ &.arrow {
98
+ transform: rotateZ(0);
99
+ transition: 0.2s;
100
+ margin-top: 3px;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ .item-list {
106
+ position: absolute;
107
+ border: 1px solid #333;
108
+ background-color: #1f1f1f;
109
+ max-height: 15rem;
110
+ overflow-y: overlay;
111
+ min-width: 20rem;
112
+ z-index: 1;
113
+ &::-webkit-scrollbar {
114
+ width: 12px;
115
+ }
116
+ &::-webkit-scrollbar-thumb {
117
+ background-color: #4c4c4c38;
118
+ }
119
+ .item {
120
+ display: flex;
121
+ align-items: center;
122
+ min-height: 2rem;
123
+ justify-content: space-between;
124
+ cursor: pointer;
125
+ padding: 0 20px;
126
+ &:hover {
127
+ background-color: #373737;
128
+ }
129
+ }
130
+ }
131
+ .default {
132
+ color: #8c8c8c;
133
+ }
134
+</style>
\ No newline at end of file