📱 (note)
This commit is contained in:
@@ -1,7 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="stacked-note"
|
class="stacked-note"
|
||||||
:class="{ [className]: true, overlay: displayNoteOverlay }"
|
:class="{
|
||||||
|
[className]: true,
|
||||||
|
overlay: displayNoteOverlay,
|
||||||
|
[`note-${sha}`]: true
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<div class="title-stacked-note" :class="titleClassName">
|
<div class="title-stacked-note" :class="titleClassName">
|
||||||
<a @click.prevent="focus">
|
<a @click.prevent="focus">
|
||||||
@@ -75,8 +79,6 @@ $border-color: rgba(18, 19, 58, 0.2);
|
|||||||
|
|
||||||
.title-stacked-note {
|
.title-stacked-note {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
transform-origin: 0 0;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -86,8 +88,17 @@ $border-color: rgba(18, 19, 58, 0.2);
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.title-stacked-note {
|
.stacked-note {
|
||||||
display: none;
|
padding: 0 1.5rem;
|
||||||
|
|
||||||
|
.title-stacked-note {
|
||||||
|
padding: 1rem 0 0;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,5 +107,11 @@ $border-color: rgba(18, 19, 58, 0.2);
|
|||||||
border-top: 0;
|
border-top: 0;
|
||||||
border-left: 1px solid $border-color;
|
border-left: 1px solid $border-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title-stacked-note {
|
||||||
|
padding: 0 1rem;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>Andy Matuschak's website</a
|
>Andy Matuschak's website</a
|
||||||
>. May "Lite note" be useful to everyone.
|
>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -101,6 +101,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.welcome-world {
|
.welcome-world {
|
||||||
|
padding: 1rem;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
1
src/constants/mobile.ts
Normal file
1
src/constants/mobile.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const MOBILE_BREAKPOINT = 768
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import { LocationQueryValue, useRoute } from 'vue-router'
|
||||||
|
import { computed, nextTick } from 'vue'
|
||||||
|
|
||||||
import { NOTE_WIDTH } from '@/constants/note-width'
|
import { NOTE_WIDTH } from '@/constants/note-width'
|
||||||
import { useOverlay } from '@/hooks/useOverlay.hook'
|
import { useOverlay } from '@/hooks/useOverlay.hook'
|
||||||
import { computed, nextTick } from 'vue'
|
|
||||||
import { LocationQueryValue, useRoute } from 'vue-router'
|
|
||||||
|
|
||||||
export const useFocus = () => {
|
export const useFocus = () => {
|
||||||
const { scrollToNote } = useOverlay(false)
|
const { scrollToNote, isMobile } = useOverlay(false)
|
||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
|
|
||||||
const initialStackedNotes = computed(() =>
|
const initialStackedNotes = computed(() =>
|
||||||
@@ -24,9 +25,14 @@ export const useFocus = () => {
|
|||||||
}
|
}
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const index = stackedNotes.findIndex((noteSHA) => noteSHA === sha)
|
const index = stackedNotes.findIndex((noteSHA) => noteSHA === sha)
|
||||||
const left = index * NOTE_WIDTH
|
if (isMobile.value) {
|
||||||
|
const element = document.querySelector(`.note-${sha}`) as HTMLElement
|
||||||
scrollToNote(left)
|
const top = (index + 1) * (element?.clientHeight ?? 0)
|
||||||
|
scrollToNote(top)
|
||||||
|
} else {
|
||||||
|
const left = index * NOTE_WIDTH
|
||||||
|
// scrollToNote(left)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ import {
|
|||||||
} from '@vue/runtime-core'
|
} from '@vue/runtime-core'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
import { noteEventBus } from '@/bus/noteBusEvent'
|
|
||||||
import { useLinks } from '@/hooks/useLinks.hook'
|
|
||||||
import { useRepo } from '@/hooks/useRepo.hook'
|
|
||||||
import { NOTE_WIDTH } from '@/constants/note-width'
|
import { NOTE_WIDTH } from '@/constants/note-width'
|
||||||
|
import { noteEventBus } from '@/bus/noteBusEvent'
|
||||||
import { useFocus } from '@/hooks/useFocus.hook'
|
import { useFocus } from '@/hooks/useFocus.hook'
|
||||||
|
import { useLinks } from '@/hooks/useLinks.hook'
|
||||||
|
import { useOverlay } from '@/hooks/useOverlay.hook'
|
||||||
|
import { useRepo } from '@/hooks/useRepo.hook'
|
||||||
|
|
||||||
const sanitizePath = (path: string) => {
|
const sanitizePath = (path: string) => {
|
||||||
if (path.startsWith('./')) {
|
if (path.startsWith('./')) {
|
||||||
@@ -28,6 +29,7 @@ export const useNote = (
|
|||||||
) => {
|
) => {
|
||||||
const { push } = useRouter()
|
const { push } = useRouter()
|
||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
|
const { isMobile } = useOverlay(false)
|
||||||
const { scrollToFocusedNote } = useFocus()
|
const { scrollToFocusedNote } = useFocus()
|
||||||
|
|
||||||
const stackedNotes = ref(
|
const stackedNotes = ref(
|
||||||
@@ -132,7 +134,11 @@ export const useNote = (
|
|||||||
if (!element) {
|
if (!element) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
element.style.width = `${NOTE_WIDTH * (stackedNotes.value.length + 1)}px`
|
if (isMobile.value) {
|
||||||
|
element.style.height = `${(stackedNotes.value.length + 1) * 100}vh`
|
||||||
|
} else {
|
||||||
|
element.style.width = `${NOTE_WIDTH * (stackedNotes.value.length + 1)}px`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
import { computed, onMounted } from '@vue/runtime-core'
|
import { computed, onMounted, ref } from '@vue/runtime-core'
|
||||||
|
|
||||||
import { useOverlay } from '@/hooks/useOverlay.hook'
|
|
||||||
import { NOTE_WIDTH } from '@/constants/note-width'
|
import { NOTE_WIDTH } from '@/constants/note-width'
|
||||||
|
import { useOverlay } from '@/hooks/useOverlay.hook'
|
||||||
|
|
||||||
const BOOKMARK_WIDTH = 1.5
|
const BOOKMARK_WIDTH = 2
|
||||||
|
const BOOKMARK_HEIGHT = 2.5
|
||||||
|
|
||||||
export const useNoteOverlay = (className: string, index: number) => {
|
export const useNoteOverlay = (className: string, index: number) => {
|
||||||
const { x } = useOverlay()
|
const { x, y, isMobile } = useOverlay()
|
||||||
const displayNoteOverlay = computed(() => x.value > index * NOTE_WIDTH)
|
const noteHeight = ref(0)
|
||||||
|
const displayNoteOverlay = computed(() => {
|
||||||
|
if (isMobile.value) {
|
||||||
|
return y.value > index * noteHeight.value
|
||||||
|
} else {
|
||||||
|
return x.value > index * NOTE_WIDTH
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const noteElement = document.querySelector(
|
const noteElement = document.querySelector(
|
||||||
@@ -17,8 +25,13 @@ export const useNoteOverlay = (className: string, index: number) => {
|
|||||||
if (!noteElement) {
|
if (!noteElement) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
noteHeight.value = noteElement.clientHeight
|
||||||
|
|
||||||
noteElement.style.left = `${(index + 1) * BOOKMARK_WIDTH}rem`
|
if (isMobile.value) {
|
||||||
|
noteElement.style.top = `${(index + 1) * BOOKMARK_HEIGHT}rem`
|
||||||
|
} else {
|
||||||
|
noteElement.style.left = `${(index + 1) * BOOKMARK_WIDTH}rem`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
|
import { MOBILE_BREAKPOINT } from '@/constants/mobile'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
|
|
||||||
export const useOverlay = (listen = true) => {
|
export const useOverlay = (listen = true) => {
|
||||||
const x = ref(0)
|
const x = ref(0)
|
||||||
const body = document.querySelector('body')
|
const y = ref(0)
|
||||||
|
const body = document.querySelector('body') as HTMLBodyElement
|
||||||
|
const isMobile = ref((body?.clientWidth ?? 0) <= MOBILE_BREAKPOINT)
|
||||||
|
|
||||||
if (listen) {
|
if (listen) {
|
||||||
useEventListener(
|
useEventListener(
|
||||||
body,
|
body,
|
||||||
'scroll',
|
'scroll',
|
||||||
(e) => {
|
(event) => {
|
||||||
const target = e.target as HTMLElement
|
const target = event.target as HTMLElement
|
||||||
x.value = target.scrollLeft
|
x.value = target.scrollLeft
|
||||||
|
y.value = target.scrollTop
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
passive: true,
|
passive: true,
|
||||||
@@ -22,13 +25,23 @@ export const useOverlay = (listen = true) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const scrollToNote = (to: number) => {
|
const scrollToNote = (to: number) => {
|
||||||
body?.scroll({
|
console.log('scroll to note', to)
|
||||||
left: to
|
|
||||||
})
|
if (isMobile.value) {
|
||||||
|
body.scroll({
|
||||||
|
top: to
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
body.scroll({
|
||||||
|
left: to
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x,
|
x,
|
||||||
|
y,
|
||||||
|
isMobile,
|
||||||
scrollToNote
|
scrollToNote
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ html {
|
|||||||
body {
|
body {
|
||||||
font-family: 'Courier Prime', monospace;
|
font-family: 'Courier Prime', monospace;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
scroll-behavior: smooth
|
scroll-behavior: smooth;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 769px) {
|
@media screen and (min-width: 769px) {
|
||||||
|
|||||||
@@ -12,17 +12,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="home content note-container" v-else>
|
<div class="home content note-container" v-else>
|
||||||
<div class="readme note">
|
<div class="readme note">
|
||||||
<h1 class="title is-1">
|
<div class="repo-title">
|
||||||
[<router-link
|
<h1 class="title is-1">
|
||||||
:to="{ name: 'Home', params: { user, repo } }"
|
[<router-link
|
||||||
:key="routeKey"
|
:to="{ name: 'Home', params: { user, repo } }"
|
||||||
>
|
:key="routeKey"
|
||||||
{{ repo }} </router-link
|
>
|
||||||
>]
|
{{ repo }} </router-link
|
||||||
</h1>
|
>]
|
||||||
<h2 class="subtitle is-2">
|
</h1>
|
||||||
<em>{{ user }}</em>
|
<h4 class="subtitle is-4">
|
||||||
</h2>
|
<em>{{ user }}</em>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
<p class="note-display" v-html="readme"></p>
|
<p class="note-display" v-html="readme"></p>
|
||||||
</div>
|
</div>
|
||||||
<stacked-note
|
<stacked-note
|
||||||
@@ -74,12 +76,16 @@ export default defineComponent({
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.home {
|
.home {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.readme {
|
.readme {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
padding: 0 1.5rem 1rem;
|
top: 0;
|
||||||
|
padding: 2.5rem 2rem 1rem;
|
||||||
|
|
||||||
|
.repo-title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.note {
|
.note {
|
||||||
@@ -107,9 +113,7 @@ export default defineComponent({
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.note {
|
.note {
|
||||||
position: initial;
|
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user