Home slide, apply kanban CSS
This commit is contained in:
parent
88f5cc416e
commit
d20a391d91
3 changed files with 177 additions and 30 deletions
|
@ -24,6 +24,9 @@
|
|||
@swiper="setSwiperRef"
|
||||
@slide-change="onSlideChange"
|
||||
>
|
||||
<swiper-slide v-slot="{ isActive }">
|
||||
<XKanban v-if="isActive"/>
|
||||
</swiper-slide>
|
||||
<swiper-slide v-slot="{ isActive }">
|
||||
<MkSpacer :content-max="800" v-if="isActive">
|
||||
<XNotes :pagination="paginationForLocal" />
|
||||
|
@ -110,9 +113,10 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, watch, onMounted } from "vue";
|
||||
import { computed, watch, onMounted, provide } from "vue";
|
||||
import * as os from "@/os";
|
||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import XKanban from "@/ui/visitor/kanban.vue";
|
||||
import XNotes from "@/components/MkNotes.vue";
|
||||
import XUsers from "./explore.users.vue";
|
||||
import XChannelList from "@/components/MkChannelList.vue";
|
||||
|
@ -127,7 +131,17 @@ import { DetailedInstanceMetadata } from "calckey-js/built/entities";
|
|||
import "swiper/scss";
|
||||
import "swiper/scss/virtual";
|
||||
|
||||
const DESKTOP_THRESHOLD = 1100;
|
||||
let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||
matchMedia(`(min-width: ${DESKTOP_THRESHOLD - 1}px)`).onchange = (mql) => {
|
||||
isDesktop = mql.matches;
|
||||
syncSlide(isDesktop ? 1 : 0);
|
||||
};
|
||||
|
||||
provide("shouldOmitHeaderTitle", true);
|
||||
|
||||
const tabs = [
|
||||
"home",
|
||||
"local",
|
||||
"remote",
|
||||
"channels",
|
||||
|
@ -141,6 +155,11 @@ watch($$(tab), () => syncSlide(tabs.indexOf(tab)));
|
|||
const headerActions = $computed(() => []);
|
||||
|
||||
const headerTabs = $computed(() => [
|
||||
!isDesktop ? {
|
||||
key: "home",
|
||||
icon: "ph-house ph-bold ph-lg",
|
||||
title: i18n.ts.home,
|
||||
} : [],
|
||||
{
|
||||
key: "local",
|
||||
icon: "ph-lightning ph-bold ph-lg",
|
||||
|
@ -196,7 +215,7 @@ function syncSlide(index) {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
syncSlide(tabs.indexOf(swiperRef.activeIndex));
|
||||
syncSlide(isDesktop ? 1 : 0);
|
||||
});
|
||||
|
||||
let meta = $ref<DetailedInstanceMetadata>();
|
||||
|
@ -215,7 +234,6 @@ const paginationForLocal = {
|
|||
days: 14,
|
||||
},
|
||||
};
|
||||
|
||||
const paginationForRemote = {
|
||||
endpoint: "notes/featured" as const,
|
||||
limit: 20,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
:class="{ wallpaper, isMobile, centered: ui === 'classic' }"
|
||||
>
|
||||
<XSidebar v-if="!isMobile && $i" />
|
||||
<XKanban class="kanban" full v-if="!$i" />
|
||||
<XKanban sticky v-if="isDesktop" />
|
||||
|
||||
<MkStickyContainer class="contents">
|
||||
<template #header
|
||||
|
@ -196,7 +196,7 @@ const DESKTOP_THRESHOLD = 1100;
|
|||
const MOBILE_THRESHOLD = 500;
|
||||
|
||||
// デスクトップでウィンドウを狭くしたときモバイルUIが表示されて欲しいことはあるので deviceKind === 'desktop' の判定は行わない
|
||||
const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||
let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||
const isMobile = ref(
|
||||
deviceKind === "smartphone" || window.innerWidth <= MOBILE_THRESHOLD
|
||||
);
|
||||
|
@ -334,15 +334,9 @@ async function startGroup(): void {
|
|||
mainRouter.push(`/my/messaging/group/${group.id}`);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!isDesktop.value) {
|
||||
matchMedia(`(min-width: ${DESKTOP_THRESHOLD - 1}px)`).onchange = (
|
||||
mql
|
||||
) => {
|
||||
if (mql.matches) isDesktop.value = true;
|
||||
};
|
||||
}
|
||||
});
|
||||
matchMedia(`(min-width: ${DESKTOP_THRESHOLD - 1}px)`).onchange = (mql) => {
|
||||
isDesktop = mql.matches;
|
||||
};
|
||||
|
||||
const onContextmenu = (ev: MouseEvent) => {
|
||||
const isLink = (el: HTMLElement) => {
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
<template>
|
||||
<div class="instance-info-container" :class="expanded">
|
||||
<div class="instance-info-container"
|
||||
:class="{ sticky }"
|
||||
>
|
||||
<header
|
||||
id="instance-info"
|
||||
v-on:scroll.passive="onScroll"
|
||||
>
|
||||
<div class="ticker" v-if="!expanded">
|
||||
<!-- <div class="ticker" v-if="!expanded">
|
||||
<img
|
||||
class="logo"
|
||||
:src="meta.logoImageUrl"
|
||||
/>
|
||||
<h1>
|
||||
<MkA
|
||||
to="/" class="link"
|
||||
>{{ instanceName }}</MkA>
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<MkA
|
||||
to="/" class="link"
|
||||
>{{ instanceName }}</MkA>
|
||||
</h1>
|
||||
<p>{{ meta.description || i18n.ts.introMisskey }}</p>
|
||||
</div>
|
||||
<MkButton
|
||||
primary
|
||||
rounded
|
||||
@click.stop="expanded = true"
|
||||
>{{ i18n.ts.instanceInfo }}</MkButton>
|
||||
</div> -->
|
||||
<img class="banner" :src="meta.backgroundImageUrl" />
|
||||
<div class="content" v-if="expanded">
|
||||
<div class="content">
|
||||
<div class="header">
|
||||
<img
|
||||
class="logo"
|
||||
|
@ -183,14 +194,15 @@ import XSignupDialog from "@/components/MkSignupDialog.vue";
|
|||
import MkKeyValue from "@/components/MkKeyValue.vue";
|
||||
import MkMention from "@/components/MkMention.vue";
|
||||
|
||||
let expanded = $ref(false);
|
||||
// let expanded = $ref(window.innerWidth >= 1000);
|
||||
|
||||
matchMedia("(max-width: 1000px)").onchange = (mql) => {
|
||||
console.log("ran");
|
||||
expanded = !mql.matches;
|
||||
};
|
||||
// matchMedia("(max-width: 1000px)").onchange = (mql) => {
|
||||
// expanded = !mql.matches;
|
||||
// };
|
||||
|
||||
expanded = true;
|
||||
defineProps<{
|
||||
sticky?: boolean;
|
||||
}>();
|
||||
|
||||
let meta = $ref<DetailedInstanceMetadata>();
|
||||
|
||||
|
@ -234,8 +246,131 @@ function signup() {
|
|||
function showMenu(ev) {
|
||||
openHelpMenu_(ev);
|
||||
}
|
||||
function onScroll(ev) {
|
||||
if (ev.target.scrollTop == 0) {
|
||||
expanded = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.instance-info-container {
|
||||
&.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
max-height: 100vh;
|
||||
overflow: hidden auto;
|
||||
min-width: 400px;
|
||||
width: 450px;
|
||||
}
|
||||
margin-left: -1px;
|
||||
border-right: 1px solid var(--divider);
|
||||
box-shadow: 0 0 48px -24px rgba(0,0,0,0.1);
|
||||
z-index: 9000;
|
||||
}
|
||||
#instance-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: var(--accent);
|
||||
transition: transform .4s cubic-bezier(.5,0,0,1);
|
||||
.banner {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: calc(100% + 2px);
|
||||
margin-inline: -1px;
|
||||
min-height: 250px;
|
||||
max-height: 250px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
mask: linear-gradient(to bottom, black, calc(100% - 50px), transparent);
|
||||
transition: min-height .4s, max-height .4s, filter .7s;
|
||||
}
|
||||
> .content {
|
||||
--margin: 32px;
|
||||
--radius: 16px;
|
||||
display: flow-root;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: var(--bg);
|
||||
border-radius: var(--radius) var(--radius) 0 0;
|
||||
margin-top: calc(0px - var(--radius));
|
||||
padding: 0 var(--margin);
|
||||
text-align: center;
|
||||
flex-grow: 1;
|
||||
max-width: 600px;
|
||||
margin-inline: auto;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
> .header {
|
||||
position: relative;
|
||||
margin-top: -50px;
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -5px calc(0px - var(--margin));
|
||||
bottom: -100px;
|
||||
backdrop-filter: blur(60px);
|
||||
filter: brightness(1.2);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
clip-path: inset(55px 0 0 0 round var(--radius));
|
||||
mask: linear-gradient(transparent 55px, #000 50px, transparent);
|
||||
-webkit-mask: linear-gradient(transparent 55px, #000 50px, transparent);
|
||||
}
|
||||
> .logo {
|
||||
height: 90px;
|
||||
min-width: 90px;
|
||||
border-radius: var(--radius);
|
||||
margin-top: -5px;
|
||||
transition: transform .4s cubic-bezier(0.5,0,0,1);
|
||||
}
|
||||
> h1 {
|
||||
margin-block: .7em;
|
||||
font-size: 1.5em;
|
||||
color: var(--fgHighlighted)
|
||||
}
|
||||
}
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 100px;
|
||||
background: var(--buttonBg)
|
||||
}
|
||||
.about {
|
||||
position: relative;
|
||||
font-size: 1.05em;
|
||||
.desc {
|
||||
display: block;
|
||||
}
|
||||
.collapsed {
|
||||
position: relative;
|
||||
max-height: calc(9em + 50px);
|
||||
mask: linear-gradient(black calc(100% - 64px), transparent);
|
||||
-webkit-mask: linear-gradient(
|
||||
black calc(100% - 64px),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
}
|
||||
.announcements {
|
||||
text-align: initial;
|
||||
}
|
||||
> :not(.header) {
|
||||
max-width: 600px;
|
||||
margin-inline: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
section {
|
||||
margin-top: 2em;
|
||||
}
|
||||
._formLinksGrid {
|
||||
grid-template-columns: repeat(2,minmax(150px,1fr));
|
||||
text-align: initial;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue