Added support for dropdowns
This commit is contained in:
parent
ecbe472acc
commit
703b12428b
3 changed files with 150 additions and 0 deletions
frontend/src
86
frontend/src/components/Dropdown.vue
Normal file
86
frontend/src/components/Dropdown.vue
Normal file
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<div class="dropdown">
|
||||
<button class="dropdown__button" @click="show">
|
||||
<slot name="button" />
|
||||
</button>
|
||||
|
||||
<div class="dropdown__container" ref="container">
|
||||
<div class="dropdown__content">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
computed: {
|
||||
container() {
|
||||
return this.$refs.container as HTMLElement;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
show() {
|
||||
this.container.classList.add('show');
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/common.scss" as *;
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
&__button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: var(--color-hover);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__container {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
|
||||
&.show {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
min-width: 10rem;
|
||||
display: flex;
|
||||
background-color: var(--color-background);
|
||||
border: 1px solid var(--color-border);
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.5);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.25rem;
|
||||
flex-direction: column;
|
||||
animation: dropdown 0.25s ease-out;
|
||||
}
|
||||
|
||||
@keyframes dropdown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.5rem);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
48
frontend/src/components/DropdownItem.vue
Normal file
48
frontend/src/components/DropdownItem.vue
Normal file
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<div class="dropdown__item" @click="$emit('click')">
|
||||
<div class="dropdown__item__icon">
|
||||
<slot name="icon" />
|
||||
</div>
|
||||
<div class="dropdown__item__text">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
emits: ['click'],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dropdown__item {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 0.5rem 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-hover);
|
||||
|
||||
:deep(a) {
|
||||
background-color: inherit;
|
||||
color: var(--color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
&__text {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
:deep(a) {
|
||||
flex: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
16
frontend/src/mixins/Dropdowns.vue
Normal file
16
frontend/src/mixins/Dropdowns.vue
Normal file
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts">
|
||||
export default {
|
||||
methods: {
|
||||
installDropdownHandler() {
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!(event.target as HTMLElement).closest('.dropdown__button')) {
|
||||
document.querySelectorAll('.dropdown__container').forEach((content) => {
|
||||
content.classList.remove('show');
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Add table
Reference in a new issue