diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-07-08 16:25:14 +0200 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-07-10 01:35:24 +0200 |
commit | d82565d67d071dce0208323decc455da9d8625ef (patch) | |
tree | c0af409b2213e0bc68e3840f9ff7e368dec845ff /core/src/components/AppMenuEntry.vue | |
parent | a96b5940dd9d80c6ea6fbb5faa6ef7d1a7cc6734 (diff) | |
download | nextcloud-server-d82565d67d071dce0208323decc455da9d8625ef.tar.gz nextcloud-server-d82565d67d071dce0208323decc455da9d8625ef.zip |
refactor(core): Split app menu into components
This allows to split one large block of code into three components with each one usecase.
Allowing for better readability and maintainablility.
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'core/src/components/AppMenuEntry.vue')
-rw-r--r-- | core/src/components/AppMenuEntry.vue | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/core/src/components/AppMenuEntry.vue b/core/src/components/AppMenuEntry.vue new file mode 100644 index 00000000000..d26e0c1dc06 --- /dev/null +++ b/core/src/components/AppMenuEntry.vue @@ -0,0 +1,128 @@ +<!-- + - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later + --> + +<template> + <li class="app-menu-entry" + :class="{ + 'app-menu-entry--active': app.active, + }"> + <a class="app-menu-entry__link" + :href="app.href" + :title="app.name" + :aria-current="app.active ? 'page' : false" + :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"> + {{ app.name }} + </span> + </a> + </li> +</template> + +<script setup lang="ts"> +import type { INavigationEntry } from '../types/navigation' +import AppMenuIcon from './AppMenuIcon.vue' + +defineProps<{ + app: INavigationEntry +}>() +</script> + +<style scoped lang="scss"> +.app-menu-entry { + width: var(--header-height); + height: var(--header-height); + position: relative; + + &__link { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + // Set color as this is shown directly on the background + color: var(--color-background-plain-text); + // Make space for focus-visible outline + width: calc(100% - 4px); + height: calc(100% - 4px); + margin: 2px; + } + + &__label { + opacity: 0; + position: absolute; + font-size: 12px; + line-height: 1.25; + // this is shown directly on the background + color: var(--color-background-plain-text); + text-align: center; + bottom: 0; + left: 50%; + display: block; + min-width: 100%; + transform: translateX(-50%); + transition: all 0.1s ease-in-out; + width: 100%; + text-overflow: ellipsis; + overflow: hidden; + letter-spacing: -0.5px; + } + + &--active { + // When hover or focus, show the label and make it bolder than the other entries + .app-menu-entry__label { + font-weight: bolder; + } + + // When active show a line below the entry as an "active" indicator + &::before { + content: " "; + position: absolute; + pointer-events: none; + border-bottom-color: var(--color-main-background); + transform: translateX(-50%); + width: 12px; + height: 5px; + border-radius: 3px; + background-color: var(--color-background-plain-text); + left: 50%; + bottom: 6px; + display: block; + transition: all 0.1s ease-in-out; + opacity: 1; + } + } + + // Make the hovered entry bold to see that it is hovered + &:hover &__label, + &:focus-within &__label { + font-weight: bold; + } +} +</style> + +<style lang="scss"> +// Showing the label +.app-menu-entry:hover .app-menu-entry, +.app-menu-entry:focus-within .app-menu-entry, +.app-menu__list:hover .app-menu-entry, +.app-menu__list:focus-within .app-menu-entry { + // Move icon up so that the name does not overflow the icon + &__icon { + margin-block-end: calc(1.5 * 12px); // font size of label * line height + } + + // Make the label visible + &__label { + opacity: 1; + } + + // Hide indicator when the text is shown + &--active::before { + opacity: 0; + } +} +</style> |