diff --git a/packages/frontend/src/components/MkLaunchPad.vue b/packages/frontend/src/components/MkLaunchPad.vue index 2dcba7a50e5c..32c1a2d17246 100644 --- a/packages/frontend/src/components/MkLaunchPad.vue +++ b/packages/frontend/src/components/MkLaunchPad.vue @@ -12,13 +12,13 @@ SPDX-License-Identifier: AGPL-3.0-only <i class="icon" :class="item.icon"></i> <div class="text">{{ item.text }}</div> <span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span> - <span v-else-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-else-if="item.indicate" class="indicator _blink"><i class="_indicatorCircle"></i></span> </button> <MkA v-else v-click-anime :to="item.to" class="item" @click.passive="close()"> <i class="icon" :class="item.icon"></i> <div class="text">{{ item.text }}</div> <span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span> - <span v-else-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-else-if="item.indicate" class="indicator _blink"><i class="_indicatorCircle"></i></span> </MkA> </template> </div> @@ -139,7 +139,6 @@ function close() { left: 32px; color: var(--MI_THEME-indicator); font-size: 8px; - animation: global-blink 1s infinite; @media (max-width: 500px) { top: 16px; diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue index 59f36f8eec45..13a65e411f50 100644 --- a/packages/frontend/src/components/MkMenu.vue +++ b/packages/frontend/src/components/MkMenu.vue @@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/> <div :class="$style.item_content"> <span :class="$style.item_content_text">{{ item.text }}</span> - <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> + <span v-if="item.indicate" :class="$style.indicator" class="_blink"><i class="_indicatorCircle"></i></span> </div> </MkA> <a @@ -68,7 +68,7 @@ SPDX-License-Identifier: AGPL-3.0-only <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <div :class="$style.item_content"> <span :class="$style.item_content_text">{{ item.text }}</span> - <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> + <span v-if="item.indicate" :class="$style.indicator" class="_blink"><i class="_indicatorCircle"></i></span> </div> </a> <button @@ -82,7 +82,7 @@ SPDX-License-Identifier: AGPL-3.0-only > <MkAvatar :user="item.user" :class="$style.avatar"/><MkUserName :user="item.user"/> <div v-if="item.indicate" :class="$style.item_content"> - <span :class="$style.indicator"><i class="_indicatorCircle"></i></span> + <span :class="$style.indicator" class="_blink"><i class="_indicatorCircle"></i></span> </div> </button> <button @@ -161,7 +161,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/> <div :class="$style.item_content"> <span :class="$style.item_content_text">{{ item.text }}</span> - <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> + <span v-if="item.indicate" :class="$style.indicator" class="_blink"><i class="_indicatorCircle"></i></span> </div> </button> </template> @@ -639,7 +639,6 @@ onBeforeUnmount(() => { align-items: center; color: var(--MI_THEME-indicator); font-size: 12px; - animation: global-blink 1s infinite; } .divider { diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss index 1e6561bdb979..4204c5af59a5 100644 --- a/packages/frontend/src/style.scss +++ b/packages/frontend/src/style.scss @@ -480,7 +480,11 @@ html[data-color-scheme=dark] ._woodenFrame { transform: scale(0.9); } -@keyframes global-blink { +._blink { + animation: blink 1s infinite; +} + +@keyframes blink { 0% { opacity: 1; transform: scale(1); } 30% { opacity: 1; transform: scale(1); } 90% { opacity: 0; transform: scale(0.5); } diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue index 9acf7b2ede91..44253e93bd27 100644 --- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue +++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only <div v-if="item === '-'" :class="$style.divider"></div> <component :is="navbarItemDef[item].to ? 'MkA' : 'button'" v-else-if="navbarItemDef[item] && (navbarItemDef[item].show !== false)" class="_button" :class="[$style.item, { [$style.active]: navbarItemDef[item].active }]" :activeClass="$style.active" :to="navbarItemDef[item].to" v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}"> <i class="ti-fw" :class="[$style.itemIcon, navbarItemDef[item].icon]"></i><span :class="$style.itemText">{{ navbarItemDef[item].title }}</span> - <span v-if="navbarItemDef[item].indicated" :class="$style.itemIndicator"> + <span v-if="navbarItemDef[item].indicated" :class="$style.itemIndicator" class="_blink"> <span v-if="navbarItemDef[item].indicateValue" class="_indicateCounter" :class="$style.itemIndicateValueIcon">{{ navbarItemDef[item].indicateValue }}</span> <i v-else class="_indicatorCircle"></i> </span> @@ -31,7 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only </MkA> <button :class="$style.item" class="_button" @click="more"> <i :class="$style.itemIcon" class="ti ti-grid-dots ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.more }}</span> - <span v-if="otherMenuItemIndicated" :class="$style.itemIndicator"><i class="_indicatorCircle"></i></span> + <span v-if="otherMenuItemIndicated" :class="$style.itemIndicator" class="_blink"><i class="_indicatorCircle"></i></span> </button> <MkA :class="$style.item" :activeClass="$style.active" to="/settings"> <i :class="$style.itemIcon" class="ti ti-settings ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.settings }}</span> @@ -257,7 +257,6 @@ function more() { left: 20px; color: var(--MI_THEME-navIndicator); font-size: 8px; - animation: global-blink 1s infinite; &:has(.itemIndicateValueIcon) { animation: none; diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue index cbfdaac235d7..8ae11efa2c66 100644 --- a/packages/frontend/src/ui/_common_/navbar.vue +++ b/packages/frontend/src/ui/_common_/navbar.vue @@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}" > <i class="ti-fw" :class="[$style.itemIcon, navbarItemDef[item].icon]"></i><span :class="$style.itemText">{{ navbarItemDef[item].title }}</span> - <span v-if="navbarItemDef[item].indicated" :class="$style.itemIndicator"> + <span v-if="navbarItemDef[item].indicated" :class="$style.itemIndicator" class="_blink"> <span v-if="navbarItemDef[item].indicateValue" class="_indicateCounter" :class="$style.itemIndicateValueIcon">{{ navbarItemDef[item].indicateValue }}</span> <i v-else class="_indicatorCircle"></i> </span> @@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only </MkA> <button class="_button" :class="$style.item" @click="more"> <i :class="$style.itemIcon" class="ti ti-grid-dots ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.more }}</span> - <span v-if="otherMenuItemIndicated" :class="$style.itemIndicator"><i class="_indicatorCircle"></i></span> + <span v-if="otherMenuItemIndicated" :class="$style.itemIndicator" class="_blink"><i class="_indicatorCircle"></i></span> </button> <MkA v-tooltip.noDelay.right="i18n.ts.settings" :class="$style.item" :activeClass="$style.active" to="/settings"> <i :class="$style.itemIcon" class="ti ti-settings ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.settings }}</span> @@ -350,7 +350,6 @@ function more(ev: MouseEvent) { left: 20px; color: var(--MI_THEME-navIndicator); font-size: 8px; - animation: global-blink 1s infinite; &:has(.itemIndicateValueIcon) { animation: none; @@ -555,7 +554,6 @@ function more(ev: MouseEvent) { left: 24px; color: var(--MI_THEME-navIndicator); font-size: 8px; - animation: global-blink 1s infinite; &:has(.itemIndicateValueIcon) { animation: none; diff --git a/packages/frontend/src/ui/classic.header.vue b/packages/frontend/src/ui/classic.header.vue index a0a860188758..f4633314ae85 100644 --- a/packages/frontend/src/ui/classic.header.vue +++ b/packages/frontend/src/ui/classic.header.vue @@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only <div v-if="item === '-'" class="divider"></div> <component :is="navbarItemDef[item].to ? 'MkA' : 'button'" v-else-if="navbarItemDef[item] && (navbarItemDef[item].show !== false)" v-click-anime v-tooltip="navbarItemDef[item].title" class="item _button" :class="item" activeClass="active" :to="navbarItemDef[item].to" v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}"> <i class="ti-fw" :class="navbarItemDef[item].icon"></i> - <span v-if="navbarItemDef[item].indicated" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-if="navbarItemDef[item].indicated" class="indicator _blink"><i class="_indicatorCircle"></i></span> </component> </template> <div class="divider"></div> @@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only </MkA> <button v-click-anime class="item _button" @click="more"> <i class="ti ti-dots ti-fw"></i> - <span v-if="otherNavItemIndicated" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-if="otherNavItemIndicated" class="indicator _blink"><i class="_indicatorCircle"></i></span> </button> </div> <div class="right"> @@ -142,7 +142,6 @@ onMounted(() => { left: 0; color: var(--MI_THEME-navIndicator); font-size: 8px; - animation: global-blink 1s infinite; } &:hover { diff --git a/packages/frontend/src/ui/classic.sidebar.vue b/packages/frontend/src/ui/classic.sidebar.vue index 4d1846c34c35..5acef0bef816 100644 --- a/packages/frontend/src/ui/classic.sidebar.vue +++ b/packages/frontend/src/ui/classic.sidebar.vue @@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only <div v-if="item === '-'" class="divider"></div> <component :is="navbarItemDef[item].to ? 'MkA' : 'button'" v-else-if="navbarItemDef[item] && (navbarItemDef[item].show !== false)" v-click-anime class="item _button" :class="item" activeClass="active" :to="navbarItemDef[item].to" v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}"> <i class="ti-fw" :class="navbarItemDef[item].icon"></i><span class="text">{{ navbarItemDef[item].title }}</span> - <span v-if="navbarItemDef[item].indicated" class="indicator"> + <span v-if="navbarItemDef[item].indicated" class="indicator _blink"> <span v-if="navbarItemDef[item].indicateValue" class="_indicateCounter itemIndicateValueIcon">{{ navbarItemDef[item].indicateValue }}</span> <i v-else class="_indicatorCircle"></i> </span> @@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only </MkA> <button v-click-anime class="item _button" @click="more"> <i class="ti ti-dots ti-fw"></i><span class="text">{{ i18n.ts.more }}</span> - <span v-if="otherNavItemIndicated" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-if="otherNavItemIndicated" class="indicator _blink"><i class="_indicatorCircle"></i></span> </button> <MkA v-click-anime class="item" activeClass="active" to="/settings" :behavior="settingsWindowed ? 'window' : null"> <i class="ti ti-settings ti-fw"></i><span class="text">{{ i18n.ts.settings }}</span> @@ -222,7 +222,6 @@ watch(defaultStore.reactiveState.menuDisplay, () => { left: 0; color: var(--MI_THEME-navIndicator); font-size: 8px; - animation: global-blink 1s infinite; &:has(.itemIndicateValueIcon) { animation: none; diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index 36ffca82644d..a1a76a7e7da8 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -50,11 +50,11 @@ SPDX-License-Identifier: AGPL-3.0-only </div> <div v-if="isMobile" :class="$style.nav"> - <button :class="$style.navButton" class="_button" @click="drawerMenuShowing = true"><i :class="$style.navButtonIcon" class="ti ti-menu-2"></i><span v-if="menuIndicated" :class="$style.navButtonIndicator"><i class="_indicatorCircle"></i></span></button> + <button :class="$style.navButton" class="_button" @click="drawerMenuShowing = true"><i :class="$style.navButtonIcon" class="ti ti-menu-2"></i><span v-if="menuIndicated" :class="$style.navButtonIndicator" class="_blink"><i class="_indicatorCircle"></i></span></button> <button :class="$style.navButton" class="_button" @click="mainRouter.push('/')"><i :class="$style.navButtonIcon" class="ti ti-home"></i></button> <button :class="$style.navButton" class="_button" @click="mainRouter.push('/my/notifications')"> <i :class="$style.navButtonIcon" class="ti ti-bell"></i> - <span v-if="$i?.hasUnreadNotification" :class="$style.navButtonIndicator"> + <span v-if="$i?.hasUnreadNotification" :class="$style.navButtonIndicator" class="_blink"> <span class="_indicateCounter" :class="$style.itemIndicateValueIcon">{{ $i.unreadNotificationsCount > 99 ? '99+' : $i.unreadNotificationsCount }}</span> </span> </button> @@ -97,6 +97,7 @@ import { v4 as uuid } from 'uuid'; import XCommon from './_common_/common.vue'; import { deckStore, columnTypes, addColumn as addColumnToStore, loadDeck, getProfiles, deleteProfile as deleteProfile_ } from './deck/deck-store.js'; import type { ColumnType } from './deck/deck-store.js'; +import type { MenuItem } from '@/types/menu.js'; import XSidebar from '@/ui/_common_/navbar.vue'; import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import MkButton from '@/components/MkButton.vue'; @@ -118,7 +119,6 @@ import XMentionsColumn from '@/ui/deck/mentions-column.vue'; import XDirectColumn from '@/ui/deck/direct-column.vue'; import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue'; import { mainRouter } from '@/router/main.js'; -import type { MenuItem } from '@/types/menu.js'; const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue')); const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue')); @@ -479,7 +479,6 @@ body { left: 0; color: var(--MI_THEME-indicator); font-size: 16px; - animation: global-blink 1s infinite; &:has(.itemIndicateValueIcon) { animation: none; diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue index 9fc8bd102d30..d739c2e1cddc 100644 --- a/packages/frontend/src/ui/universal.vue +++ b/packages/frontend/src/ui/universal.vue @@ -25,11 +25,11 @@ SPDX-License-Identifier: AGPL-3.0-only <button v-if="(!isDesktop || pageMetadata?.needWideArea) && !isMobile" :class="$style.widgetButton" class="_button" @click="widgetsShowing = true"><i class="ti ti-apps"></i></button> <div v-if="isMobile" ref="navFooter" :class="$style.nav"> - <button :class="$style.navButton" class="_button" @click="drawerMenuShowing = true"><i :class="$style.navButtonIcon" class="ti ti-menu-2"></i><span v-if="menuIndicated" :class="$style.navButtonIndicator"><i class="_indicatorCircle"></i></span></button> + <button :class="$style.navButton" class="_button" @click="drawerMenuShowing = true"><i :class="$style.navButtonIcon" class="ti ti-menu-2"></i><span v-if="menuIndicated" :class="$style.navButtonIndicator" class="_blink"><i class="_indicatorCircle"></i></span></button> <button :class="$style.navButton" class="_button" @click="isRoot ? top() : mainRouter.push('/')"><i :class="$style.navButtonIcon" class="ti ti-home"></i></button> <button :class="$style.navButton" class="_button" @click="mainRouter.push('/my/notifications')"> <i :class="$style.navButtonIcon" class="ti ti-bell"></i> - <span v-if="$i?.hasUnreadNotification" :class="$style.navButtonIndicator"> + <span v-if="$i?.hasUnreadNotification" :class="$style.navButtonIndicator" class="_blink"> <span class="_indicateCounter" :class="$style.itemIndicateValueIcon">{{ $i.unreadNotificationsCount > 99 ? '99+' : $i.unreadNotificationsCount }}</span> </span> </button> @@ -96,9 +96,11 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { defineAsyncComponent, provide, onMounted, computed, ref, watch, shallowRef, Ref } from 'vue'; +import { instanceName } from '@@/js/config.js'; +import { CURRENT_STICKY_BOTTOM } from '@@/js/const.js'; +import { isLink } from '@@/js/is-link.js'; import XCommon from './_common_/common.vue'; import type MkStickyContainer from '@/components/global/MkStickyContainer.vue'; -import { instanceName } from '@@/js/config.js'; import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import * as os from '@/os.js'; import { defaultStore } from '@/store.js'; @@ -108,10 +110,8 @@ import { $i } from '@/account.js'; import { PageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js'; import { deviceKind } from '@/scripts/device-kind.js'; import { miLocalStorage } from '@/local-storage.js'; -import { CURRENT_STICKY_BOTTOM } from '@@/js/const.js'; import { useScrollPositionManager } from '@/nirax.js'; import { mainRouter } from '@/router/main.js'; -import { isLink } from '@@/js/is-link.js'; const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue')); const XSidebar = defineAsyncComponent(() => import('@/ui/_common_/navbar.vue')); @@ -451,7 +451,6 @@ $widgets-hide-threshold: 1090px; left: 0; color: var(--MI_THEME-indicator); font-size: 16px; - animation: global-blink 1s infinite; &:has(.itemIndicateValueIcon) { animation: none;