tweak navbar

This commit is contained in:
syuilo 2025-05-03 12:36:34 +09:00
parent 55b50663b3
commit a2f3947bfc
3 changed files with 117 additions and 446 deletions

View File

@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawer_leaveTo : ''" :leaveToClass="prefer.s.animation ? $style.transition_menuDrawer_leaveTo : ''"
> >
<div v-if="drawerMenuShowing" :class="$style.menuDrawer"> <div v-if="drawerMenuShowing" :class="$style.menuDrawer">
<XDrawerMenu/> <XNavbar style="height: 100%;" :asDrawer="true" :showWidgetButton="false"/>
</div> </div>
</Transition> </Transition>
@ -113,7 +113,7 @@ import { i18n } from '@/i18n.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { globalEvents } from '@/events.js'; import { globalEvents } from '@/events.js';
import { store } from '@/store.js'; import { store } from '@/store.js';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import XNavbar from '@/ui/_common_/navbar.vue';
const XStreamIndicator = defineAsyncComponent(() => import('./stream-indicator.vue')); const XStreamIndicator = defineAsyncComponent(() => import('./stream-indicator.vue'));
const XUpload = defineAsyncComponent(() => import('./upload.vue')); const XUpload = defineAsyncComponent(() => import('./upload.vue'));
@ -230,12 +230,6 @@ if ($i) {
left: 0; left: 0;
z-index: 1001; z-index: 1001;
height: 100dvh; height: 100dvh;
width: 240px;
box-sizing: border-box;
contain: strict;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-navBg);
} }
.widgetsDrawerBg { .widgetsDrawerBg {

View File

@ -1,387 +0,0 @@
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="$style.root">
<div :class="$style.top">
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<button class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
</button>
<button class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
<i class="ti ti-bolt ti-fw"></i>
</button>
</div>
<div :class="$style.middle">
<MkA :class="$style.item" :activeClass="$style.active" to="/" exact>
<i :class="$style.itemIcon" class="ti ti-home ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.timeline }}</span>
</MkA>
<template v-for="item in prefer.r.menu.value">
<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" class="_blink">
<span v-if="navbarItemDef[item].indicateValue" class="_indicateCounter" :class="$style.itemIndicateValueIcon">{{ navbarItemDef[item].indicateValue }}</span>
<i v-else class="_indicatorCircle"></i>
</span>
</component>
</template>
<div :class="$style.divider"></div>
<MkA v-if="$i.isAdmin || $i.isModerator" :class="$style.item" :activeClass="$style.active" to="/admin">
<i :class="$style.itemIcon" class="ti ti-dashboard ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.controlPanel }}</span>
</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" 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>
</MkA>
</div>
<div :class="$style.bottom">
<button class="_button" :class="$style.post" data-cy-open-post-form @click="os.post">
<i :class="$style.postIcon" class="ti ti-pencil ti-fw"></i><span style="position: relative;">{{ i18n.ts.note }}</span>
</button>
<button class="_button" :class="$style.account" @click="openAccountMenu">
<MkAvatar :user="$i" :class="$style.avatar"/><MkAcct :class="$style.acct" class="_nowrap" :user="$i"/>
</button>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, defineAsyncComponent } from 'vue';
import { openInstanceMenu } from './common.js';
import * as os from '@/os.js';
import { navbarItemDef } from '@/navbar.js';
import { prefer } from '@/preferences.js';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
import { openAccountMenu as openAccountMenu_ } from '@/accounts.js';
import { $i } from '@/i.js';
import { store } from '@/store.js';
const otherMenuItemIndicated = computed(() => {
for (const def in navbarItemDef) {
if (prefer.r.menu.value.includes(def)) continue;
if (navbarItemDef[def].indicated) return true;
}
return false;
});
function toggleRealtimeMode(ev: MouseEvent) {
os.popupMenu([{
type: 'label',
text: i18n.ts.realtimeMode,
}, {
text: store.s.realtimeMode ? i18n.ts.turnItOff : i18n.ts.turnItOn,
icon: store.s.realtimeMode ? 'ti ti-bolt-off' : 'ti ti-bolt',
action: () => {
store.set('realtimeMode', !store.s.realtimeMode);
window.location.reload();
},
}], ev.currentTarget ?? ev.target);
}
function openAccountMenu(ev: MouseEvent) {
openAccountMenu_({
withExtraOperation: true,
}, ev);
}
function more() {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
closed: () => dispose(),
});
}
</script>
<style lang="scss" module>
.root {
--nav-bg-transparent: color(from var(--MI_THEME-navBg) srgb r g b / 0.5);
display: flex;
flex-direction: column;
}
.top {
--top-height: 80px;
position: sticky;
top: 0;
z-index: 1;
display: flex;
height: var(--top-height);
/* 疑似progressive blur */
&::before {
position: absolute;
z-index: -1;
inset: 0;
content: "";
backdrop-filter: blur(8px);
mask-image: linear-gradient(
to top,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 7.75%,
rgb(0 0 0 / 10.4%) 11.25%,
rgb(0 0 0 / 45%) 23.55%,
rgb(0 0 0 / 55%) 26.45%,
rgb(0 0 0 / 89.6%) 38.75%,
rgb(0 0 0 / 95.1%) 42.25%,
rgb(0 0 0 / 100%) 50%
);
}
&::after {
position: absolute;
z-index: -1;
inset: 0;
bottom: 25%;
content: "";
backdrop-filter: blur(16px);
mask-image: linear-gradient(
to top,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 15.5%,
rgb(0 0 0 / 10.4%) 22.5%,
rgb(0 0 0 / 45%) 47.1%,
rgb(0 0 0 / 55%) 52.9%,
rgb(0 0 0 / 89.6%) 77.5%,
rgb(0 0 0 / 95.1%) 91.9%,
rgb(0 0 0 / 100%) 100%
);
}
}
.banner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center center;
mask-image: linear-gradient(
to top,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 15.5%,
rgb(0 0 0 / 10.4%) 22.5%,
rgb(0 0 0 / 45%) 47.1%,
rgb(0 0 0 / 55%) 52.9%,
rgb(0 0 0 / 89.6%) 77.5%,
rgb(0 0 0 / 95.1%) 91.9%,
rgb(0 0 0 / 100%) 100%
);
pointer-events: none;
opacity: 0.5;
}
.instance {
position: relative;
width: var(--top-height);
}
.instanceIcon {
display: inline-block;
width: 38px;
aspect-ratio: 1;
border-radius: 8px;
}
.realtimeMode {
display: inline-block;
width: var(--top-height);
margin-left: auto;
&.on {
color: var(--MI_THEME-accent);
}
}
.bottom {
position: sticky;
bottom: 0;
padding: 20px 0;
/* 疑似progressive blur */
&::before {
position: absolute;
z-index: -1;
inset: -30px 0 0 0;
content: "";
backdrop-filter: blur(8px);
mask-image: linear-gradient(
to bottom,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 7.75%,
rgb(0 0 0 / 10.4%) 11.25%,
rgb(0 0 0 / 45%) 23.55%,
rgb(0 0 0 / 55%) 26.45%,
rgb(0 0 0 / 89.6%) 38.75%,
rgb(0 0 0 / 95.1%) 42.25%,
rgb(0 0 0 / 100%) 50%
);
}
&::after {
position: absolute;
z-index: -1;
inset: 0;
top: 25%;
content: "";
backdrop-filter: blur(16px);
mask-image: linear-gradient(
to bottom,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 15.5%,
rgb(0 0 0 / 10.4%) 22.5%,
rgb(0 0 0 / 45%) 47.1%,
rgb(0 0 0 / 55%) 52.9%,
rgb(0 0 0 / 89.6%) 77.5%,
rgb(0 0 0 / 95.1%) 91.9%,
rgb(0 0 0 / 100%) 100%
);
}
}
.post {
position: relative;
display: block;
width: 100%;
height: 40px;
color: var(--MI_THEME-fgOnAccent);
font-weight: bold;
text-align: left;
&::before {
content: "";
display: block;
width: calc(100% - 38px);
height: 100%;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 999px;
background: linear-gradient(90deg, var(--MI_THEME-buttonGradateA), var(--MI_THEME-buttonGradateB));
}
&:hover, &.active {
&::before {
background: hsl(from var(--MI_THEME-accent) h s calc(l + 10));
}
}
}
.postIcon {
position: relative;
margin-left: 30px;
margin-right: 8px;
width: 32px;
}
.account {
position: relative;
display: flex;
align-items: center;
padding-left: 30px;
width: 100%;
text-align: left;
box-sizing: border-box;
margin-top: 16px;
}
.avatar {
display: block;
flex-shrink: 0;
position: relative;
width: 32px;
aspect-ratio: 1;
margin-right: 8px;
}
.acct {
display: block;
flex-shrink: 1;
padding-right: 8px;
}
.middle {
flex: 1;
}
.divider {
margin: 16px 16px;
border-top: solid 0.5px var(--MI_THEME-divider);
}
.item {
position: relative;
display: block;
padding-left: 24px;
line-height: 2.85rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
text-align: left;
box-sizing: border-box;
color: var(--MI_THEME-navFg);
&:hover {
text-decoration: none;
color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17)));
}
&.active {
color: var(--MI_THEME-navActive);
}
&:hover, &.active {
&::before {
content: "";
display: block;
width: calc(100% - 24px);
height: 100%;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 999px;
background: var(--MI_THEME-accentedBg);
}
}
}
.itemIcon {
position: relative;
width: 32px;
margin-right: 8px;
}
.itemIndicator {
position: absolute;
top: 0;
left: 20px;
color: var(--MI_THEME-navIndicator);
font-size: 8px;
&:has(.itemIndicateValueIcon) {
animation: none;
left: auto;
right: 20px;
}
}
.itemText {
position: relative;
font-size: 0.9em;
}
</style>

