refactor(web): use tabs instead of buttons in NotificationsSidebar header

This commit is contained in:
Pujit Mehrotra
2024-10-10 12:08:11 -04:00
parent a1f0dac42d
commit f6d09f4ba2
5 changed files with 120 additions and 40 deletions

View File

@@ -34,7 +34,7 @@ const icon = computed<{ component: Component, color: string } | null>(() => {
</script>
<template>
<div class="group/item relative w-full py-4 flex flex-col gap-2">
<div class="group/item relative w-full py-4 pl-1 flex flex-col gap-2">
<header class="w-full flex flex-row items-start justify-between gap-2">
<h3 class="text-16px font-semibold leading-2 flex flex-row items-start gap-2">
<component :is="icon.component" v-if="icon" class="size-6 shrink-0" :class="icon.color" />

View File

@@ -14,33 +14,33 @@ import { useUnraidApiStore } from "~/store/unraidApi";
import gql from "graphql-tag";
const getNotifications = gql`
query Notifications($filter: NotificationFilter!) {
notifications {
list(filter: $filter) {
id
title
subject
description
importance
link
type
timestamp
}
query Notifications($filter: NotificationFilter!) {
notifications {
list(filter: $filter) {
id
title
subject
description
importance
link
type
timestamp
}
}
}
`;
const notifications = ref<NotificationItemProps[]>([]);
watch(notifications, (newVal) => {
console.log('[notifications]', newVal);
console.log("[notifications]", newVal);
});
const fetchType = ref<'UNREAD' | 'ARCHIVED'>('UNREAD');
const setFetchType = (type: 'UNREAD' | 'ARCHIVED') => fetchType.value = type;
const fetchType = ref<"UNREAD" | "ARCHIVED">("UNREAD");
const setFetchType = (type: "UNREAD" | "ARCHIVED") => (fetchType.value = type);
const { unraidApiClient } = storeToRefs(useUnraidApiStore());
watch(unraidApiClient, async(newVal) => {
watch(unraidApiClient, async (newVal) => {
if (newVal) {
const apiResponse = await newVal.query({
query: getNotifications,
@@ -66,30 +66,41 @@ const { teleportTarget, determineTeleportTarget } = useTeleport();
<BellIcon class="w-6 h-6" />
</SheetTrigger>
<SheetContent :to="teleportTarget" class="w-full max-w-[400px] sm:max-w-[540px]">
<SheetContent
:to="teleportTarget"
class="w-full overflow-y-scroll max-w-[400px] sm:max-w-[540px]"
>
<SheetHeader>
<SheetTitle>Notifications</SheetTitle>
</SheetHeader>
<div class="flex flex-row justify-between items-center">
<div class="w-auto flex flex-row justify-start items-center gap-1 p-2 rounded">
<Button
v-for="opt in ['Unread', 'Archived']"
:key="opt"
:variant="fetchType === opt ? 'secondary' : undefined"
class="py-2 px-4 text-left"
@click="setFetchType(opt.toUpperCase() as 'UNREAD' | 'ARCHIVED')"
>
{{ opt }}
</Button>
</div>
<div class="w-auto flex flex-row justify-start items-center gap-1 p-2 rounded">
<Tabs default-value="unread" class="">
<div class="flex flex-row justify-between items-center flex-wrap gap-2">
<TabsList class="ml-[1px]">
<TabsTrigger
class="text-[1rem] leading-[1.3rem]"
value="unread"
@click="setFetchType('UNREAD')"
>
Unread
</TabsTrigger>
<TabsTrigger
class="text-[1rem] leading-[1.3rem]"
value="archived"
@="setFetchType('ARCHIVED')"
>
Archived
</TabsTrigger>
</TabsList>
<Button
variant="secondary"
class="py-2 px-4 text-left"
size="sm"
class="text-[1rem] leading-[1.3rem]"
>
{{ `Archive All` }}
</Button>
<Select>
<SelectTrigger>
<SelectValue placeholder="Filter" />
@@ -104,15 +115,23 @@ const { teleportTarget, determineTeleportTarget } = useTeleport();
</SelectContent>
</Select>
</div>
</div>
<div class="divide-y divide-gray-200">
<NotificationsItem
v-for="notification in notifications"
:key="notification.id"
v-bind="notification"
/>
</div>
<TabsContent value="unread">
<ScrollArea>
<div class="divide-y divide-gray-200">
<NotificationsItem
v-for="notification in notifications"
:key="notification.id"
v-bind="notification"
/>
</div>
</ScrollArea>
</TabsContent>
<TabsContent value="archived">
<p>Archived</p>
</TabsContent>
</Tabs>
<SheetFooter class="text-center">
<p>Future pagination station</p>

View File

@@ -0,0 +1,29 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import {
ScrollAreaCorner,
ScrollAreaRoot,
type ScrollAreaRootProps,
ScrollAreaViewport,
} from 'radix-vue'
import ScrollBar from './ScrollBar.vue'
import { cn } from '@/helpers/utils'
const props = defineProps<ScrollAreaRootProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<ScrollAreaRoot v-bind="delegatedProps" :class="cn('relative overflow-hidden', props.class)">
<ScrollAreaViewport class="h-full w-full rounded-[inherit]">
<slot />
</ScrollAreaViewport>
<ScrollBar />
<ScrollAreaCorner />
</ScrollAreaRoot>
</template>

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { ScrollAreaScrollbar, type ScrollAreaScrollbarProps, ScrollAreaThumb } from 'radix-vue'
import { cn } from '@/helpers/utils'
const props = withDefaults(defineProps<ScrollAreaScrollbarProps & { class?: HTMLAttributes['class'] }>(), {
orientation: 'vertical',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<ScrollAreaScrollbar
v-bind="delegatedProps"
:class="
cn('flex touch-none select-none transition-colors',
orientation === 'vertical'
&& 'h-full w-2.5 border-l border-l-transparent p-px',
orientation === 'horizontal'
&& 'h-2.5 flex-col border-t border-t-transparent p-px',
props.class)"
>
<ScrollAreaThumb class="relative flex-1 rounded-full bg-border" />
</ScrollAreaScrollbar>
</template>

View File

@@ -0,0 +1,2 @@
export { default as ScrollArea } from './ScrollArea.vue'
export { default as ScrollBar } from './ScrollBar.vue'