Skip to content

Commit

Permalink
Merge pull request #47236 from nextcloud/backport/47203/stable30
Browse files Browse the repository at this point in the history
[stable30] fix(AppMenu): Prevent menu entries from jumping on hover
  • Loading branch information
skjnldsv authored Aug 14, 2024
2 parents 9a1339d + f8bbb27 commit f68065c
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 31 deletions.
10 changes: 0 additions & 10 deletions core/src/components/AppMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,6 @@ export default defineComponent({
display: flex;
flex-wrap: nowrap;
margin-inline: calc(var(--app-menu-entry-growth) / 2);
transition: margin-inline var(--animation-quick) ease-in-out;

// Remove padding if the first child is focussed
&:has(.app-menu-entry:hover:first-child, .app-menu-entry:focus-within:first-child) {
margin-inline: 0 calc(var(--app-menu-entry-growth) / 2);
}
// Remove padding if the last child is focussed
&:has(.app-menu-entry:hover:last-child, .app-menu-entry:focus-within:last-child) {
margin-inline: calc(var(--app-menu-entry-growth) / 2) 0;
}
}

&__overflow {
Expand Down
52 changes: 34 additions & 18 deletions core/src/components/AppMenuEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
-->

<template>
<li class="app-menu-entry"
<li ref="containerElement"
class="app-menu-entry"
:class="{
'app-menu-entry--active': app.active,
'app-menu-entry--truncated': needsSpace,
}">
<a class="app-menu-entry__link"
:href="app.href"
Expand All @@ -15,7 +17,7 @@
:target="app.target ? '_blank' : undefined"
:rel="app.target ? 'noopener noreferrer' : undefined">
<AppMenuIcon class="app-menu-entry__icon" :app="app" />
<span class="app-menu-entry__label">
<span ref="labelElement" class="app-menu-entry__label">
{{ app.name }}
</span>
</a>
Expand All @@ -24,11 +26,26 @@

<script setup lang="ts">
import type { INavigationEntry } from '../types/navigation'
import { onMounted, ref, watch } from 'vue'
import AppMenuIcon from './AppMenuIcon.vue'

defineProps<{
const props = defineProps<{
app: INavigationEntry
}>()

const containerElement = ref<HTMLLIElement>()
const labelElement = ref<HTMLSpanElement>()
const needsSpace = ref(false)

/** Update the space requirements of the app label */
function calculateSize() {
const maxWidth = containerElement.value!.clientWidth
// Also keep the 0.5px letter spacing in mind
needsSpace.value = (maxWidth - props.app.name.length * 0.5) < (labelElement.value!.scrollWidth)
}
// Update size on mounted and when the app name changes
onMounted(calculateSize)
watch(() => props.app.name, calculateSize)
</script>

<style scoped lang="scss">
Expand All @@ -37,8 +54,6 @@ defineProps<{
width: var(--header-height);
height: var(--header-height);
position: relative;
// Needed to prevent jumping when hover an entry (keep in sync with :hover styles)
transition: width var(--animation-quick) ease-in-out;

&__link {
position: relative;
Expand All @@ -65,9 +80,8 @@ defineProps<{
left: 50%;
top: 50%;
display: block;
min-width: 100%;
transform: translateX(-50%);
width: 100%;
max-width: 100%;
text-overflow: ellipsis;
overflow: hidden;
letter-spacing: -0.5px;
Expand Down Expand Up @@ -115,25 +129,27 @@ defineProps<{

// Adjust the width when an entry is focussed
// The focussed / hovered entry should grow, while both neighbors need to shrink
&:hover,
&:focus-within {
width: calc(var(--header-height) + var(--app-menu-entry-growth));
&--truncated:hover,
&--truncated:focus-within {
.app-menu-entry__label {
max-width: calc(var(--header-height) + var(--app-menu-entry-growth));
}

// The next entry needs to shrink half the growth
+ .app-menu-entry {
width: calc(var(--header-height) - (var(--app-menu-entry-growth) / 2));
.app-menu-entry__icon {
margin-inline-end: calc(var(--app-menu-entry-growth) / 2);
.app-menu-entry__label {
font-weight: normal;
max-width: calc(var(--header-height) - var(--app-menu-entry-growth));
}
}
}

// The previous entry needs to shrink half the growth
&:has(+ .app-menu-entry:hover),
&:has(+ .app-menu-entry:focus-within) {
width: calc(var(--header-height) - (var(--app-menu-entry-growth) / 2));
.app-menu-entry__icon {
margin-inline-start: calc(var(--app-menu-entry-growth) / 2);
&:has(+ .app-menu-entry--truncated:hover),
&:has(+ .app-menu-entry--truncated:focus-within) {
.app-menu-entry__label {
font-weight: normal;
max-width: calc(var(--header-height) - var(--app-menu-entry-growth));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions dist/core-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/core-main.js.map

Large diffs are not rendered by default.

0 comments on commit f68065c

Please sign in to comment.