View File

@ -10,6 +10,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu"> <button v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon" style="viewTransitionName: navbar-serverIcon;"/> <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon" style="viewTransitionName: navbar-serverIcon;"/>
</button> </button>
<button v-if="!iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
<i class="ti ti-bolt ti-fw"></i>
</button>
</div> </div>
<div :class="$style.middle"> <div :class="$style.middle">
<MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact> <MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact>
@ -50,7 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-if="showWidgetButton" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')"> <button v-if="showWidgetButton" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
<i class="ti ti-apps ti-fw"></i> <i class="ti ti-apps ti-fw"></i>
</button> </button>
<button v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode"> <button v-if="iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
<i class="ti ti-bolt ti-fw"></i> <i class="ti ti-bolt ti-fw"></i>
</button> </button>
<button v-tooltip.noDelay.right="i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="() => { os.post(); }"> <button v-tooltip.noDelay.right="i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="() => { os.post(); }">
@ -79,16 +82,18 @@ SPDX-License-Identifier: AGPL-3.0-only
</svg> </svg>
<button class="_button" :class="$style.subButtonClickable" @click="menuEdit"><i :class="$style.subButtonIcon" class="ti ti-settings-2"></i></button> <button class="_button" :class="$style.subButtonClickable" @click="menuEdit"><i :class="$style.subButtonIcon" class="ti ti-settings-2"></i></button>
</div> </div>
<div :class="$style.subButtonGapFill"></div> <template v-if="!props.asDrawer">
<div :class="$style.subButtonGapFillDivider"></div> <div :class="$style.subButtonGapFill"></div>
<div :class="[$style.subButton, $style.toggleButton]"> <div :class="$style.subButtonGapFillDivider"></div>
<svg viewBox="0 0 16 64" :class="$style.subButtonShape"> <div :class="[$style.subButton, $style.toggleButton]">
<g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)"> <svg viewBox="0 0 16 64" :class="$style.subButtonShape">
<path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/> <g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
</g> <path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
</svg> </g>
<button class="_button" :class="$style.subButtonClickable" @click="toggleIconOnly"><i v-if="iconOnly" class="ti ti-chevron-right" :class="$style.subButtonIcon"></i><i v-else class="ti ti-chevron-left" :class="$style.subButtonIcon"></i></button> </svg>
</div> <button class="_button" :class="$style.subButtonClickable" @click="toggleIconOnly"><i v-if="iconOnly" class="ti ti-chevron-right" :class="$style.subButtonIcon"></i><i v-else class="ti ti-chevron-left" :class="$style.subButtonIcon"></i></button>
</div>
</template>
</div> </div>
</div> </div>
</template> </template>
@ -111,15 +116,16 @@ const router = useRouter();
const props = defineProps<{ const props = defineProps<{
showWidgetButton?: boolean; showWidgetButton?: boolean;
asDrawer?: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'widgetButtonClick'): void; (ev: 'widgetButtonClick'): void;
}>(); }>();
const forceIconOnly = ref(window.innerWidth <= 1279); const forceIconOnly = ref(!props.asDrawer && window.innerWidth <= 1279);
const iconOnly = computed(() => { const iconOnly = computed(() => {
return forceIconOnly.value || (store.r.menuDisplay.value === 'sideIcon'); return !props.asDrawer && (forceIconOnly.value || (store.r.menuDisplay.value === 'sideIcon'));
}); });
const otherMenuItemIndicated = computed(() => { const otherMenuItemIndicated = computed(() => {
@ -208,13 +214,51 @@ function menuEdit() {
overscroll-behavior: contain; overscroll-behavior: contain;
background: var(--MI_THEME-navBg); background: var(--MI_THEME-navBg);
contain: strict; contain: strict;
display: flex;
flex-direction: column;
direction: rtl; // direction: rtl; //
} }
.top { .top {
direction: ltr; direction: ltr;
/* 疑似progressive blur */
&::before {
position: absolute;
z-index: -1;
inset: 0;
content: "";
backdrop-filter: blur(8px);
mask-image: linear-gradient(
to top,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 7.75%,
rgb(0 0 0 / 10.4%) 11.25%,
rgb(0 0 0 / 45%) 23.55%,
rgb(0 0 0 / 55%) 26.45%,
rgb(0 0 0 / 89.6%) 38.75%,
rgb(0 0 0 / 95.1%) 42.25%,
rgb(0 0 0 / 100%) 50%
);
}
&::after {
position: absolute;
z-index: -1;
inset: 0;
bottom: 25%;
content: "";
backdrop-filter: blur(16px);
mask-image: linear-gradient(
to top,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 15.5%,
rgb(0 0 0 / 10.4%) 22.5%,
rgb(0 0 0 / 45%) 47.1%,
rgb(0 0 0 / 55%) 52.9%,
rgb(0 0 0 / 89.6%) 77.5%,
rgb(0 0 0 / 95.1%) 91.9%,
rgb(0 0 0 / 100%) 100%
);
}
} }
.middle { .middle {
@ -223,6 +267,47 @@ function menuEdit() {
.bottom { .bottom {
direction: ltr; direction: ltr;
/* 疑似progressive blur */
&::before {
position: absolute;
z-index: -1;
inset: -30px 0 0 0;
content: "";
backdrop-filter: blur(8px);
mask-image: linear-gradient(
to bottom,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 7.75%,
rgb(0 0 0 / 10.4%) 11.25%,
rgb(0 0 0 / 45%) 23.55%,
rgb(0 0 0 / 55%) 26.45%,
rgb(0 0 0 / 89.6%) 38.75%,
rgb(0 0 0 / 95.1%) 42.25%,
rgb(0 0 0 / 100%) 50%
);
pointer-events: none;
}
&::after {
position: absolute;
z-index: -1;
inset: 0;
top: 25%;
content: "";
backdrop-filter: blur(16px);
mask-image: linear-gradient(
to bottom,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 15.5%,
rgb(0 0 0 / 10.4%) 22.5%,
rgb(0 0 0 / 45%) 47.1%,
rgb(0 0 0 / 55%) 52.9%,
rgb(0 0 0 / 89.6%) 77.5%,
rgb(0 0 0 / 95.1%) 91.9%,
rgb(0 0 0 / 100%) 100%
);
}
} }
.subButtons { .subButtons {
@ -307,29 +392,18 @@ function menuEdit() {
} }
.top { .top {
--top-height: 80px;
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 1; z-index: 1;
padding: 20px 0; display: flex;
background: var(--nav-bg-transparent); height: var(--top-height);
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(8px));
} }
.instance { .instance {
position: relative; position: relative;
display: block; width: var(--top-height);
text-align: center;
width: 100%;
&:focus-visible {
outline: none;
> .instanceIcon {
outline: 2px solid var(--MI_THEME-focus);
outline-offset: 2px;
}
}
} }
.instanceIcon { .instanceIcon {
@ -339,26 +413,22 @@ function menuEdit() {
border-radius: 8px; border-radius: 8px;
} }
.bottom {
position: sticky;
bottom: 0;
background: var(--nav-bg-transparent);
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(8px));
}
.realtimeMode { .realtimeMode {
display: block; display: inline-block;
position: relative; width: var(--top-height);
width: 100%; margin-left: auto;
height: 52px;
text-align: center;
&.on { &.on {
color: var(--MI_THEME-accent); color: var(--MI_THEME-accent);
} }
} }
.bottom {
position: sticky;
bottom: 0;
padding-top: 20px;
}
.post { .post {
position: relative; position: relative;
display: block; display: block;
@ -548,9 +618,6 @@ function menuEdit() {
top: 0; top: 0;
z-index: 1; z-index: 1;
padding: 20px 0; padding: 20px 0;
background: var(--nav-bg-transparent);
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(8px));
} }
.instance { .instance {
@ -579,9 +646,6 @@ function menuEdit() {
position: sticky; position: sticky;
bottom: 0; bottom: 0;
padding-top: 20px; padding-top: 20px;
background: var(--nav-bg-transparent);
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(8px));
} }
.widget { .widget {
@ -690,7 +754,7 @@ function menuEdit() {
.item { .item {
display: block; display: block;
position: relative; position: relative;
padding: 18px 0; padding: 16px 0;
width: 100%; width: 100%;
text-align: center; text-align: center;