Skip to content

Commit 3ff6740

Browse files
committed
refactor: ♻️ Improve mobile timeline switching
1 parent 466c1ea commit 3ff6740

File tree

10 files changed

+82
-103
lines changed

10 files changed

+82
-103
lines changed
+7-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
<template>
22
<div
3-
class="fixed md:hidden bottom-0 inset-x-0 border-t h-20 bg-background z-10 flex items-center justify-around *:p-7 *:w-full gap-6 p-6">
4-
<Timelines>
5-
<Button variant="ghost" size="icon">
6-
<Home class="!size-6" />
7-
</Button>
8-
</Timelines>
9-
<Button v-if="identity" :as="NuxtLink" href="/notifications" variant="ghost" size="icon">
3+
class="fixed md:hidden bottom-0 inset-x-0 border-t h-20 bg-background z-10 flex items-center justify-around *:h-full *:w-full gap-6 px-4 py-2">
4+
<Button :as="NuxtLink" href="/" variant="ghost" size="icon">
5+
<Home class="!size-6" />
6+
</Button>
7+
<Button :as="NuxtLink" href="/notifications" variant="ghost" size="icon">
108
<Bell class="!size-6" />
119
</Button>
1210
<AccountSwitcher>
1311
<Button variant="ghost" size="icon">
1412
<User class="!size-6" />
1513
</Button>
1614
</AccountSwitcher>
17-
<Button v-if="identity" variant="default" size="icon" :title="m.salty_aloof_turkey_nudge()"
15+
<Button variant="default" size="icon" :title="m.salty_aloof_turkey_nudge()"
1816
@click="useEvent('composer:open')">
1917
<Pen class="!size-6" />
2018
</Button>
@@ -27,5 +25,4 @@ import * as m from "~/paraglide/messages.js";
2725
import { NuxtLink } from "#components";
2826
import AccountSwitcher from "../sidebars/account-switcher.vue";
2927
import { Button } from "../ui/button";
30-
import Timelines from "./timelines.vue";
31-
</script>
28+
</script>

components/navigation/timelines.vue

+26-20
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,61 @@
11
<template>
2-
<Drawer>
3-
<DrawerTrigger :as-child="true">
4-
<slot />
5-
</DrawerTrigger>
6-
<DrawerContent>
7-
<DrawerClose v-for="item in timelines.filter(
2+
<Tabs v-model:model-value="current">
3+
<TabsList>
4+
<TabsTrigger v-for="timeline in timelines.filter(
85
i => i.requiresLogin ? !!identity : true,
9-
)" :key="item.name" :as-child="true">
10-
<Button :as="NuxtLink" :href="item.url" variant="outline" size="lg" class="w-full">
11-
<component :is="item.icon" />
12-
{{ item.name }}
13-
</Button>
14-
</DrawerClose>
15-
<DialogTitle class="sr-only">{{ m.trite_real_sawfish_drum() }}</DialogTitle>
16-
<DialogDescription class="sr-only">{{ m.trite_real_sawfish_drum() }}</DialogDescription>
17-
</DrawerContent>
18-
</Drawer>
6+
)" :key="timeline.value" :value="timeline.value" :as="NuxtLink" :href="timeline.url">
7+
{{ timeline.name }}
8+
</TabsTrigger>
9+
</TabsList>
10+
</Tabs>
1911
</template>
2012

2113
<script lang="ts" setup>
2214
import { BedSingle, Globe, House, MapIcon } from "lucide-vue-next";
15+
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs";
2316
import * as m from "~/paraglide/messages.js";
2417
import { NuxtLink } from "#components";
25-
import DrawerContent from "../modals/drawer-content.vue";
26-
import { Button } from "../ui/button";
27-
import { Drawer, DrawerTrigger } from "../ui/drawer";
2818
2919
const timelines = [
3020
{
3121
name: m.bland_chunky_sparrow_propel(),
22+
value: "home",
3223
url: "/home",
3324
icon: House,
3425
requiresLogin: true,
3526
},
3627
{
3728
name: m.lost_trick_dog_grace(),
29+
value: "public",
3830
url: "/public",
3931
icon: MapIcon,
4032
requiresLogin: false,
4133
},
4234
{
4335
name: m.crazy_game_parrot_pave(),
36+
value: "local",
4437
url: "/local",
4538
icon: BedSingle,
4639
requiresLogin: false,
4740
},
4841
{
4942
name: m.real_tame_moose_greet(),
43+
value: "global",
5044
url: "/global",
5145
icon: Globe,
5246
requiresLogin: false,
5347
},
5448
];
55-
</script>
49+
50+
const { beforeEach } = useRouter();
51+
const { path } = useRoute();
52+
53+
const current = computed(() => {
54+
if (path === "/") {
55+
return identity.value ? "home" : "public";
56+
}
57+
58+
const timeline = timelines.find((i) => i.url === path);
59+
return timeline ? timeline.value : "public";
60+
});
61+
</script>

