wip bsky client for the web & android bbell.vt3e.cat
at main 95 lines 2.4 kB view raw
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>