Browse Source

Maintenance: Desktop view - Open select dropdown is visible outside of scroll area and may introduce extra spacing.

Dusan Vuckovic 5 months ago
parent
commit
dc787b6d98

+ 3 - 1
app/frontend/apps/desktop/components/CommonSelect/CommonSelect.vue

@@ -66,6 +66,7 @@ export interface Props {
   actions?: DropdownOptionsAction[]
   actions?: DropdownOptionsAction[]
   isChildPage?: boolean
   isChildPage?: boolean
   isLoading?: boolean
   isLoading?: boolean
+  isTargetVisible?: boolean
 }
 }
 
 
 const props = withDefaults(defineProps<Props>(), {
 const props = withDefaults(defineProps<Props>(), {
@@ -405,7 +406,7 @@ const goToChildPage = ({
   />
   />
   <Teleport to="body">
   <Teleport to="body">
     <Transition
     <Transition
-      name="collapse"
+      :name="isTargetVisible ? 'collapse' : 'none'"
       :duration="collapseDuration"
       :duration="collapseDuration"
       @enter="collapseEnter"
       @enter="collapseEnter"
       @after-enter="collapseAfterEnter"
       @after-enter="collapseAfterEnter"
@@ -413,6 +414,7 @@ const goToChildPage = ({
     >
     >
       <div
       <div
         v-if="showDropdown"
         v-if="showDropdown"
+        v-show="isTargetVisible"
         id="common-select"
         id="common-select"
         ref="dropdown"
         ref="dropdown"
         class="fixed z-50 flex min-h-9 antialiased"
         class="fixed z-50 flex min-h-9 antialiased"

+ 4 - 1
app/frontend/apps/desktop/components/CommonSelect/__tests__/CommonSelect.spec.ts

@@ -29,7 +29,10 @@ const html = String.raw
 
 
 const renderSelect = (props: Props, modelValue?: Ref) => {
 const renderSelect = (props: Props, modelValue?: Ref) => {
   return renderComponent(CommonSelect, {
   return renderComponent(CommonSelect, {
-    props,
+    props: {
+      isTargetVisible: true,
+      ...props,
+    },
     slots: {
     slots: {
       default: html` <template #default="{ open, focus }">
       default: html` <template #default="{ open, focus }">
         <button @click="open()">Open Select</button>
         <button @click="open()">Open Select</button>

+ 3 - 0
app/frontend/apps/desktop/components/Form/fields/FieldAutoComplete/FieldAutoCompleteInput.vue

@@ -6,6 +6,7 @@ import {
   refDebounced,
   refDebounced,
   useDebounceFn,
   useDebounceFn,
   useElementBounding,
   useElementBounding,
+  useElementVisibility,
   useWindowSize,
   useWindowSize,
   watchOnce,
   watchOnce,
 } from '@vueuse/core'
 } from '@vueuse/core'
@@ -394,6 +395,7 @@ const suggestedOptionLabel = computed(() => {
 })
 })
 
 
 const inputElementBounds = useElementBounding(input)
 const inputElementBounds = useElementBounding(input)
+const isInputVisible = !!VITE_TEST_MODE || useElementVisibility(input)
 const windowSize = useWindowSize()
 const windowSize = useWindowSize()
 
 
 const isBelowHalfScreen = computed(() => {
 const isBelowHalfScreen = computed(() => {
@@ -507,6 +509,7 @@ useFormBlock(
       :is-child-page="childOptions.length > 0"
       :is-child-page="childOptions.length > 0"
       no-options-label-translation
       no-options-label-translation
       :is-loading="isLoading || isUserTyping"
       :is-loading="isLoading || isUserTyping"
+      :is-target-visible="isInputVisible"
       no-close
       no-close
       passive
       passive
       initially-empty
       initially-empty

+ 8 - 1
app/frontend/apps/desktop/components/Form/fields/FieldSelect/FieldSelectInput.vue

@@ -1,7 +1,12 @@
 <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
 <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { useDebounceFn, useElementBounding, useWindowSize } from '@vueuse/core'
+import {
+  useDebounceFn,
+  useElementBounding,
+  useElementVisibility,
+  useWindowSize,
+} from '@vueuse/core'
 import { escapeRegExp } from 'lodash-es'
 import { escapeRegExp } from 'lodash-es'
 import { useTemplateRef, computed, nextTick, ref, toRef, watch } from 'vue'
 import { useTemplateRef, computed, nextTick, ref, toRef, watch } from 'vue'
 
 
@@ -98,6 +103,7 @@ const suggestedOptionLabel = computed(() => {
 })
 })
 
 
 const inputElementBounds = useElementBounding(inputElement)
 const inputElementBounds = useElementBounding(inputElement)
+const isInputVisible = !!VITE_TEST_MODE || useElementVisibility(inputElement)
 const windowSize = useWindowSize()
 const windowSize = useWindowSize()
 
 
 const isBelowHalfScreen = computed(() => {
 const isBelowHalfScreen = computed(() => {
@@ -187,6 +193,7 @@ setupMissingOrDisabledOptionHandling()
       :multiple="context.multiple"
       :multiple="context.multiple"
       :owner="context.id"
       :owner="context.id"
       :filter="filter"
       :filter="filter"
+      :is-target-visible="isInputVisible"
       no-options-label-translation
       no-options-label-translation
       no-close
       no-close
       passive
       passive

+ 7 - 1
app/frontend/apps/desktop/components/Form/fields/FieldTreeSelect/FieldTreeSelectInput.vue

@@ -1,7 +1,11 @@
 <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
 <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { useElementBounding, useWindowSize } from '@vueuse/core'
+import {
+  useElementBounding,
+  useElementVisibility,
+  useWindowSize,
+} from '@vueuse/core'
 import { escapeRegExp } from 'lodash-es'
 import { escapeRegExp } from 'lodash-es'
 import { computed, nextTick, ref, toRef, watch, useTemplateRef } from 'vue'
 import { computed, nextTick, ref, toRef, watch, useTemplateRef } from 'vue'
 
 
@@ -153,6 +157,7 @@ const clearValue = () => {
 }
 }
 
 
 const inputElementBounds = useElementBounding(inputElement)
 const inputElementBounds = useElementBounding(inputElement)
+const isInputVisible = !!VITE_TEST_MODE || useElementVisibility(inputElement)
 const windowSize = useWindowSize()
 const windowSize = useWindowSize()
 
 
 const isBelowHalfScreen = computed(() => {
 const isBelowHalfScreen = computed(() => {
@@ -245,6 +250,7 @@ setupMissingOrDisabledOptionHandling()
       :flat-options="flatOptions"
       :flat-options="flatOptions"
       :current-options="currentOptions"
       :current-options="currentOptions"
       :option-value-lookup="optionValueLookup"
       :option-value-lookup="optionValueLookup"
+      :is-target-visible="isInputVisible"
       no-options-label-translation
       no-options-label-translation
       no-close
       no-close
       passive
       passive

+ 3 - 1
app/frontend/apps/desktop/components/Form/fields/FieldTreeSelect/FieldTreeSelectInputDropdown.vue

@@ -55,6 +55,7 @@ export interface Props {
   flatOptions: FlatSelectOption[]
   flatOptions: FlatSelectOption[]
   currentOptions: FlatSelectOption[]
   currentOptions: FlatSelectOption[]
   optionValueLookup: { [index: string | number]: FlatSelectOption }
   optionValueLookup: { [index: string | number]: FlatSelectOption }
+  isTargetVisible?: boolean
 }
 }
 
 
 const props = defineProps<Props>()
 const props = defineProps<Props>()
@@ -417,7 +418,7 @@ const { collapseDuration, collapseEnter, collapseAfterEnter, collapseLeave } =
   />
   />
   <Teleport to="body">
   <Teleport to="body">
     <Transition
     <Transition
-      name="collapse"
+      :name="isTargetVisible ? 'collapse' : 'none'"
       :duration="collapseDuration"
       :duration="collapseDuration"
       @enter="collapseEnter"
       @enter="collapseEnter"
       @after-enter="collapseAfterEnter"
       @after-enter="collapseAfterEnter"
@@ -425,6 +426,7 @@ const { collapseDuration, collapseEnter, collapseAfterEnter, collapseLeave } =
     >
     >
       <div
       <div
         v-if="showDropdown"
         v-if="showDropdown"
+        v-show="isTargetVisible"
         id="field-tree-select-input-dropdown"
         id="field-tree-select-input-dropdown"
         ref="dropdown"
         ref="dropdown"
         class="fixed z-10 flex min-h-9 antialiased"
         class="fixed z-10 flex min-h-9 antialiased"

+ 1 - 1
app/frontend/apps/desktop/components/layout/LayoutSidebar.vue

@@ -101,7 +101,7 @@ const collapseButtonClass = computed(() => {
 <template>
 <template>
   <aside
   <aside
     :id="props.id"
     :id="props.id"
-    class="-:bg-neutral-950 -:max-h-screen relative flex flex-col border-neutral-100 dark:border-gray-900"
+    class="-:bg-neutral-950 -:max-h-screen relative flex flex-col overflow-y-clip border-neutral-100 dark:border-gray-900"
     :class="{
     :class="{
       'py-3': isCollapsed && !noPadding,
       'py-3': isCollapsed && !noPadding,
       'border-e': position === SidebarPosition.Start,
       'border-e': position === SidebarPosition.Start,