aboutsummaryrefslogtreecommitdiff
path: root/resources
diff options
context:
space:
mode:
authorMurtaza Sultani <sultani@data-quest.de>2025-08-07 16:38:29 +0200
committerMurtaza Sultani <sultani@data-quest.de>2025-08-07 16:38:29 +0200
commit327b4db7b6b025b839097814f358e3163749b3b0 (patch)
tree9335b6f4c0d0cc4537199536ac58bb121dda2131 /resources
parente22cd7ecb77a0133cc013b62e1d91be7ce6605ff (diff)
Resolve "Dynamische Positionierung für Dropdown-Komponente"
Closes #5736 Merge request studip/studip!4364
Diffstat (limited to 'resources')
-rw-r--r--resources/assets/stylesheets/scss/forum.scss37
-rw-r--r--resources/assets/stylesheets/studip.scss29
-rw-r--r--resources/vue/components/Dropdown.vue43
3 files changed, 66 insertions, 43 deletions
diff --git a/resources/assets/stylesheets/scss/forum.scss b/resources/assets/stylesheets/scss/forum.scss
index 9e1027c..0fab91c 100644
--- a/resources/assets/stylesheets/scss/forum.scss
+++ b/resources/assets/stylesheets/scss/forum.scss
@@ -542,8 +542,8 @@ $card-max-width: 300px;
z-index: 1;
.dropdown__content {
- right: auto;
- left: 0;
+ right: auto !important;
+ left: 0 !important;
}
}
@@ -761,34 +761,6 @@ $card-max-width: 300px;
}
}
- .user-avatar-dropdown {
- &__preview {
- background: none;
- border: none;
- padding: 0;
- cursor: pointer;
-
- &:hover,
- &:focus,
- &[aria-ppressed="true"] {
- position: relative;
- z-index: 1;
-
- img.user-profile {
- box-shadow: 0 2px 3px rgb(0 0 0 / 0.2);
- }
- }
-
- img.user-profile {
- width: 25px;
- height: auto;
- border-radius: 100%;
- border: 1.5px solid white;
- transition: all .4s ease-in-out;
- }
- }
- }
-
.forum-users-dropdown {
padding: 10px;
min-width: 200px;
@@ -1106,6 +1078,7 @@ $card-max-width: 300px;
.forum-subscriptions-dropdown {
text-align: left;
white-space: pre-wrap;
+ display: inline-flex;
.dropdown__items {
max-width: 300px;
@@ -1549,8 +1522,8 @@ $card-max-width: 300px;
.post-reactions-dialog {
.user-avatar-dropdown {
.dropdown__content {
- right: auto;
- left: 0;
+ right: auto !important;
+ left: 0 !important;
}
}
}
diff --git a/resources/assets/stylesheets/studip.scss b/resources/assets/stylesheets/studip.scss
index 284734c..f6c8e9e 100644
--- a/resources/assets/stylesheets/studip.scss
+++ b/resources/assets/stylesheets/studip.scss
@@ -890,6 +890,35 @@ input.allow-plaintext-toggle {
}
}
}
+
+.user-avatar-dropdown {
+ &__preview {
+ background: none;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ display: flex;
+
+ &:hover,
+ &:focus,
+ &[aria-ppressed="true"] {
+ position: relative;
+ z-index: 1;
+
+ img.user-profile {
+ box-shadow: 0 2px 3px rgb(0 0 0 / 0.2);
+ }
+ }
+
+ img.user-profile {
+ width: 25px;
+ height: auto;
+ border-radius: 100%;
+ border: 1.5px solid white;
+ transition: all .4s ease-in-out;
+ }
+ }
+}
/*
vue Transition:fade-down --start--
*/
diff --git a/resources/vue/components/Dropdown.vue b/resources/vue/components/Dropdown.vue
index 1063516..f68f485 100644
--- a/resources/vue/components/Dropdown.vue
+++ b/resources/vue/components/Dropdown.vue
@@ -1,5 +1,6 @@
<script setup>
-import {nextTick, ref, useTemplateRef, watch} from "vue";
+import {nextTick, onBeforeUnmount, ref, useTemplateRef, watch} from "vue";
+import { createPopper } from '@popperjs/core';
import useDetectOutsideClick from "../composables/useDetectOutsideClick";
import StudipIcon from "./StudipIcon.vue";
@@ -14,22 +15,41 @@ defineProps({
});
const isOpen = defineModel({ default: false });
-const dropdownStyle = ref({});
const dropdown = useTemplateRef('dropdown');
+const trigger = useTemplateRef('trigger');
const dropdownContent = useTemplateRef('dropdownContent');
+const popperInstance = ref(null);
useDetectOutsideClick(dropdown, () => isOpen.value = false);
-watch(isOpen, async (open) => {
+watch(isOpen, async open => {
if (open) {
await nextTick();
- const trigger = dropdown.value?.getBoundingClientRect();
- const content = dropdownContent.value?.getBoundingClientRect();
+ popperInstance.value = createPopper(trigger.value, dropdownContent.value, {
+ placement: 'bottom-end',
+ modifiers: [
+ {
+ name: 'offset',
+ options: {
+ offset: [0, 6]
+ }
+ },
+ {
+ name: 'preventOverflow',
+ options: {
+ padding: 10
+ }
+ }
+ ]
+ });
+ }
+});
- dropdownStyle.value = {
- ...(content.width > trigger.left ? {left: '0'} : {right: '0'})
- };
+onBeforeUnmount(() => {
+ if (popperInstance.value) {
+ popperInstance.value.destroy();
+ popperInstance.value = null;
}
});
</script>
@@ -42,15 +62,16 @@ watch(isOpen, async (open) => {
aria-haspopup="true"
:aria-expanded="isOpen.toString()"
>
- <slot name="trigger">
- </slot>
+ <div ref="trigger">
+ <slot name="trigger">
+ </slot>
+ </div>
<Transition name="fade-down">
<div
v-if="isOpen"
ref="dropdownContent"
class="dropdown__content"
- :style="dropdownStyle"
aria-labelledby="dropdown-title"
>
<button