wip bsky client for the web & android
bbell.vt3e.cat
1<script setup lang="ts">
2import { ref, onMounted, getCurrentInstance } from 'vue'
3import { IconArrowBackRounded } from '@iconify-prerendered/vue-material-symbols'
4import { useNavigationStore, type StackEntry, type TabKey } from '@/stores/navigation'
5
6const appBarElement = ref<HTMLElement | null>(null)
7const overlayElement = ref<HTMLElement | null>(null)
8defineExpose({ $el: appBarElement, $overlay: overlayElement })
9
10const nav = useNavigationStore()
11const props = defineProps<{
12 left?: number
13 root?: boolean
14 title?: string
15}>()
16
17const mountedStack = ref<StackEntry[] | null>(null)
18const canGoBack = ref(false)
19
20onMounted(() => {
21 if (!appBarElement.value) {
22 const inst = getCurrentInstance()
23 const root = inst?.proxy?.$el as HTMLElement | undefined
24 if (root instanceof HTMLElement) appBarElement.value = root
25 }
26
27 if (!appBarElement.value) return
28
29 let contextTab: TabKey | null = null
30 let contextEntryId: string | null = null
31
32 const tabEl = appBarElement.value.closest('[data-tab]')
33 if (tabEl instanceof HTMLElement && tabEl.dataset.tab) contextTab = tabEl.dataset.tab as TabKey
34
35 const entryEl = appBarElement.value.closest('[data-entry-id]')
36 if (entryEl instanceof HTMLElement && entryEl.dataset.entryId) {
37 contextEntryId = entryEl.dataset.entryId
38 }
39
40 const tab = (contextTab ?? nav.activeTab) as TabKey
41 const s = nav.stacks[tab]
42 mountedStack.value = s ?? null
43
44 if (props.root || !s || s.length <= 1) {
45 canGoBack.value = false
46 return
47 }
48
49 if (contextEntryId) {
50 const index = s.findIndex((e: StackEntry) => e.id === contextEntryId)
51 canGoBack.value = index > 0
52 return
53 }
54
55 canGoBack.value = true
56})
57
58function goBack() {
59 if (canGoBack.value) nav.popStack()
60}
61</script>
62
63<template>
64 <div ref="appBarElement" class="app-bar">
65 <button v-if="canGoBack" @click="goBack" class="back-button" aria-label="Go back" type="button">
66 <IconArrowBackRounded class="icon" aria-hidden="true" />
67 </button>
68 </div>
69</template>
70
71<style lang="scss" scoped>
72.back-button {
73 border: none;
74 background: transparent;
75 display: flex;
76 align-items: center;
77 justify-content: center;
78 cursor: pointer;
79 color: hsl(var(--text));
80 border-radius: 50%;
81 padding: 0.5rem;
82
83 &:hover {
84 background: hsla(var(--surface0) / 1);
85 }
86 &:active {
87 background: hsla(var(--surface0) / 0.5);
88 }
89
90 .icon {
91 width: 1.5rem;
92 height: 1.5rem;
93 }
94}
95</style>