diff --git a/components/nav/NavSide.vue b/components/nav/NavSide.vue index 59ef211f..2de4f545 100644 --- a/components/nav/NavSide.vue +++ b/components/nav/NavSide.vue @@ -4,26 +4,22 @@ const { notifications } = useNotifications() <template> <nav sm:px3 sm:py4 flex="~ col gap2" text-size-base leading-normal md:text-lg> - <template v-if="isMastoInitialised && currentUser"> - <NavSideItem :text="$t('nav_side.home')" to="/home" icon="i-ri:home-5-line" /> - <NavSideItem :text="$t('nav_side.notifications')" to="/notifications" icon="i-ri:notification-4-line"> - <template #icon> - <div flex relative> - <div class="i-ri:notification-4-line" md:text-size-inherit text-xl /> - <div v-if="notifications" class="top-[-0.3rem] right-[-0.3rem]" absolute font-bold rounded-full h-4 w-4 text-xs bg-primary text-inverted flex items-center justify-center> - {{ notifications < 10 ? notifications : '•' }} - </div> + <NavSideItem :text="$t('nav_side.home')" to="/home" icon="i-ri:home-5-line" /> + <NavSideItem :text="$t('nav_side.notifications')" to="/notifications" icon="i-ri:notification-4-line" :user-only="true"> + <template #icon> + <div flex relative> + <div class="i-ri:notification-4-line" md:text-size-inherit text-xl /> + <div v-if="notifications" class="top-[-0.3rem] right-[-0.3rem]" absolute font-bold rounded-full h-4 w-4 text-xs bg-primary text-inverted flex items-center justify-center> + {{ notifications < 10 ? notifications : '•' }} </div> - </template> - </NavSideItem> - </template> + </div> + </template> + </NavSideItem> <NavSideItem :text="$t('nav_side.explore')" :to="`/${currentServer}/explore`" icon="i-ri:hashtag" /> <NavSideItem :text="$t('nav_side.local')" :to="`/${currentServer}/public/local`" icon="i-ri:group-2-line " /> <NavSideItem :text="$t('nav_side.federated')" :to="`/${currentServer}/public`" icon="i-ri:earth-line" /> - <template v-if="isMastoInitialised && currentUser"> - <NavSideItem :text="$t('nav_side.conversations')" to="/conversations" icon="i-ri:at-line" /> - <NavSideItem :text="$t('nav_side.favourites')" to="/favourites" icon="i-ri:heart-3-line" /> - <NavSideItem :text="$t('nav_side.bookmarks')" to="/bookmarks" icon="i-ri:bookmark-line " /> - </template> + <NavSideItem :text="$t('nav_side.conversations')" to="/conversations" icon="i-ri:at-line" :user-only="true" /> + <NavSideItem :text="$t('nav_side.favourites')" to="/favourites" icon="i-ri:heart-3-line" :user-only="true" /> + <NavSideItem :text="$t('nav_side.bookmarks')" to="/bookmarks" icon="i-ri:bookmark-line " :user-only="true" /> </nav> </template> diff --git a/components/nav/NavSideItem.vue b/components/nav/NavSideItem.vue index 58e07834..be5e25b8 100644 --- a/components/nav/NavSideItem.vue +++ b/components/nav/NavSideItem.vue @@ -1,9 +1,12 @@ <script setup lang="ts"> -const props = defineProps<{ +const props = withDefaults(defineProps<{ text?: string icon: string to: string | Record<string, string> -}>() + userOnly?: boolean +}>(), { + userOnly: false, +}) defineSlots<{ icon: {} @@ -22,10 +25,26 @@ useCommand({ router.push(props.to) }, }) + +let activeClass = $ref('text-primary') +watch(isMastoInitialised, async () => { + if (!props.userOnly) { + // TODO: force NuxtLink to reevaluate, we now we are in this route though, so we should force it to active + // we don't have currentServer defined until later + activeClass = '' + await nextTick() + activeClass = 'text-primary' + } +}) + +// Optimize rendering for the common case of being logged in, only show visual feedback for disabled user-only items +// when we know there is no user. +const noUserDisable = computed(() => !isMastoInitialised.value || (props.userOnly && !currentUser.value)) +const noUserVisual = computed(() => isMastoInitialised.value && props.userOnly && !currentUser.value) </script> <template> - <NuxtLink :to="to" :active-class="isMastoInitialised ? 'text-primary' : ''" group focus:outline-none @click="$scrollToTop"> + <NuxtLink :to="to" :disabled="noUserDisable" :class="noUserVisual ? 'op25 pointer-events-none ' : ''" :active-class="activeClass" group focus:outline-none @click="$scrollToTop"> <CommonTooltip :disabled="!isMediumScreen" :content="text" placement="right"> <div flex w-fit px2 mx3 lg:mx0 lg:px5 py2 gap4 items-center transition-100 rounded-full group-hover:bg-active group-focus-visible:ring="2 current"> <slot name="icon"> diff --git a/components/publish/PublishButton.vue b/components/publish/PublishButton.vue index f182d0c8..d1150a47 100644 --- a/components/publish/PublishButton.vue +++ b/components/publish/PublishButton.vue @@ -1,5 +1,16 @@ +<script setup> +const disabled = computed(() => !isMastoInitialised.value || !currentUser.value) +const disabledVisual = computed(() => isMastoInitialised.value && !currentUser.value) +</script> + <template> - <button color-primary btn-outline rounded-full ml-7 lg:ml-3 w-9 lg:w-auto font-bold py2 lg:py4 flex="~ gap2 center" @click="openPublishDialog()"> + <button + color-primary rounded-full ml-7 lg:ml-3 w-9 lg:w-auto font-bold py2 lg:py4 flex="~ gap2 center" + cursor-pointer disabled:pointer-events-none + text-primary border-1 border-primary + :disabled="disabled" :class="disabledVisual ? 'op25' : 'hover:bg-primary hover:text-inverted'" + @click="openPublishDialog()" + > <div i-ri:quill-pen-line /> <span hidden lg:block>{{ $t('action.compose') }}</span> </button> diff --git a/layouts/default.vue b/layouts/default.vue index 08d795f1..2efbe01b 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -11,7 +11,7 @@ <div flex="~ col" overflow-y-auto justify-between h-full> <div flex flex-col> <NavSide /> - <PublishButton v-if="isMastoInitialised && currentUser" m5 /> + <PublishButton m5 /> </div> <div flex flex-col> <UserSignInEntry v-if="isMastoInitialised && !currentUser" sm:hidden />