diff options
| author | Murtaza Sultani <sultani@data-quest.de> | 2025-08-07 16:38:29 +0200 |
|---|---|---|
| committer | Murtaza Sultani <sultani@data-quest.de> | 2025-08-07 16:38:29 +0200 |
| commit | 327b4db7b6b025b839097814f358e3163749b3b0 (patch) | |
| tree | 9335b6f4c0d0cc4537199536ac58bb121dda2131 /resources | |
| parent | e22cd7ecb77a0133cc013b62e1d91be7ce6605ff (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.scss | 37 | ||||
| -rw-r--r-- | resources/assets/stylesheets/studip.scss | 29 | ||||
| -rw-r--r-- | resources/vue/components/Dropdown.vue | 43 |
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 |
