Skip to content

Commit

Permalink
fix: Ensure app overflow menu is rendered centered
Browse files Browse the repository at this point in the history
1. Fix app menu overflow button to be centered
2. Ensure the overflow calculation always just removed one element (incl. refactor to use `@vueuse`)
3. Ensure we use 1.5 line height for app menu, otherwise some languages look squashed under the app icon

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux authored and AndyScherzinger committed Aug 7, 2024
1 parent 609fa7d commit 91f7893
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 43 deletions.
79 changes: 39 additions & 40 deletions core/src/components/AppMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
-->

<template>
<nav class="app-menu"
<nav ref="appMenu"
class="app-menu"
:aria-label="t('core', 'Applications menu')">
<ul class="app-menu__list">
<AppMenuEntry v-for="app in mainAppList"
Expand All @@ -29,7 +30,8 @@ import type { INavigationEntry } from '../types/navigation'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
import { n, t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
import { useElementSize } from '@vueuse/core'
import { defineComponent, ref } from 'vue'

import AppMenuEntry from './AppMenuEntry.vue'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
Expand All @@ -46,40 +48,47 @@ export default defineComponent({
},

setup() {
const appMenu = ref()
const { width: appMenuWidth } = useElementSize(appMenu)
return {
t,
n,
appMenu,
appMenuWidth,
}
},

data() {
const appList = loadState<INavigationEntry[]>('core', 'apps', [])

return {
appList,
appLimit: 0,
observer: null as ResizeObserver | null,
}
},

computed: {
appLimit() {
const maxApps = Math.floor(this.appMenuWidth / 50)
if (maxApps < this.appList.length) {
// Ensure there is space for the overflow menu
return Math.max(maxApps - 1, 0)
}
return maxApps
},

mainAppList() {
return this.appList.slice(0, this.appLimit)
},

popoverAppList() {
return this.appList.slice(this.appLimit)
},
},

mounted() {
this.observer = new ResizeObserver(this.resize)
this.observer.observe(this.$el)
this.resize()
subscribe('nextcloud:app-menu.refresh', this.setApps)
},

beforeDestroy() {
this.observer!.disconnect()
unsubscribe('nextcloud:app-menu.refresh', this.setApps)
},

Expand All @@ -96,54 +105,44 @@ export default defineComponent({
setApps({ apps }: { apps: INavigationEntry[]}) {
this.appList = apps
},

resize() {
const availableWidth = (this.$el as HTMLElement).offsetWidth
let appCount = Math.floor(availableWidth / 50) - 1
const popoverAppCount = this.appList.length - appCount
if (popoverAppCount === 1) {
appCount--
}
if (appCount < 1) {
appCount = 0
}
this.appLimit = appCount
},
},
})
</script>

<style scoped lang="scss">
.app-menu {
width: 100%;
display: flex;
flex-shrink: 1;
flex-wrap: wrap;
flex: 1 1;
width: 0;

&__list {
display: flex;
flex-wrap: nowrap;
}

// Adjust the overflow NcActions styles as they are directly rendered on the background
&__overflow :deep(.button-vue--vue-tertiary) {
opacity: .7;
margin: 3px;
filter: var(--background-image-invert-if-bright);
&__overflow {
margin-block: auto;

/* Remove all background and align text color if not expanded */
&:not([aria-expanded="true"]) {
color: var(--color-background-plain-text);
// Adjust the overflow NcActions styles as they are directly rendered on the background
:deep(.button-vue--vue-tertiary) {
opacity: .7;
margin: 3px;
filter: var(--background-image-invert-if-bright);

&:hover {
opacity: 1;
background-color: transparent !important;
/* Remove all background and align text color if not expanded */
&:not([aria-expanded="true"]) {
color: var(--color-background-plain-text);

&:hover {
opacity: 1;
background-color: transparent !important;
}
}
}

&:focus-visible {
opacity: 1;
outline: none !important;
&:focus-visible {
opacity: 1;
outline: none !important;
}
}
}

Expand Down
10 changes: 7 additions & 3 deletions core/src/components/AppMenuEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ defineProps<{

<style scoped lang="scss">
.app-menu-entry {
--app-menu-entry-font-size: 12px;
width: var(--header-height);
height: var(--header-height);
position: relative;
Expand All @@ -54,8 +55,7 @@ defineProps<{
&__label {
opacity: 0;
position: absolute;
font-size: 12px;
line-height: 1.25;
font-size: var(--app-menu-entry-font-size);
// this is shown directly on the background
color: var(--color-background-plain-text);
text-align: center;
Expand All @@ -71,6 +71,10 @@ defineProps<{
letter-spacing: -0.5px;
}

&__icon {
font-size: var(--app-menu-entry-font-size);
}

&--active {
// When hover or focus, show the label and make it bolder than the other entries
.app-menu-entry__label {
Expand Down Expand Up @@ -117,7 +121,7 @@ defineProps<{
.app-menu__list:focus-within {
// Move icon up so that the name does not overflow the icon
.app-menu-entry__icon {
margin-block-end: calc(1.5 * 12px); // font size of label * line height
margin-block-end: 1lh;
}

// Make the label visible
Expand Down

0 comments on commit 91f7893

Please sign in to comment.