summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkLaunchPad.vue
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
commit9384f5399da39e53855beb8e7f8ded1aa56bf72e (patch)
treece5959571a981b9c4047da3c7b3fd080aa44222c /packages/frontend/src/components/MkLaunchPad.vue
parentwip: retention for dashboard (diff)
downloadmisskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.gz
misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.bz2
misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.zip
rename: client -> frontend
Diffstat (limited to 'packages/frontend/src/components/MkLaunchPad.vue')
-rw-r--r--packages/frontend/src/components/MkLaunchPad.vue138
1 files changed, 138 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkLaunchPad.vue b/packages/frontend/src/components/MkLaunchPad.vue
new file mode 100644
index 0000000000..1ccc648c72
--- /dev/null
+++ b/packages/frontend/src/components/MkLaunchPad.vue
@@ -0,0 +1,138 @@
+<template>
+<MkModal ref="modal" v-slot="{ type, maxHeight }" :prefer-type="preferedModalType" :anchor="anchor" :transparent-bg="true" :src="src" @click="modal.close()" @closed="emit('closed')">
+ <div class="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
+ <div class="main">
+ <template v-for="item in items">
+ <button v-if="item.action" v-click-anime class="_button" @click="$event => { item.action($event); close(); }">
+ <i class="icon" :class="item.icon"></i>
+ <div class="text">{{ item.text }}</div>
+ <span v-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span>
+ </button>
+ <MkA v-else v-click-anime :to="item.to" @click.passive="close()">
+ <i class="icon" :class="item.icon"></i>
+ <div class="text">{{ item.text }}</div>
+ <span v-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span>
+ </MkA>
+ </template>
+ </div>
+ </div>
+</MkModal>
+</template>
+
+<script lang="ts" setup>
+import { } from 'vue';
+import MkModal from '@/components/MkModal.vue';
+import { navbarItemDef } from '@/navbar';
+import { instanceName } from '@/config';
+import { defaultStore } from '@/store';
+import { i18n } from '@/i18n';
+import { deviceKind } from '@/scripts/device-kind';
+import * as os from '@/os';
+
+const props = withDefaults(defineProps<{
+ src?: HTMLElement;
+ anchor?: { x: string; y: string; };
+}>(), {
+ anchor: () => ({ x: 'right', y: 'center' }),
+});
+
+const emit = defineEmits<{
+ (ev: 'closed'): void;
+}>();
+
+const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'popup' :
+ deviceKind === 'smartphone' ? 'drawer' :
+ 'dialog';
+
+const modal = $ref<InstanceType<typeof MkModal>>();
+
+const menu = defaultStore.state.menu;
+
+const items = Object.keys(navbarItemDef).filter(k => !menu.includes(k)).map(k => navbarItemDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
+ type: def.to ? 'link' : 'button',
+ text: i18n.ts[def.title],
+ icon: def.icon,
+ to: def.to,
+ action: def.action,
+ indicate: def.indicated,
+}));
+
+function close() {
+ modal.close();
+}
+</script>
+
+<style lang="scss" scoped>
+.szkkfdyq {
+ max-height: 100%;
+ width: min(460px, 100vw);
+ padding: 24px;
+ box-sizing: border-box;
+ overflow: auto;
+ overscroll-behavior: contain;
+ text-align: left;
+ border-radius: 16px;
+
+ &.asDrawer {
+ width: 100%;
+ padding: 16px 16px calc(env(safe-area-inset-bottom, 0px) + 16px) 16px;
+ border-radius: 24px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ text-align: center;
+ }
+
+ > .main, > .sub {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
+
+ > * {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ vertical-align: bottom;
+ height: 100px;
+ border-radius: 10px;
+
+ &:hover {
+ color: var(--accent);
+ background: var(--accentedBg);
+ text-decoration: none;
+ }
+
+ > .icon {
+ font-size: 24px;
+ height: 24px;
+ }
+
+ > .text {
+ margin-top: 12px;
+ font-size: 0.8em;
+ line-height: 1.5em;
+ }
+
+ > .indicator {
+ position: absolute;
+ top: 32px;
+ left: 32px;
+ color: var(--indicator);
+ font-size: 8px;
+ animation: blink 1s infinite;
+
+ @media (max-width: 500px) {
+ top: 16px;
+ left: 16px;
+ }
+ }
+ }
+ }
+
+ > .sub {
+ margin-top: 8px;
+ padding-top: 8px;
+ border-top: solid 0.5px var(--divider);
+ }
+}
+</style>