Highlight focused element by path
Also force all its parents to be open, similar to forceOpen from the previous commit (which, incidentally, this commit removes again).
This commit is contained in:
parent
af99414d6a
commit
37f1b0e9d1
3 changed files with 29 additions and 7 deletions
|
|
@ -10,7 +10,7 @@ const ui = useUiStore();
|
||||||
<div class="flex h-screen touch-pan-x touch-pan-y flex-col">
|
<div class="flex h-screen touch-pan-x touch-pan-y flex-col">
|
||||||
<CNavbar />
|
<CNavbar />
|
||||||
<div class="h-full overflow-auto px-2 py-1">
|
<div class="h-full overflow-auto px-2 py-1">
|
||||||
<CNote :noteId="ui.anchor" />
|
<CNote :noteId="ui.anchor" :focusPath="ui.focusPath" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,14 @@ const { notes } = useNotesStore();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
noteId?: string;
|
noteId?: string;
|
||||||
forceOpen?: boolean;
|
focusPath?: number[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const note = computed(() =>
|
const note = computed(() =>
|
||||||
props.noteId ? notes.get(props.noteId) : undefined,
|
props.noteId ? notes.get(props.noteId) : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Our children and their locally unique keys.
|
||||||
const children = computed(() => {
|
const children = computed(() => {
|
||||||
if (note.value === undefined) return [];
|
if (note.value === undefined) return [];
|
||||||
const seen = new Map<string, number>();
|
const seen = new Map<string, number>();
|
||||||
|
|
@ -29,16 +30,30 @@ const children = computed(() => {
|
||||||
|
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
|
|
||||||
// We want to set open to true when forced, but then it should stay true. Hence
|
// We're the node pointed to by the `focusPath`.
|
||||||
// a computed() combining open and forceOpen would not suffice.
|
const focused = computed(() => props.focusPath?.length === 0);
|
||||||
|
|
||||||
|
// We want to set open to true when we're on the focus path, but then it should
|
||||||
|
// stay true. Hence a computed() combining open and forceOpen would not suffice.
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (props.forceOpen) open.value = true;
|
open.value; // Ensure we stay open if `open.value = false` is attempted
|
||||||
|
if (props.focusPath && props.focusPath.length > 0) open.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function focusPathFor(index: number): number[] | undefined {
|
||||||
|
if (!props.focusPath) return undefined;
|
||||||
|
if (index !== props.focusPath[0]) return undefined;
|
||||||
|
return props.focusPath.slice(1);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-row gap-1" @click="open = !open">
|
<div
|
||||||
|
class="flex flex-row gap-1"
|
||||||
|
:class="focused ? ['bg-neutral-200'] : []"
|
||||||
|
@click="open = !open"
|
||||||
|
>
|
||||||
<!-- Fold/unfold symbol -->
|
<!-- Fold/unfold symbol -->
|
||||||
<div v-if="children.length > 0 && !open" class="flex items-center">
|
<div v-if="children.length > 0 && !open" class="flex items-center">
|
||||||
<RiArrowRightSLine size="16px" />
|
<RiArrowRightSLine size="16px" />
|
||||||
|
|
@ -60,7 +75,12 @@ watchEffect(() => {
|
||||||
v-if="open && children.length > 0"
|
v-if="open && children.length > 0"
|
||||||
class="flex flex-col border-l border-neutral-300 pl-3"
|
class="flex flex-col border-l border-neutral-300 pl-3"
|
||||||
>
|
>
|
||||||
<CNote v-for="[noteId, key] in children" :key :note-id />
|
<CNote
|
||||||
|
v-for="([noteId, key], index) in children"
|
||||||
|
:key
|
||||||
|
:note-id
|
||||||
|
:focusPath="focusPathFor(index)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,10 @@ import { ref } from "vue";
|
||||||
|
|
||||||
export const useUiStore = defineStore("ui", () => {
|
export const useUiStore = defineStore("ui", () => {
|
||||||
const anchor = ref<string>();
|
const anchor = ref<string>();
|
||||||
|
const focusPath = ref<number[]>([1]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
anchor,
|
anchor,
|
||||||
|
focusPath,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue