summaryrefslogtreecommitdiff
path: root/packages/client/src
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-07-15 22:09:05 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2022-07-15 22:09:05 +0900
commit92e8a5dbd6d445f94440e4da7c1101276611a98f (patch)
treef792543dace2d5d62765f88d1d908c175514562f /packages/client/src
parentchore(client): tweak style (diff)
downloadmisskey-92e8a5dbd6d445f94440e4da7c1101276611a98f.tar.gz
misskey-92e8a5dbd6d445f94440e4da7c1101276611a98f.tar.bz2
misskey-92e8a5dbd6d445f94440e4da7c1101276611a98f.zip
chore(client): tweak ui
Diffstat (limited to 'packages/client/src')
-rw-r--r--packages/client/src/ui/_common_/navbar-for-mobile.vue367
-rw-r--r--packages/client/src/ui/_common_/navbar.vue537
-rw-r--r--packages/client/src/ui/deck.vue3
-rw-r--r--packages/client/src/ui/universal.vue4
4 files changed, 583 insertions, 328 deletions
diff --git a/packages/client/src/ui/_common_/navbar-for-mobile.vue b/packages/client/src/ui/_common_/navbar-for-mobile.vue
index 8ac4c1150a..cae1d25304 100644
--- a/packages/client/src/ui/_common_/navbar-for-mobile.vue
+++ b/packages/client/src/ui/_common_/navbar-for-mobile.vue
@@ -1,151 +1,165 @@
<template>
<div class="kmwsukvl">
<div class="body">
- <button v-click-anime class="item _button account" @click="openAccountMenu">
- <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
- </button>
- <MkA v-click-anime class="item index" active-class="active" to="/" exact>
- <i class="icon fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span>
- </MkA>
- <template v-for="item in menu">
- <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, { active: navbarItemDef[item].active }]" active-class="active" :to="navbarItemDef[item].to" v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}">
- <i class="icon fa-fw" :class="navbarItemDef[item].icon"></i><span class="text">{{ $ts[navbarItemDef[item].title] }}</span>
- <span v-if="navbarItemDef[item].indicated" class="indicator"><i class="icon fas fa-circle"></i></span>
- </component>
- </template>
- <div class="divider"></div>
- <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime class="item" active-class="active" to="/admin">
- <i class="icon fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
- </MkA>
- <button v-click-anime class="item _button" @click="more">
- <i class="icon fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>
- <span v-if="otherMenuItemIndicated" class="indicator"><i class="icon fas fa-circle"></i></span>
- </button>
- <MkA v-click-anime class="item" active-class="active" to="/settings">
- <i class="icon fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
- </MkA>
- <button class="item _button post" data-cy-open-post-form @click="post">
- <i class="icon fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
- </button>
+ <div class="top">
+ <div class="banner" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"></div>
+ <button v-click-anime v-tooltip.right="$instance.name ?? i18n.ts.instance" class="item _button instance" @click="openInstanceMenu">
+ <img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/>
+ </button>
+ </div>
+ <div class="middle">
+ <MkA v-click-anime class="item index" active-class="active" to="/" exact>
+ <i class="icon fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span>
+ </MkA>
+ <template v-for="item in menu">
+ <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, { active: navbarItemDef[item].active }]" active-class="active" :to="navbarItemDef[item].to" v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}">
+ <i class="icon fa-fw" :class="navbarItemDef[item].icon"></i><span class="text">{{ $ts[navbarItemDef[item].title] }}</span>
+ <span v-if="navbarItemDef[item].indicated" class="indicator"><i class="icon fas fa-circle"></i></span>
+ </component>
+ </template>
+ <div class="divider"></div>
+ <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime class="item" active-class="active" to="/admin">
+ <i class="icon fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
+ </MkA>
+ <button v-click-anime class="item _button" @click="more">
+ <i class="icon fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>
+ <span v-if="otherMenuItemIndicated" class="indicator"><i class="icon fas fa-circle"></i></span>
+ </button>
+ <MkA v-click-anime class="item" active-class="active" to="/settings">
+ <i class="icon fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
+ </MkA>
+ </div>
+ <div class="bottom">
+ <button class="item _button post" data-cy-open-post-form @click="os.post">
+ <i class="icon fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
+ </button>
+ <button v-click-anime class="item _button account" @click="openAccountMenu">
+ <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
+ </button>
+ </div>
</div>
</div>
</template>
-<script lang="ts">
+<script lang="ts" setup>
import { computed, defineAsyncComponent, defineComponent, ref, toRef, watch } from 'vue';
import { host } from '@/config';
import { search } from '@/scripts/search';
import * as os from '@/os';
import { navbarItemDef } from '@/navbar';
-import { openAccountMenu } from '@/account';
+import { openAccountMenu as openAccountMenu_ } from '@/account';
import { defaultStore } from '@/store';
+import { instance } from '@/instance';
+import { i18n } from '@/i18n';
-export default defineComponent({
- setup(props, context) {
- const menu = toRef(defaultStore.state, 'menu');
- const otherMenuItemIndicated = computed(() => {
- for (const def in navbarItemDef) {
- if (menu.value.includes(def)) continue;
- if (navbarItemDef[def].indicated) return true;
- }
- return false;
- });
-
- return {
- host: host,
- accounts: [],
- connection: null,
- menu,
- navbarItemDef: navbarItemDef,
- otherMenuItemIndicated,
- post: os.post,
- search,
- openAccountMenu: (ev) => {
- openAccountMenu({
- withExtraOperation: true,
- }, ev);
- },
- more: () => {
- os.popup(defineAsyncComponent(() => import('@/components/launch-pad.vue')), {}, {
- }, 'closed');
- },
- };
- },
+const menu = toRef(defaultStore.state, 'menu');
+const otherMenuItemIndicated = computed(() => {
+ for (const def in navbarItemDef) {
+ if (menu.value.includes(def)) continue;
+ if (navbarItemDef[def].indicated) return true;
+ }
+ return false;
});
+
+function openAccountMenu(ev: MouseEvent) {
+ openAccountMenu_({
+ withExtraOperation: true,
+ }, ev);
+}
+
+function openInstanceMenu(ev: MouseEvent) {
+ os.popupMenu([{
+ text: instance.name ?? host,
+ type: 'label',
+ }, {
+ type: 'link',
+ text: i18n.ts.instanceInfo,
+ icon: 'fas fa-info-circle',
+ to: '/about',
+ }, {
+ type: 'link',
+ text: i18n.ts.customEmojis,
+ icon: 'fas fa-laugh',
+ to: '/about#emojis',
+ }, {
+ type: 'link',
+ text: i18n.ts.federation,
+ icon: 'fas fa-globe',
+ to: '/about#federation',
+ }], ev.currentTarget ?? ev.target, {
+ align: 'left',
+ });
+}
+
+function more() {
+ os.popup(defineAsyncComponent(() => import('@/components/launch-pad.vue')), {}, {
+ }, 'closed');
+}
</script>
<style lang="scss" scoped>
.kmwsukvl {
- $ui-font-size: 1em; // TODO: どこかに集約したい
- $avatar-size: 32px;
- $avatar-margin: 8px;
-
> .body {
+ display: flex;
+ flex-direction: column;
- > .divider {
- margin: 16px 16px;
- border-top: solid 0.5px var(--divider);
- }
-
- > .item {
- position: relative;
- display: block;
- padding-left: 24px;
- font-size: $ui-font-size;
- line-height: 2.85rem;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- width: 100%;
- text-align: left;
- box-sizing: border-box;
- color: var(--navFg);
-
- > .icon {
- position: relative;
- width: 32px;
- }
-
- > .icon,
- > .avatar {
- margin-right: $avatar-margin;
- }
-
- > .avatar {
- width: $avatar-size;
- height: $avatar-size;
- vertical-align: middle;
- }
+ > .top {
+ position: sticky;
+ top: 0;
+ z-index: 1;
+ padding: 20px 0;
+ background: var(--X14);
+ -webkit-backdrop-filter: var(--blur, blur(8px));
+ backdrop-filter: var(--blur, blur(8px));
- > .indicator {
+ > .banner {
position: absolute;
top: 0;
- left: 20px;
- color: var(--navIndicator);
- font-size: 8px;
- animation: blink 1s infinite;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-size: cover;
+ background-position: center center;
+ -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 15%, rgba(0,0,0,0.75) 100%);
+ mask-image: linear-gradient(0deg, rgba(0,0,0,0) 15%, rgba(0,0,0,0.75) 100%);
}
- > .text {
+ > .instance {
position: relative;
- font-size: 0.9em;
- }
+ display: block;
+ text-align: center;
+ width: 100%;
- &:hover {
- text-decoration: none;
- color: var(--navHoverFg);
+ > .icon {
+ display: inline-block;
+ width: 38px;
+ aspect-ratio: 1;
+ }
}
+ }
- &.active {
- color: var(--navActive);
- }
+ > .bottom {
+ position: sticky;
+ bottom: 0;
+ padding: 20px 0;
+ background: var(--X14);
+ -webkit-backdrop-filter: var(--blur, blur(8px));
+ backdrop-filter: var(--blur, blur(8px));
+
+ > .post {
+ position: relative;
+ display: block;
+ width: 100%;
+ height: 40px;
+ color: var(--fgOnAccent);
+ font-weight: bold;
+ text-align: left;
- &:hover, &.active {
&:before {
content: "";
display: block;
- width: calc(100% - 24px);
+ width: calc(100% - 38px);
height: 100%;
margin: auto;
position: absolute;
@@ -154,52 +168,113 @@ export default defineComponent({
right: 0;
bottom: 0;
border-radius: 999px;
- background: var(--accentedBg);
+ background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
}
- }
-
- &:first-child, &:last-child {
- position: sticky;
- z-index: 1;
- padding-top: 8px;
- padding-bottom: 8px;
- background: var(--X14);
- -webkit-backdrop-filter: var(--blur, blur(8px));
- backdrop-filter: var(--blur, blur(8px));
- }
-
- &:first-child {
- top: 0;
&:hover, &.active {
&:before {
- content: none;
+ background: var(--accentLighten);
}
}
+
+ > .icon {
+ position: relative;
+ margin-left: 30px;
+ margin-right: 8px;
+ width: 32px;
+ }
+
+ > .text {
+ position: relative;
+ }
}
- &:last-child {
- bottom: 0;
- color: var(--fgOnAccent);
+ > .account {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding-left: 30px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 100%;
+ text-align: left;
+ box-sizing: border-box;
+ margin-top: 16px;
- &:before {
- content: "";
- display: block;
- width: calc(100% - 20px);
- height: calc(100% - 20px);
- margin: auto;
+ > .avatar {
+ position: relative;
+ width: 32px;
+ aspect-ratio: 1;
+ margin-right: 8px;
+ }
+ }
+ }
+
+ > .middle {
+ flex: 1;
+
+ > .divider {
+ margin: 16px 16px;
+ border-top: solid 0.5px var(--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(--navFg);
+
+ > .icon {
+ position: relative;
+ width: 32px;
+ margin-right: 8px;
+ }
+
+ > .indicator {
position: absolute;
top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- border-radius: 999px;
- background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
+ left: 20px;
+ color: var(--navIndicator);
+ font-size: 8px;
+ animation: blink 1s infinite;
}
-
+
+ > .text {
+ position: relative;
+ font-size: 0.9em;
+ }
+
+ &:hover {
+ text-decoration: none;
+ color: var(--navHoverFg);
+ }
+
+ &.active {
+ color: var(--navActive);
+ }
+
&:hover, &.active {
&:before {
- background: var(--accentLighten);
+ 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(--accentedBg);
}
}
}
diff --git a/packages/client/src/ui/_common_/navbar.vue b/packages/client/src/ui/_common_/navbar.vue
index 924dda25d7..fbac8425d7 100644
--- a/packages/client/src/ui/_common_/navbar.vue
+++ b/packages/client/src/ui/_common_/navbar.vue
@@ -1,42 +1,53 @@
<template>
<div class="mvcprjjd" :class="{ iconOnly }">
<div class="body">
- <button v-click-anime class="item _button account" @click="openAccountMenu">
- <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
- </button>
- <MkA v-click-anime v-tooltip.right="i18n.ts.timeline" class="item index" active-class="active" to="/" exact>
- <i class="icon fas fa-home fa-fw"></i><span class="text">{{ i18n.ts.timeline }}</span>
- </MkA>
- <template v-for="item in menu">
- <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.right="i18n.ts[navbarItemDef[item].title]"
- class="item _button"
- :class="[item, { active: navbarItemDef[item].active }]"
- active-class="active"
- :to="navbarItemDef[item].to"
- v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}"
- >
- <i class="icon fa-fw" :class="navbarItemDef[item].icon"></i><span class="text">{{ i18n.ts[navbarItemDef[item].title] }}</span>
- <span v-if="navbarItemDef[item].indicated" class="indicator"><i class="icon fas fa-circle"></i></span>
- </component>
- </template>
- <div class="divider"></div>
- <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime v-tooltip.right="i18n.ts.controlPanel" class="item" active-class="active" to="/admin">
- <i class="icon fas fa-door-open fa-fw"></i><span class="text">{{ i18n.ts.controlPanel }}</span>
- </MkA>
- <button v-click-anime class="item _button" @click="more">
- <i class="icon fa fa-ellipsis-h fa-fw"></i><span class="text">{{ i18n.ts.more }}</span>
- <span v-if="otherMenuItemIndicated" class="indicator"><i class="icon fas fa-circle"></i></span>
- </button>
- <MkA v-click-anime v-tooltip.right="i18n.ts.settings" class="item" active-class="active" to="/settings">
- <i class="icon fas fa-cog fa-fw"></i><span class="text">{{ i18n.ts.settings }}</span>
- </MkA>
- <button class="item _button post" data-cy-open-post-form @click="os.post">
- <i class="icon fas fa-pencil-alt fa-fw"></i><span class="text">{{ i18n.ts.note }}</span>
- </button>
+ <div class="top">
+ <div class="banner" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"></div>
+ <button v-click-anime v-tooltip.right="$instance.name ?? i18n.ts.instance" class="item _button instance" @click="openInstanceMenu">
+ <img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/>
+ </button>
+ </div>
+ <div class="middle">
+ <MkA v-click-anime v-tooltip.right="i18n.ts.timeline" class="item index" active-class="active" to="/" exact>
+ <i class="icon fas fa-home fa-fw"></i><span class="text">{{ i18n.ts.timeline }}</span>
+ </MkA>
+ <template v-for="item in menu">
+ <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.right="i18n.ts[navbarItemDef[item].title]"
+ class="item _button"
+ :class="[item, { active: navbarItemDef[item].active }]"
+ active-class="active"
+ :to="navbarItemDef[item].to"
+ v-on="navbarItemDef[item].action ? { click: navbarItemDef[item].action } : {}"
+ >
+ <i class="icon fa-fw" :class="navbarItemDef[item].icon"></i><span class="text">{{ i18n.ts[navbarItemDef[item].title] }}</span>
+ <span v-if="navbarItemDef[item].indicated" class="indicator"><i class="icon fas fa-circle"></i></span>
+ </component>
+ </template>
+ <div class="divider"></div>
+ <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime v-tooltip.right="i18n.ts.controlPanel" class="item" active-class="active" to="/admin">
+ <i class="icon fas fa-door-open fa-fw"></i><span class="text">{{ i18n.ts.controlPanel }}</span>
+ </MkA>
+ <button v-click-anime class="item _button" @click="more">
+ <i class="icon fa fa-ellipsis-h fa-fw"></i><span class="text">{{ i18n.ts.more }}</span>
+ <span v-if="otherMenuItemIndicated" class="indicator"><i class="icon fas fa-circle"></i></span>
+ </button>
+ <MkA v-click-anime v-tooltip.right="i18n.ts.settings" class="item" active-class="active" to="/settings">
+ <i class="icon fas fa-cog fa-fw"></i><span class="text">{{ i18n.ts.settings }}</span>
+ </MkA>
+ </div>
+ <div class="bottom">
+ <button v-tooltip.right="i18n.ts.note" class="item _button post" data-cy-open-post-form @click="os.post">
+ <i class="icon fas fa-pencil-alt fa-fw"></i><span class="text">{{ i18n.ts.note }}</span>
+ </button>
+ <button v-click-anime v-tooltip.right="i18n.ts.account" class="item _button account" @click="openAccountMenu">
+ <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
+ </button>
+ </div>
</div>
</div>
</template>
@@ -48,6 +59,8 @@ import { navbarItemDef } from '@/navbar';
import { $i, openAccountMenu as openAccountMenu_ } from '@/account';
import { defaultStore } from '@/store';
import { i18n } from '@/i18n';
+import { instance } from '@/instance';
+import { host } from '@/config';
const iconOnly = ref(false);
@@ -78,6 +91,30 @@ function openAccountMenu(ev: MouseEvent) {
}, ev);
}
+function openInstanceMenu(ev: MouseEvent) {
+ os.popupMenu([{
+ text: instance.name ?? host,
+ type: 'label',
+ }, {
+ type: 'link',
+ text: i18n.ts.instanceInfo,
+ icon: 'fas fa-info-circle',
+ to: '/about',
+ }, {
+ type: 'link',
+ text: i18n.ts.customEmojis,
+ icon: 'fas fa-laugh',
+ to: '/about#emojis',
+ }, {
+ type: 'link',
+ text: i18n.ts.federation,
+ icon: 'fas fa-globe',
+ to: '/about#federation',
+ }], ev.currentTarget ?? ev.target, {
+ align: 'left',
+ });
+}
+
function more(ev: MouseEvent) {
os.popup(defineAsyncComponent(() => import('@/components/launch-pad.vue')), {
src: ev.currentTarget ?? ev.target,
@@ -88,11 +125,8 @@ function more(ev: MouseEvent) {
<style lang="scss" scoped>
.mvcprjjd {
- $ui-font-size: 1em; // TODO: どこかに集約したい
$nav-width: 250px;
$nav-icon-only-width: 86px;
- $avatar-size: 32px;
- $avatar-margin: 8px;
flex: 0 0 $nav-width;
width: $nav-width;
@@ -103,7 +137,7 @@ function more(ev: MouseEvent) {
top: 0;
left: 0;
z-index: 1001;
- width: $nav-width;
+ width: $nav-icon-only-width;
// ほんとは単に 100vh と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
height: calc(var(--vh, 1vh) * 100);
box-sizing: border-box;
@@ -111,126 +145,188 @@ function more(ev: MouseEvent) {
overflow-x: clip;
background: var(--navBg);
contain: strict;
+ display: flex;
+ flex-direction: column;
+ }
- > .divider {
- margin: 16px 16px;
- border-top: solid 0.5px var(--divider);
- }
-
- > .item {
- position: relative;
- display: block;
- padding-left: 24px;
- font-size: $ui-font-size;
- line-height: 2.85rem;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- width: 100%;
- text-align: left;
- box-sizing: border-box;
- color: var(--navFg);
-
- > .icon {
- position: relative;
- width: 32px;
- }
-
- > .icon,
- > .avatar {
- margin-right: $avatar-margin;
- }
-
- > .avatar {
- width: $avatar-size;
- height: $avatar-size;
- vertical-align: middle;
- }
+ &:not(.iconOnly) {
+ > .body {
+ width: $nav-width;
- > .indicator {
- position: absolute;
+ > .top {
+ position: sticky;
top: 0;
- left: 20px;
- color: var(--navIndicator);
- font-size: 8px;
- animation: blink 1s infinite;
- }
-
- > .text {
- position: relative;
- font-size: 0.9em;
- }
-
- &:hover {
- text-decoration: none;
- color: var(--navHoverFg);
- }
-
- &.active {
- color: var(--navActive);
- }
-
- &:hover, &.active {
- color: var(--accent);
+ z-index: 1;
+ padding: 20px 0;
+ background: var(--X14);
+ -webkit-backdrop-filter: var(--blur, blur(8px));
+ backdrop-filter: var(--blur, blur(8px));
- &:before {
- content: "";
- display: block;
- width: calc(100% - 24px);
- height: 100%;
- margin: auto;
+ > .banner {
position: absolute;
top: 0;
left: 0;
- right: 0;
- bottom: 0;
- border-radius: 999px;
- background: var(--accentedBg);
+ width: 100%;
+ height: 100%;
+ background-size: cover;
+ background-position: center center;
+ -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 15%, rgba(0,0,0,0.75) 100%);
+ mask-image: linear-gradient(0deg, rgba(0,0,0,0) 15%, rgba(0,0,0,0.75) 100%);
+ }
+
+ > .instance {
+ position: relative;
+ display: block;
+ text-align: center;
+ width: 100%;
+
+ > .icon {
+ display: inline-block;
+ width: 38px;
+ aspect-ratio: 1;
+ }
}
}
- &:first-child, &:last-child {
+ > .bottom {
position: sticky;
- z-index: 1;
- padding-top: 8px;
- padding-bottom: 8px;
+ bottom: 0;
+ padding: 20px 0;
background: var(--X14);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
- }
- &:first-child {
- top: 0;
+ > .post {
+ position: relative;
+ display: block;
+ width: 100%;
+ height: 40px;
+ color: var(--fgOnAccent);
+ font-weight: bold;
+ text-align: left;
- &:hover, &.active {
&:before {
- content: none;
+ 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(--buttonGradateA), var(--buttonGradateB));
+ }
+
+ &:hover, &.active {
+ &:before {
+ background: var(--accentLighten);
+ }
+ }
+
+ > .icon {
+ position: relative;
+ margin-left: 30px;
+ margin-right: 8px;
+ width: 32px;
+ }
+
+ > .text {
+ position: relative;
+ }
+ }
+
+ > .account {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding-left: 30px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 100%;
+ text-align: left;
+ box-sizing: border-box;
+ margin-top: 16px;
+
+ > .avatar {
+ position: relative;
+ width: 32px;
+ aspect-ratio: 1;
+ margin-right: 8px;
}
}
}
- &:last-child {
- bottom: 0;
- color: var(--fgOnAccent);
+ > .middle {
+ flex: 1;
- &:before {
- content: "";
- display: block;
- width: calc(100% - 20px);
- height: calc(100% - 20px);
- margin: auto;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- border-radius: 999px;
- background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
+ > .divider {
+ margin: 16px 16px;
+ border-top: solid 0.5px var(--divider);
}
-
- &:hover, &.active {
- &:before {
- background: var(--accentLighten);
+
+ > .item {
+ position: relative;
+ display: block;
+ padding-left: 30px;
+ line-height: 2.85rem;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 100%;
+ text-align: left;
+ box-sizing: border-box;
+ color: var(--navFg);
+
+ > .icon {
+ position: relative;
+ width: 32px;
+ margin-right: 8px;
+ }
+
+ > .indicator {
+ position: absolute;
+ top: 0;
+ left: 20px;
+ color: var(--navIndicator);
+ font-size: 8px;
+ animation: blink 1s infinite;
+ }
+
+ > .text {
+ position: relative;
+ font-size: 0.9em;
+ }
+
+ &:hover {
+ text-decoration: none;
+ color: var(--navHoverFg);
+ }
+
+ &.active {
+ color: var(--navActive);
+ }
+
+ &:hover, &.active {
+ color: var(--accent);
+
+ &:before {
+ content: "";
+ display: block;
+ width: calc(100% - 34px);
+ height: 100%;
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ border-radius: 999px;
+ background: var(--accentedBg);
+ }
}
}
}
@@ -244,67 +340,150 @@ function more(ev: MouseEvent) {
> .body {
width: $nav-icon-only-width;
- > .divider {
- margin: 8px auto;
- width: calc(100% - 32px);
+ > .top {
+ position: sticky;
+ top: 0;
+ z-index: 1;
+ padding: 20px 0;
+ background: var(--X14);
+ -webkit-backdrop-filter: var(--blur, blur(8px));
+ backdrop-filter: var(--blur, blur(8px));
+
+ > .instance {
+ display: block;
+ text-align: center;
+ width: 100%;
+
+ > .icon {
+ display: inline-block;
+ width: 38px;
+ aspect-ratio: 1;
+ }
+ }
}
- > .item {
- padding-left: 0;
- padding: 18px 0;
- width: 100%;
- text-align: center;
- font-size: $ui-font-size;
- line-height: initial;
+ > .bottom {
+ position: sticky;
+ bottom: 0;
+ padding: 20px 0;
+ background: var(--X14);
+ -webkit-backdrop-filter: var(--blur, blur(8px));
+ backdrop-filter: var(--blur, blur(8px));
- > .icon,
- > .avatar {
+ > .post {
display: block;
- margin: 0 auto;
- }
+ position: relative;
+ width: 100%;
+ height: 52px;
+ margin-bottom: 16px;
+ text-align: center;
- > .icon {
- opacity: 0.7;
- }
+ &:before {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ width: 52px;
+ aspect-ratio: 1/1;
+ border-radius: 100%;
+ background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
+ }
- > .text {
- display: none;
- }
+ &:hover, &.active {
+ &:before {
+ background: var(--accentLighten);
+ }
+ }
- &:hover, &.active {
- > .icon, > .text {
- opacity: 1;
+ > .icon {
+ position: relative;
+ color: var(--fgOnAccent);
}
- }
- &:first-child {
- margin-bottom: 8px;
+ > .text {
+ display: none;
+ }
}
- &:last-child {
- margin-top: 8px;
+ > .account {
+ display: block;
+ text-align: center;
+ width: 100%;
+
+ > .avatar {
+ display: inline-block;
+ width: 38px;
+ aspect-ratio: 1;
+ }
+
+ > .text {
+ display: none;
+ }
}
+ }
- &:before {
- width: min-content;
- height: 100%;
- aspect-ratio: 1/1;
- border-radius: 8px;
+ > .middle {
+ flex: 1;
+
+ > .divider {
+ margin: 8px auto;
+ width: calc(100% - 32px);
+ border-top: solid 0.5px var(--divider);
}
- &.post {
- height: $nav-icon-only-width;
+ > .item {
+ display: block;
+ position: relative;
+ padding: 18px 0;
+ width: 100%;
+ text-align: center;
> .icon {
- opacity: 1;
+ display: block;
+ margin: 0 auto;
+ opacity: 0.7;
}
- }
- &.post:before {
- width: calc(100% - 28px);
- height: auto;
- aspect-ratio: 1/1;
- border-radius: 100%;
+ > .text {
+ display: none;
+ }
+
+ > .indicator {
+ position: absolute;
+ top: 6px;
+ left: 24px;
+ color: var(--navIndicator);
+ font-size: 8px;
+ animation: blink 1s infinite;
+ }
+
+ &:hover, &.active {
+ text-decoration: none;
+ color: var(--accent);
+
+ &:before {
+ content: "";
+ display: block;
+ height: 100%;
+ aspect-ratio: 1;
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ border-radius: 999px;
+ background: var(--accentedBg);
+ }
+
+ > .icon, > .text {
+ opacity: 1;
+ }
+ }
}
}
}
diff --git a/packages/client/src/ui/deck.vue b/packages/client/src/ui/deck.vue
index f330c99814..94fee1424e 100644
--- a/packages/client/src/ui/deck.vue
+++ b/packages/client/src/ui/deck.vue
@@ -359,9 +359,10 @@ function moveFocus(id: string, direction: 'up' | 'down' | 'left' | 'right') {
height: calc(var(--vh, 1vh) * 100);
width: 240px;
box-sizing: border-box;
+ contain: strict;
overflow: auto;
overscroll-behavior: contain;
- background: var(--bg);
+ background: var(--navBg);
}
}
</style>
diff --git a/packages/client/src/ui/universal.vue b/packages/client/src/ui/universal.vue
index fe4fc425cd..e4b5de9918 100644
--- a/packages/client/src/ui/universal.vue
+++ b/packages/client/src/ui/universal.vue
@@ -365,11 +365,11 @@ const wallpaper = localStorage.getItem('wallpaper') != null;
height: calc(var(--vh, 1vh) * 100);
width: 240px;
box-sizing: border-box;
+ contain: strict;
overflow: auto;
overscroll-behavior: contain;
- background: var(--bg);
+ background: var(--navBg);
}
-
}
</style>