mobile WIP

This commit is contained in:
nicwands 2026-06-19 16:08:25 -04:00
parent a99dfdb8ff
commit ecd784ad42
12 changed files with 147 additions and 20 deletions

View file

@ -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>

View file

@ -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 {

View file

@ -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)

View file

@ -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>

View file

@ -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;

View file

@ -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>

View file

@ -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>

View file

@ -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>

View 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,
}
}

View file

@ -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
const isTouch = event.type.includes('touch')
if (isTouch) {
deltaY *= 10
} else {
deltaY *= 3 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) => {

View file

@ -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);
} }

View file

@ -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;
}