mobile WIP
This commit is contained in:
parent
a99dfdb8ff
commit
ecd784ad42
12 changed files with 147 additions and 20 deletions
|
|
@ -27,5 +27,10 @@ const props = defineProps({ row: Object })
|
|||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile() {
|
||||
grid-template-columns: mobile-vw(60px) 1fr;
|
||||
padding-top: mobile-vw(8px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ defineExpose({
|
|||
position: fixed;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: calc(100 * var(--vh));
|
||||
overflow: hidden;
|
||||
|
||||
.viewport-stage {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div v-if="global" class="layout">
|
||||
<site-header :copy="headerCopy" :dl="headerDl" />
|
||||
<site-header v-show="showHeader" :copy="headerCopy" :dl="headerDl" />
|
||||
|
||||
<client-only>
|
||||
<mosaic-scroll :items="mosaicItems" />
|
||||
|
|
@ -21,13 +21,16 @@ import { computed} from 'vue';
|
|||
import { useSeoMeta } from '@unhead/vue'
|
||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||
import { useRoute } from 'vue-router';
|
||||
import useBreakpoints from '@/composables/useBreakpoints';
|
||||
|
||||
const { data: global } = await useStrapiGlobal()
|
||||
const route = useRoute()
|
||||
const { data: global } = await useStrapiGlobal()
|
||||
const {isMobile} = useBreakpoints()
|
||||
|
||||
const headerCopy = computed(() => global.value?.header_copy)
|
||||
const headerDl = computed(() => global.value?.header_dl)
|
||||
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
||||
const showHeader = computed(() => !(isMobile && route.name === 'mosaic-item'))
|
||||
|
||||
// SEO
|
||||
const seo = computed(() => global.value?.seo)
|
||||
|
|
|
|||
|
|
@ -14,13 +14,19 @@
|
|||
|
||||
<div class="window content" @click.stop data-lenis-prevent>
|
||||
<lenis instance="mosaic-modal">
|
||||
<button class="close mobile-only" @click="onClose">
|
||||
Close X
|
||||
</button>
|
||||
|
||||
<h1 class="title">{{ item.title }}</h1>
|
||||
|
||||
<strapi-map :items="item.content" mediaDS="42vw" />
|
||||
</lenis>
|
||||
</div>
|
||||
|
||||
<button class="window close" @click="onClose">Close X</button>
|
||||
<button class="window close desktop-only" @click="onClose">
|
||||
Close X
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -100,5 +106,53 @@ const onClose = () => router.push('/')
|
|||
@include label;
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile() {
|
||||
padding: var(--layout-margin);
|
||||
height: calc(100 * var(--vh));
|
||||
grid-template-rows: auto 1fr;
|
||||
|
||||
.meta {
|
||||
grid-column: 1/-1;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
display: grid;
|
||||
gap: var(--layout-column-gap);
|
||||
align-items: flex-start;
|
||||
}
|
||||
.window {
|
||||
border-radius: mobile-vw(10px);
|
||||
|
||||
&.dl {
|
||||
padding: mobile-vw(12px) mobile-vw(10px);
|
||||
}
|
||||
&.gif {
|
||||
.strapi-media {
|
||||
max-width: mobile-vw(80px);
|
||||
max-height: mobile-vw(80px);
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
&.content {
|
||||
grid-column: 1/-1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.lenis {
|
||||
max-height: unset;
|
||||
height: 100%;
|
||||
padding: mobile-vw(54px) mobile-vw(24px) mobile-vw(34px);
|
||||
}
|
||||
.strapi-media {
|
||||
border-radius: mobile-vw(8px);
|
||||
}
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ const onIntersect = (isIntersecting) => {
|
|||
|
||||
<style lang="scss">
|
||||
.mosaic-viewport {
|
||||
height: 100vh;
|
||||
height: calc(100 * var(--vh));
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
|
|
|||
|
|
@ -57,5 +57,27 @@ const props = defineProps({
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile() {
|
||||
padding: mobile-vw(27px) var(--layout-margin);
|
||||
|
||||
.logo {
|
||||
width: mobile-vw(93px);
|
||||
}
|
||||
.info {
|
||||
border-radius: mobile-vw(10px);
|
||||
padding: mobile-vw(12px) mobile-vw(10px);
|
||||
grid-column: 2 / span 4;
|
||||
|
||||
.copy {
|
||||
margin-bottom: mobile-vw(18px);
|
||||
|
||||
p,
|
||||
a {
|
||||
margin: mobile-vw(6px) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -36,5 +36,21 @@ const props = defineProps({
|
|||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: desktop-vw(4px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@include mobile() {
|
||||
pre {
|
||||
padding: mobile-vw(20px);
|
||||
border-radius: mobile-vw(8px);
|
||||
max-width: calc(100vw - (6 * var(--layout-margin)));
|
||||
}
|
||||
img {
|
||||
border-radius: mobile-vw(8px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -31,5 +31,9 @@ const props = defineProps({
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: desktop-vw(30px);
|
||||
|
||||
@include mobile() {
|
||||
gap: mobile-vw(30px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
25
src/composables/useBreakpoints.js
Normal file
25
src/composables/useBreakpoints.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { breakpoints } from '@/libs/theme'
|
||||
import { tryOnMounted, useWindowSize } from '@vueuse/core'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const { width } = useWindowSize()
|
||||
|
||||
export default () => {
|
||||
const mounted = ref(false)
|
||||
|
||||
tryOnMounted(() => {
|
||||
if (!import.meta.env.SSR) mounted.value = true
|
||||
})
|
||||
|
||||
const isMobile = computed(
|
||||
() => mounted.value && width.value < breakpoints.mobile,
|
||||
)
|
||||
const isDesktop = computed(
|
||||
() => mounted.value && width.value >= breakpoints.mobile,
|
||||
)
|
||||
|
||||
return {
|
||||
isMobile,
|
||||
isDesktop,
|
||||
}
|
||||
}
|
||||
|
|
@ -164,10 +164,16 @@ export const useInfiniteScroll = (options = {}) => {
|
|||
}
|
||||
|
||||
// Handle virtual-scroll delta events from Lenis
|
||||
const onVirtualScroll = async ({ deltaY }) => {
|
||||
const onVirtualScroll = async ({ deltaY, event }) => {
|
||||
if (!state.active) return
|
||||
|
||||
deltaY *= 3
|
||||
const isTouch = event.type.includes('touch')
|
||||
|
||||
if (isTouch) {
|
||||
deltaY *= 10
|
||||
} else {
|
||||
deltaY *= 3
|
||||
}
|
||||
|
||||
gsap.to(state, {
|
||||
scrollY: state.scrollY + deltaY,
|
||||
|
|
@ -188,11 +194,8 @@ export const useInfiniteScroll = (options = {}) => {
|
|||
}
|
||||
}
|
||||
|
||||
// Setup Lenis — we use virtual-scroll instead of scroll so the DOM
|
||||
// height can stay at 100vh with overflow: hidden.
|
||||
const lenis = useLenis()
|
||||
|
||||
// Attach the virtual-scroll listener once Lenis is ready
|
||||
const lenis = useLenis()
|
||||
watch(
|
||||
lenis,
|
||||
(instance) => {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
font-family: var(--font-sans);
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
@include size-font(12px, 12px);
|
||||
@include size-font(12px, 14px);
|
||||
}
|
||||
|
||||
@mixin p {
|
||||
|
|
@ -39,19 +39,19 @@
|
|||
font-family: var(--font-sans);
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
@include size-font(8px, 8px);
|
||||
@include size-font(8px, 14px);
|
||||
}
|
||||
|
||||
@mixin label {
|
||||
font-family: var(--font-sans);
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
@include size-font(7px, 7px);
|
||||
@include size-font(7px, 12px);
|
||||
}
|
||||
|
||||
@mixin code {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
@include size-font(12px, 12px);
|
||||
@include size-font(12px, 14px);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
// Type
|
||||
|
|
@ -60,7 +59,3 @@ dt {
|
|||
code {
|
||||
@include code;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue