wip bsky client for the web & android
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(toasts): finsih off toaststack

vi a1e29453 fad72c4d

+79 -55
+79 -54
src/components/UI/Toast/ToastStack.vue
··· 1 1 <script setup lang="ts"> 2 - import { ref } from 'vue' 3 - 4 - import { 5 - IconCheckRounded, 6 - IconErrorRounded, 7 - IconInfoRounded, 8 - } from '@iconify-prerendered/vue-material-symbols' 9 - 10 - enum ToastType { 11 - Success = 'success', 12 - Error = 'error', 13 - Info = 'info', 14 - } 15 - const toastIcons = { 16 - [ToastType.Success]: IconCheckRounded, 17 - [ToastType.Error]: IconErrorRounded, 18 - [ToastType.Info]: IconInfoRounded, 19 - } 2 + import { useToastStore } from '@/stores/toast' 20 3 21 - type Toast = { 22 - id: number 23 - message: string 24 - type: ToastType 4 + function onBeforeLeave(el: Element) { 5 + const htmlEl = el as HTMLElement 6 + const { offsetTop, offsetLeft, offsetWidth } = htmlEl 7 + htmlEl.style.top = `${offsetTop}px` 8 + htmlEl.style.left = `${offsetLeft}px` 9 + htmlEl.style.width = `${offsetWidth}px` 25 10 } 26 - 27 - const toasts = ref<Toast[]>([ 28 - { 29 - id: 1, 30 - message: 'This is a success toast!', 31 - type: ToastType.Success, 32 - }, 33 - { 34 - id: 2, 35 - message: 'This is an error toast!', 36 - type: ToastType.Error, 37 - }, 38 - ]) 11 + const toast = useToastStore() 39 12 </script> 40 13 41 14 <template> 42 - <div class="toast-stack"> 43 - <div v-for="toast in toasts" :key="toast.id" :class="['toast', toast.type]"> 44 - <div class="icon"> 45 - <component :is="toastIcons[toast.type]" /> 46 - </div> 47 - <span class="message">{{ toast.message }}</span> 15 + <Transition tag="div" name="stack"> 16 + <div v-if="toast.toasts.length" class="toast-stack"> 17 + <TransitionGroup name="toast" @before-leave="onBeforeLeave"> 18 + <div 19 + v-for="t in toast.toasts" 20 + :key="t.id" 21 + :class="['toast', t.type]" 22 + @click="toast.handleClick(t.id)" 23 + > 24 + <div class="icon"> 25 + <component :is="t.icon" /> 26 + </div> 27 + <span class="message">{{ t.message }}</span> 28 + </div> 29 + </TransitionGroup> 48 30 </div> 49 - </div> 31 + </Transition> 50 32 </template> 51 33 52 34 <style scoped lang="scss"> ··· 62 44 gap: 0.75rem; 63 45 64 46 width: 100%; 47 + pointer-events: none; 65 48 } 66 49 @media (min-width: 800px) { 67 50 .toast-stack { ··· 71 54 } 72 55 73 56 .toast { 57 + --accent-colour: var(--accent); 58 + max-width: var(--content-width); 59 + background-color: hsla(var(--surface0) / 1); 60 + 74 61 display: inline-flex; 75 62 align-items: center; 76 63 justify-content: center; 77 64 78 - max-width: var(--content-width); 79 - 80 - background-color: hsla(var(--surface0) / 1); 81 65 padding: 0.25rem 0.5rem; 82 66 padding-right: 1rem; 83 67 gap: 0.5rem; 84 68 border-radius: 2rem; 85 69 86 - &.success { 87 - border: 2px solid hsla(var(--green) / 0.5); 88 - } 89 - &.error { 90 - border: 2px solid hsla(var(--red) / 0.5); 91 - } 92 - &.info { 93 - border: 2px solid hsla(var(--accent) / 0.5); 94 - } 70 + cursor: pointer; 71 + pointer-events: all; 72 + user-select: none; 73 + 74 + max-height: 5rem; 75 + overflow: hidden; 76 + 77 + border: 1px solid hsla(var(--accent-colour) / 0.25); 95 78 96 79 .icon { 97 80 font-size: 1.5rem; 98 81 display: flex; 99 82 align-items: center; 100 83 justify-content: center; 84 + color: hsl(var(--accent-colour)); 101 85 } 86 + 87 + &.success { 88 + --accent-colour: var(--green); 89 + } 90 + &.error { 91 + --accent-colour: var(--red); 92 + } 93 + &.info { 94 + --accent-colour: var(--blue); 95 + } 96 + } 97 + 98 + .stack-enter-active, 99 + .stack-leave-active { 100 + transition: opacity 0.2s ease; 101 + } 102 + .stack-enter-from, 103 + .stack-leave-to { 104 + opacity: 0; 105 + } 106 + 107 + .toast-move, 108 + .toast-enter-active, 109 + .toast-leave-active { 110 + transition: all 0.25s ease; 111 + } 112 + 113 + .toast-enter-from { 114 + opacity: 0; 115 + transform: translateY(1rem) scale(0.95); 116 + } 117 + 118 + .toast-leave-to { 119 + opacity: 0; 120 + transform: translateX(-2rem) scale(0.95); 121 + filter: blur(2px); 122 + max-height: 0; 123 + padding-top: 0; 124 + padding-bottom: 0; 125 + margin-top: -0.75rem; 126 + border-width: 0; 102 127 } 103 128 </style>
-1
src/views/Root/HomeView.vue
··· 243 243 font-weight: 600; 244 244 white-space: nowrap; 245 245 color: hsl(var(--subtext0)); 246 - cursor: pointer; 247 246 248 247 flex-shrink: 0; 249 248