BreadCrumb & keyboard navigation improvements.
This commit is contained in:
parent
61f9026e23
commit
c5c65d136a
|
@ -4,7 +4,7 @@
|
||||||
<HeaderMain ref="headerMain" :path="path.pathList" :query="path.query">
|
<HeaderMain ref="headerMain" :path="path.pathList" :query="path.query">
|
||||||
<HeaderSelected :path="path.pathList" />
|
<HeaderSelected :path="path.pathList" />
|
||||||
</HeaderMain>
|
</HeaderMain>
|
||||||
<BreadCrumb :path="path.pathList" tabindex="-1"/>
|
<BreadCrumb :path="path.pathList" primary />
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<RouterView :path="path.pathList" :query="path.query" />
|
<RouterView :path="path.pathList" :query="path.query" />
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
@keyup.left.stop="move(-1)"
|
@keyup.left.stop="move(-1)"
|
||||||
@keyup.right.stop="move(1)"
|
@keyup.right.stop="move(1)"
|
||||||
@keyup.enter="move(0)"
|
@keyup.enter="move(0)"
|
||||||
|
@focus=focusCurrent
|
||||||
|
tabindex=0
|
||||||
>
|
>
|
||||||
<a href="#/"
|
<a href="#/"
|
||||||
:ref="el => setLinkRef(0, el)"
|
:ref="el => setLinkRef(0, el)"
|
||||||
|
@ -26,7 +28,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import home from '@/assets/svg/home.svg'
|
import home from '@/assets/svg/home.svg'
|
||||||
import { onBeforeUpdate, ref, watchEffect } from 'vue'
|
import { nextTick, onBeforeUpdate, ref, watchEffect } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -37,22 +39,33 @@ onBeforeUpdate(() => { links.length = 1 }) // 1 to keep home
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
path: Array<string>
|
path: Array<string>
|
||||||
|
primary?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const longest = ref<Array<string>>([])
|
const longest = ref<Array<string>>([])
|
||||||
|
|
||||||
const isCurrent = (index: number) => index == props.path.length ? 'location' : undefined
|
const isCurrent = (index: number) => index == props.path.length ? 'location' : undefined
|
||||||
|
|
||||||
|
const focusCurrent = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
const index = props.path.length
|
||||||
|
if (index < links.length) links[index].focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const navigate = (index: number) => {
|
const navigate = (index: number) => {
|
||||||
const link = links[index]
|
const link = links[index]
|
||||||
if (!link) throw Error(`No link at index ${index} (path: ${props.path})`)
|
if (!link) throw Error(`No link at index ${index} (path: ${props.path})`)
|
||||||
const url = `/${longest.value.slice(0, index).join('/')}/`
|
const url = index ? `/${longest.value.slice(0, index).join('/')}/` : '/'
|
||||||
const here = `/${longest.value.join('/')}/`
|
const long = longest.value.length ? `/${longest.value.join('/')}/` : '/'
|
||||||
const current = decodeURIComponent(location.hash.slice(1).split('//')[0])
|
const browser = decodeURIComponent(location.hash.slice(1).split('//')[0])
|
||||||
const u = url.replaceAll('?', '%3F').replaceAll('#', '%23')
|
const u = url.replaceAll('?', '%3F').replaceAll('#', '%23')
|
||||||
if (here.startsWith(current)) router.replace(u)
|
// Clicking on current link clears the rest of the path and adds new history
|
||||||
|
if (isCurrent(index)) { longest.value.splice(index); router.push(u) }
|
||||||
|
// Moving along breadcrumbs doesn't create new history
|
||||||
|
else if (long.startsWith(browser)) router.replace(u)
|
||||||
|
// Nornal navigation from elsewhere (e.g. search result breadcrumbs)
|
||||||
else router.push(u)
|
else router.push(u)
|
||||||
link.focus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const move = (dir: number) => {
|
const move = (dir: number) => {
|
||||||
|
@ -64,13 +77,16 @@ const move = (dir: number) => {
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const longcut = longest.value.slice(0, props.path.length)
|
const longcut = longest.value.slice(0, props.path.length)
|
||||||
const same = longcut.every((value, index) => value === props.path[index])
|
const same = longcut.every((value, index) => value === props.path[index])
|
||||||
|
// Navigated out of previous path, reset longest to current
|
||||||
if (!same) longest.value = props.path
|
if (!same) longest.value = props.path
|
||||||
else if (props.path.length > longcut.length) {
|
else if (props.path.length > longcut.length) {
|
||||||
longest.value = longcut.concat(props.path.slice(longcut.length))
|
longest.value = longcut.concat(props.path.slice(longcut.length))
|
||||||
}
|
}
|
||||||
})
|
// If needed, focus primary navigation to new location
|
||||||
watchEffect(() => {
|
if (props.primary) nextTick(() => {
|
||||||
if (links.length) navigate(props.path.length)
|
const act = document.activeElement as HTMLElement
|
||||||
|
if (!act || [...links, document.body].includes(act)) focusCurrent()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -58,13 +58,13 @@
|
||||||
@keyup.right.stop="ev => { if (doc.dir) (ev.target as HTMLElement).click() }"
|
@keyup.right.stop="ev => { if (doc.dir) (ev.target as HTMLElement).click() }"
|
||||||
>{{ doc.name }}</a
|
>{{ doc.name }}</a
|
||||||
>
|
>
|
||||||
<button v-if="cursor == doc" class="rename-button" @click="() => (editing = doc)">🖊️</button>
|
<button tabindex=-1 v-if="cursor == doc" class="rename-button" @click="() => (editing = doc)">🖊️</button>
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<FileModified :doc=doc :key=nowkey />
|
<FileModified :doc=doc :key=nowkey />
|
||||||
<FileSize :doc=doc />
|
<FileSize :doc=doc />
|
||||||
<td class="menu">
|
<td class="menu">
|
||||||
<button tabindex="-1" @click.stop="contextMenu($event, doc)">⋮</button>
|
<button tabindex=-1 @click.stop="contextMenu($event, doc)">⋮</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user