components/sidebars/sidebar.vue

+29-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import { ChevronDownIcon } from "lucide-vue-next";
23
import {
34
Breadcrumb,
45
BreadcrumbItem,
@@ -14,12 +15,19 @@ import {
1415
SidebarTrigger,
1516
} from "~/components/ui/sidebar";
1617
import { SettingIds } from "~/settings";
18+
import Timelines from "../navigation/timelines.vue";
1719
import LeftSidebar from "./left-sidebar.vue";
1820
import RightSidebar from "./right-sidebar.vue";
1921
2022
const showRightSidebar = useSetting(SettingIds.NotificationsSidebar);
2123
2224
const route = useRoute();
25+
const isMd = useMediaQuery("(max-width: 768px)");
26+
const showTimelines = computed(
27+
() =>
28+
["/", "/home", "/local", "/public", "/global"].includes(route.path) &&
29+
isMd.value,
30+
);
2331
</script>
2432

2533
<template>
@@ -28,22 +36,36 @@ const route = useRoute();
2836
<SidebarInset>
2937
<header
3038
class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12 overflow-hidden bg-background">
31-
<div class="flex items-center gap-2 px-4">
32-
<SidebarTrigger class="-ml-1" />
33-
<Separator orientation="vertical" class="mr-2 h-4" />
39+
<div :key="route.path" class="flex items-center gap-2 px-4 max-w-full">
40+
<SidebarTrigger class="-ml-1 shrink-0" />
41+
<Separator v-if="route.meta.breadcrumbs" orientation="vertical" class="mr-2 h-4" />
3442
<Breadcrumb v-if="route.meta.breadcrumbs">
3543
<BreadcrumbList>
3644
<template v-for="(breadcrumb, index) of route.meta.breadcrumbs()">
37-
<BreadcrumbItem class="hidden md:block">
38-
<component :is="breadcrumb.href ? BreadcrumbLink : BreadcrumbPage" :href="breadcrumb.href">
45+
<BreadcrumbItem>
46+
<component v-if="!breadcrumb.links"
47+
:is="breadcrumb.href ? BreadcrumbLink : BreadcrumbPage" :href="breadcrumb.href">
3948
{{ breadcrumb.text }}
4049
</component>
50+
<DropdownMenu v-else>
51+
<DropdownMenuTrigger class="flex items-center gap-1">
52+
{{ breadcrumb.text }}
53+
<ChevronDownIcon class="size-4" />
54+
</DropdownMenuTrigger>
55+
<DropdownMenuContent align="start">
56+
<DropdownMenuItem v-for="link of breadcrumb.links" :key="link.href"
57+
:as="BreadcrumbLink" :href="link.href">
58+
{{ link.text }}
59+
</DropdownMenuItem>
60+
</DropdownMenuContent>
61+
</DropdownMenu>
4162
</BreadcrumbItem>
42-
<BreadcrumbSeparator v-if="index !== (route.meta.breadcrumbs().length - 1)"
43-
class="hidden md:block" />
63+
<BreadcrumbSeparator v-if="index !== (route.meta.breadcrumbs().length - 1)" />
4464
</template>
4565
</BreadcrumbList>
4666
</Breadcrumb>
67+
<Separator v-if="showTimelines" orientation="vertical" class="h-4" />
68+
<Timelines v-if="showTimelines" />
4769
</div>
4870
</header>
4971
<div class="flex flex-1 flex-col gap-4 md:p-1 overflow-auto *:z-10">

index.d.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
import type { JSX } from "vue/jsx-runtime";
2+
13
declare module "#app" {
24
interface PageMeta {
35
breadcrumbs?: () => {
46
text: string;
57
href?: string;
8+
list?: {
9+
text: string;
10+
href: string;
11+
}[];
612
}[];
13+
header?: JSX.Element;
714
requiresAuth?: boolean;
815
}
916
}
10-
11-
// It is always important to import/export something when augmenting a type
12-
export {};

layouts/app.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</CardFooter>
1717
</Card>
1818
</Sidebar>
19-
<MobileNavbar />
19+
<MobileNavbar v-if="identity" />
2020
<ComposerDialog />
2121
</template>
2222

pages/global.vue

+2-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</div>
77
</template>
88

9-
<script setup lang="ts">
9+
<script setup lang="tsx">
1010
import Global from "~/components/timelines/global.vue";
1111
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
1212
import * as m from "~/paraglide/messages.js";
@@ -17,14 +17,5 @@ useHead({
1717
1818
definePageMeta({
1919
layout: "app",
20-
breadcrumbs: () => [
21-
{
22-
text: m.steep_aqua_fox_harbor(),
23-
},
24-
{
25-
text: m.real_tame_moose_greet(),
26-
href: "/global",
27-
},
28-
],
2920
});
30-
</script>
21+
</script>

pages/home.vue

+3-12
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,17 @@
66
</div>
77
</template>
88

9-
<script setup lang="ts">
9+
<script setup lang="tsx">
1010
import Home from "~/components/timelines/home.vue";
1111
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
1212
import * as m from "~/paraglide/messages.js";
1313
1414
useHead({
15-
title: "Home",
15+
title: m.bland_chunky_sparrow_propel(),
1616
});
1717
1818
definePageMeta({
1919
layout: "app",
20-
breadcrumbs: () => [
21-
{
22-
text: m.steep_aqua_fox_harbor(),
23-
},
24-
{
25-
text: m.bland_chunky_sparrow_propel(),
26-
href: "/home",
27-
},
28-
],
2920
requiresAuth: true,
3021
});
31-
</script>
22+
</script>

pages/index.vue

+2-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</template>
99

1010

11-
<script setup lang="ts">
11+
<script setup lang="tsx">
1212
import Home from "~/components/timelines/home.vue";
1313
import Public from "~/components/timelines/public.vue";
1414
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
@@ -22,19 +22,5 @@ useHead({
2222
2323
definePageMeta({
2424
layout: "app",
25-
breadcrumbs: () => [
26-
{
27-
text: m.steep_aqua_fox_harbor(),
28-
},
29-
identity.value
30-
? {
31-
text: m.bland_chunky_sparrow_propel(),
32-
href: "/home",
33-
}
34-
: {
35-
text: m.lost_trick_dog_grace(),
36-
href: "/public",
37-
},
38-
],
3925
});
40-
</script>
26+
</script>

pages/local.vue

+2-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</template>
88

99

10-
<script lang="ts" setup>
10+
<script lang="tsx" setup>
1111
import Local from "~/components/timelines/local.vue";
1212
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
1313
import * as m from "~/paraglide/messages.js";
@@ -18,14 +18,5 @@ useHead({
1818
1919
definePageMeta({
2020
layout: "app",
21-
breadcrumbs: () => [
22-
{
23-
text: m.steep_aqua_fox_harbor(),
24-
},
25-
{
26-
text: m.crazy_game_parrot_pave(),
27-
href: "/local",
28-
},
29-
],
3021
});
31-
</script>
22+
</script>

pages/public.vue

+3-12
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,16 @@
66
</div>
77
</template>
88

9-
<script setup lang="ts">
9+
<script setup lang="tsx">
1010
import Public from "~/components/timelines/public.vue";
1111
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
1212
import * as m from "~/paraglide/messages.js";
1313
1414
useHead({
15-
title: "Public",
15+
title: m.lost_trick_dog_grace(),
1616
});
1717
1818
definePageMeta({
1919
layout: "app",
20-
breadcrumbs: () => [
21-
{
22-
text: m.steep_aqua_fox_harbor(),
23-
},
24-
{
25-
text: m.lost_trick_dog_grace(),
26-
href: "/public",
27-
},
28-
],
2920
});
30-
</script>
21+
</script>

0 commit comments

Comments
 (0)