mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
now select dropdown is fixed
This commit is contained in:
parent
1b55d2d632
commit
7965ae1828
5 changed files with 87 additions and 18 deletions
|
|
@ -219,9 +219,15 @@ body {
|
|||
}
|
||||
|
||||
.select-dropdown-container {
|
||||
@apply z-[20] absolute h-fit max-h-[200px] overflow-x-hidden overflow-y-auto flex-col w-fit mt-2;
|
||||
@apply flex fixed h-full max-h-[200px] overflow-x-hidden overflow-y-auto flex-col w-fit mt-2;
|
||||
}
|
||||
|
||||
.open.select-dropdown-container {
|
||||
@apply z-[20] opacity-100;
|
||||
}
|
||||
.close.select-dropdown-container {
|
||||
@apply -z-10 opacity-0 pointer-events-none;
|
||||
}
|
||||
.select-dropdown-btn {
|
||||
@apply border-b border-l border-r border-gray-300 hover:brightness-90 bg-white text-gray-700 my-0 relative px-6 py-2 text-center align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-normal dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -5,7 +5,7 @@ import Container from "@components/Widget/Container.vue";
|
|||
import Header from "@components/Forms/Header/Field.vue";
|
||||
import ErrorField from "@components/Forms/Error/Field.vue";
|
||||
|
||||
/**
|
||||
/**
|
||||
@name Forms/Field/Select.vue
|
||||
@description This component is used to create a complete select field input with error handling and label.
|
||||
We can be more precise by adding values that need to be selected to be valid.
|
||||
|
|
@ -151,10 +151,69 @@ const select = reactive({
|
|||
|
||||
const selectBtn = ref();
|
||||
const selectWidth = ref("");
|
||||
const selectDropdown = ref();
|
||||
|
||||
// EVENTS
|
||||
function toggleSelect() {
|
||||
select.isOpen = select.isOpen ? false : true;
|
||||
// Position dropdown relative to btn on open on fixed position
|
||||
if (select.isOpen) {
|
||||
const selectBtnRect = selectBtn.value.getBoundingClientRect();
|
||||
const selectDropdownRect = selectDropdown.value.getBoundingClientRect();
|
||||
|
||||
// We need to take care of parent padding and margin that will affect dropdown position but aren't calculate in rect
|
||||
const parents = [selectBtn.value.parentElement];
|
||||
let isParent = selectBtn.value.parentElement ? true : false;
|
||||
while (isParent) {
|
||||
parents.push(parents[parents.length - 1].parentElement);
|
||||
isParent = parents[parents.length - 1].parentElement ? true : false;
|
||||
}
|
||||
|
||||
let noRectParentHeight = 0;
|
||||
for (let i = 0; i < parents.length; i++) {
|
||||
try {
|
||||
noRectParentHeight += +window
|
||||
.getComputedStyle(parents[i], null)
|
||||
.getPropertyValue("padding-top")
|
||||
.replace("px", "");
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
noRectParentHeight += +window
|
||||
.getComputedStyle(parents[i], null)
|
||||
.getPropertyValue("margin-top")
|
||||
.replace("px", "");
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// If dropdown is too close to bottom, we need to drop it up
|
||||
const canDropBeDown =
|
||||
selectBtnRect.top + selectDropdownRect.height + 20 < window.innerHeight
|
||||
? true
|
||||
: false;
|
||||
|
||||
if (canDropBeDown) {
|
||||
selectDropdown.value.style.top = `${
|
||||
window.scrollY +
|
||||
selectBtnRect.bottom +
|
||||
selectBtnRect.height * 2 -
|
||||
selectDropdownRect.height -
|
||||
noRectParentHeight +
|
||||
16
|
||||
}px`;
|
||||
}
|
||||
|
||||
if (!canDropBeDown) {
|
||||
selectDropdown.value.style.top = `${
|
||||
window.scrollY +
|
||||
selectBtnRect.top +
|
||||
selectBtnRect.height * 2 -
|
||||
selectDropdownRect.height * 2 -
|
||||
noRectParentHeight -
|
||||
24
|
||||
}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeSelect() {
|
||||
|
|
@ -177,15 +236,6 @@ function changeValue(newValue) {
|
|||
return newValue;
|
||||
}
|
||||
|
||||
// Close select dropdown when clicked outside element
|
||||
watch(select, () => {
|
||||
if (select.isOpen) {
|
||||
document.querySelector("body").addEventListener("click", closeOutside);
|
||||
} else {
|
||||
document.querySelector("body").removeEventListener("click", closeOutside);
|
||||
}
|
||||
});
|
||||
|
||||
// Close select when clicked outside logic
|
||||
function closeOutside(e) {
|
||||
try {
|
||||
|
|
@ -197,6 +247,17 @@ function closeOutside(e) {
|
|||
}
|
||||
}
|
||||
|
||||
// Close select dropdown when clicked outside element
|
||||
watch(select, () => {
|
||||
if (select.isOpen) {
|
||||
window.addEventListener("click", closeOutside);
|
||||
window.addEventListener("scroll", closeSelect, true);
|
||||
} else {
|
||||
window.removeEventListener("click", closeOutside);
|
||||
window.removeEventListener("scroll", closeSelect, true);
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
selectWidth.value = `${selectBtn.value.clientWidth}px`;
|
||||
window.addEventListener("resize", () => {
|
||||
|
|
@ -279,15 +340,17 @@ const emits = defineEmits(["inp"]);
|
|||
</button>
|
||||
<!-- dropdown-->
|
||||
<div
|
||||
:aria-hidden="select.isOpen ? 'false' : 'true'"
|
||||
ref="selectDropdown"
|
||||
role="radiogroup"
|
||||
:style="{ width: selectWidth }"
|
||||
:id="`${props.id}-custom`"
|
||||
:class="[select.isOpen ? 'flex' : 'hidden']"
|
||||
:class="[select.isOpen ? 'open' : 'close']"
|
||||
class="select-dropdown-container"
|
||||
:aria-description="$t('inp_select_dropdown_desc')"
|
||||
>
|
||||
<button
|
||||
:tabindex="contentIndex"
|
||||
:tabindex="select.isOpen ? props.tabId : '-1'"
|
||||
v-for="(value, id) in props.values"
|
||||
role="radio"
|
||||
@click.prevent="$emit('inp', changeValue(value))"
|
||||
|
|
@ -312,7 +375,6 @@ const emits = defineEmits(["inp"]);
|
|||
</button>
|
||||
</div>
|
||||
<ErrorField :isValid="select.isValid" :isValue="true" />
|
||||
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end custom-->
|
||||
|
|
|
|||
|
|
@ -77,7 +77,10 @@ const props = defineProps({
|
|||
<Title type="card" :title="plugin.name" />
|
||||
<Subtitle type="card" :subtitle="plugin.description" />
|
||||
|
||||
<Container class="grid grid-cols-12 w-full">
|
||||
<Container
|
||||
style="max-height: 300px; overflow: auto"
|
||||
class="grid grid-cols-12 w-full relative"
|
||||
>
|
||||
<template v-for="(setting, index) in plugin.settings" :key="index">
|
||||
<Checkbox v-if="setting.inpType === 'checkbox'" v-bind="setting" />
|
||||
<Select v-if="setting.inpType === 'select'" v-bind="setting" />
|
||||
|
|
|
|||
|
|
@ -72,9 +72,7 @@ function showPopover() {
|
|||
|
||||
// Position popover relative to btn
|
||||
const popoverBtnRect = popoverBtn.value.getBoundingClientRect();
|
||||
const popoverContainerRect = popoverContainer.value.getBoundingClientRect();
|
||||
|
||||
// Get current window scroll positio
|
||||
popoverContainer.value.style.right = `${
|
||||
window.innerWidth - popoverBtnRect.left - popoverBtnRect.width
|
||||
}px`;
|
||||
|
|
|
|||
Loading…
Reference in a new issue