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;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include mobile() {
|
||||||
|
grid-template-columns: mobile-vw(60px) 1fr;
|
||||||
|
padding-top: mobile-vw(8px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ defineExpose({
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: calc(100 * var(--vh));
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.viewport-stage {
|
.viewport-stage {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="global" class="layout">
|
<div v-if="global" class="layout">
|
||||||
<site-header :copy="headerCopy" :dl="headerDl" />
|
<site-header v-show="showHeader" :copy="headerCopy" :dl="headerDl" />
|
||||||
|
|
||||||
<client-only>
|
<client-only>
|
||||||
<mosaic-scroll :items="mosaicItems" />
|
<mosaic-scroll :items="mosaicItems" />
|
||||||
|
|
@ -21,13 +21,16 @@ import { computed} from 'vue';
|
||||||
import { useSeoMeta } from '@unhead/vue'
|
import { useSeoMeta } from '@unhead/vue'
|
||||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import useBreakpoints from '@/composables/useBreakpoints';
|
||||||
|
|
||||||
const { data: global } = await useStrapiGlobal()
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const { data: global } = await useStrapiGlobal()
|
||||||
|
const {isMobile} = useBreakpoints()
|
||||||
|
|
||||||
const headerCopy = computed(() => global.value?.header_copy)
|
const headerCopy = computed(() => global.value?.header_copy)
|
||||||
const headerDl = computed(() => global.value?.header_dl)
|
const headerDl = computed(() => global.value?.header_dl)
|
||||||
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
||||||
|
const showHeader = computed(() => !(isMobile && route.name === 'mosaic-item'))
|
||||||
|
|
||||||
// SEO
|
// SEO
|
||||||
const seo = computed(() => global.value?.seo)
|
const seo = computed(() => global.value?.seo)
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,19 @@
|
||||||
|
|
||||||
<div class="window content" @click.stop data-lenis-prevent>
|
<div class="window content" @click.stop data-lenis-prevent>
|
||||||
<lenis instance="mosaic-modal">
|
<lenis instance="mosaic-modal">
|
||||||
|
<button class="close mobile-only" @click="onClose">
|
||||||
|
Close X
|
||||||
|
</button>
|
||||||
|
|
||||||
<h1 class="title">{{ item.title }}</h1>
|
<h1 class="title">{{ item.title }}</h1>
|
||||||
|
|
||||||
<strapi-map :items="item.content" mediaDS="42vw" />
|
<strapi-map :items="item.content" mediaDS="42vw" />
|
||||||
</lenis>
|
</lenis>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="window close" @click="onClose">Close X</button>
|
<button class="window close desktop-only" @click="onClose">
|
||||||
|
Close X
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -100,5 +106,53 @@ const onClose = () => router.push('/')
|
||||||
@include label;
|
@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>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ const onIntersect = (isIntersecting) => {
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.mosaic-viewport {
|
.mosaic-viewport {
|
||||||
height: 100vh;
|
height: calc(100 * var(--vh));
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
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>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -36,5 +36,21 @@ const props = defineProps({
|
||||||
a {
|
a {
|
||||||
text-decoration: underline;
|
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>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -31,5 +31,9 @@ const props = defineProps({
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: desktop-vw(30px);
|
gap: desktop-vw(30px);
|
||||||
|
|
||||||
|
@include mobile() {
|
||||||
|
gap: mobile-vw(30px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</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
|
// Handle virtual-scroll delta events from Lenis
|
||||||
const onVirtualScroll = async ({ deltaY }) => {
|
const onVirtualScroll = async ({ deltaY, event }) => {
|
||||||
if (!state.active) return
|
if (!state.active) return
|
||||||
|
|
||||||
deltaY *= 3
|
const isTouch = event.type.includes('touch')
|
||||||
|
|
||||||
|
if (isTouch) {
|
||||||
|
deltaY *= 10
|
||||||
|
} else {
|
||||||
|
deltaY *= 3
|
||||||
|
}
|
||||||
|
|
||||||
gsap.to(state, {
|
gsap.to(state, {
|
||||||
scrollY: state.scrollY + deltaY,
|
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
|
// Attach the virtual-scroll listener once Lenis is ready
|
||||||
|
const lenis = useLenis()
|
||||||
watch(
|
watch(
|
||||||
lenis,
|
lenis,
|
||||||
(instance) => {
|
(instance) => {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
@include size-font(12px, 12px);
|
@include size-font(12px, 14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin p {
|
@mixin p {
|
||||||
|
|
@ -39,19 +39,19 @@
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
@include size-font(8px, 8px);
|
@include size-font(8px, 14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin label {
|
@mixin label {
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
@include size-font(7px, 7px);
|
@include size-font(7px, 12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin code {
|
@mixin code {
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
@include size-font(12px, 12px);
|
@include size-font(12px, 14px);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-height: 100vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
|
|
@ -60,7 +59,3 @@ dt {
|
||||||
code {
|
code {
|
||||||
@include code;
|
@include code;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue