Skip to content

Commit 4dc9cdb

Browse files
committed
ui: web marketing visual parity
1 parent 7537dfb commit 4dc9cdb

7 files changed

Lines changed: 217 additions & 124 deletions

File tree

5.07 KB
Loading

new-deepnotes/apps/web/src/App.vue

Lines changed: 19 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,39 @@
11
<script setup lang="ts">
22
import { onMounted } from "vue";
3-
import { RouterLink, RouterView, useRoute } from "vue-router";
3+
import { RouterView, useRoute } from "vue-router";
44
5-
import { Button } from "@/components/ui/button";
5+
import DefaultLayout from "@/layouts/DefaultLayout.vue";
66
77
import { useSession } from "./features/auth/useSession";
8-
import { unreadNotificationCount } from "./features/notifications/useNotificationBadge";
9-
import { realtimeToastMessage, useRealtimeUserChannel } from "./features/realtime/useRealtimeUserChannel";
10-
import ThemeSwitcher from "./features/theme/ThemeSwitcher.vue";
8+
import {
9+
realtimeToastMessage,
10+
useRealtimeUserChannel,
11+
} from "./features/realtime/useRealtimeUserChannel";
1112
12-
const { bootstrap, isAuthenticated, user, bootstrapped, loading, logout } =
13-
useSession();
13+
const { bootstrap, user, bootstrapped } = useSession();
1414
useRealtimeUserChannel(user);
1515
const route = useRoute();
1616
1717
onMounted(() => {
1818
void bootstrap();
1919
});
20-
21-
async function onLogout() {
22-
await logout();
23-
}
2420
</script>
2521

2622
<template>
27-
<div
28-
class="bg-background text-foreground flex min-h-svh flex-col"
29-
data-testid="app-shell"
30-
>
31-
<header
32-
class="bg-background/80 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-10 border-b backdrop-blur"
33-
>
34-
<div
35-
class="mx-auto flex h-14 max-w-3xl items-center justify-between gap-3 px-4 sm:px-6"
36-
>
37-
<RouterLink
38-
class="text-foreground text-base font-bold tracking-tight"
39-
to="/"
40-
>
41-
DeepNotes
42-
</RouterLink>
43-
<nav class="flex items-center gap-2 text-sm">
44-
<ThemeSwitcher />
45-
<template v-if="bootstrapped">
46-
<span
47-
v-if="isAuthenticated && user"
48-
class="text-muted-foreground text-xs font-medium"
49-
>
50-
{{ user.demo ? "Demo" : "Signed in" }}
51-
</span>
52-
<Button
53-
v-if="isAuthenticated"
54-
as-child
55-
size="sm"
56-
variant="ghost"
57-
>
58-
<RouterLink to="/pages">Pages</RouterLink>
59-
</Button>
60-
<Button
61-
v-if="isAuthenticated"
62-
as-child
63-
size="sm"
64-
variant="ghost"
65-
>
66-
<RouterLink to="/spatial" title="Map of spatial pages"
67-
>Canvas</RouterLink
68-
>
69-
</Button>
70-
<Button
71-
v-if="isAuthenticated"
72-
as-child
73-
size="sm"
74-
variant="ghost"
75-
>
76-
<RouterLink to="/groups">Groups</RouterLink>
77-
</Button>
78-
<Button
79-
v-if="isAuthenticated"
80-
as-child
81-
size="sm"
82-
variant="ghost"
83-
class="relative"
84-
>
85-
<RouterLink to="/notifications">
86-
Notifications
87-
<span
88-
v-if="unreadNotificationCount > 0"
89-
class="bg-primary text-primary-foreground absolute -right-1 -top-1 flex h-4 min-w-[1rem] items-center justify-center rounded-full px-1 text-[10px] font-bold"
90-
>
91-
{{ unreadNotificationCount > 99 ? "99+" : unreadNotificationCount }}
92-
</span>
93-
</RouterLink>
94-
</Button>
95-
<Button
96-
v-if="isAuthenticated"
97-
as-child
98-
size="sm"
99-
variant="ghost"
100-
>
101-
<RouterLink to="/account">Account</RouterLink>
102-
</Button>
103-
<template v-if="!isAuthenticated">
104-
<Button as-child variant="ghost" size="sm">
105-
<RouterLink to="/register">Register</RouterLink>
106-
</Button>
107-
<Button as-child variant="ghost" size="sm">
108-
<RouterLink to="/login">Sign in</RouterLink>
109-
</Button>
110-
</template>
111-
<Button
112-
v-if="isAuthenticated"
113-
:disabled="loading"
114-
size="sm"
115-
variant="ghost"
116-
@click="onLogout"
117-
>
118-
Sign out
119-
</Button>
120-
</template>
121-
</nav>
122-
</div>
123-
</header>
124-
<main class="mx-auto w-full max-w-3xl flex-1 px-4 py-6 sm:px-6">
125-
<div
126-
v-if="!bootstrapped"
127-
class="text-muted-foreground flex min-h-[40vh] items-center justify-center text-sm"
128-
>
129-
Loading session…
130-
</div>
131-
<RouterView
132-
v-else
133-
:key="route.path"
134-
/>
135-
</main>
23+
<DefaultLayout data-testid="app-shell">
13624
<div
137-
v-if="realtimeToastMessage"
138-
class="bg-card fixed bottom-4 left-1/2 z-50 max-w-md -translate-x-1/2 rounded-md border px-4 py-2 text-sm shadow-lg"
139-
role="status"
25+
v-if="!bootstrapped"
26+
class="text-muted-foreground flex min-h-[40vh] items-center justify-center text-sm"
14027
>
141-
{{ realtimeToastMessage }}
28+
Loading session…
14229
</div>
30+
<RouterView v-else :key="route.path" />
31+
</DefaultLayout>
32+
<div
33+
v-if="realtimeToastMessage"
34+
class="bg-card fixed bottom-4 left-1/2 z-50 max-w-md -translate-x-1/2 rounded-md border px-4 py-2 text-sm shadow-lg"
35+
role="status"
36+
>
37+
{{ realtimeToastMessage }}
14338
</div>
14439
</template>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<script setup lang="ts">
2+
const currentYear = new Date().getFullYear();
3+
</script>
4+
5+
<template>
6+
<footer
7+
class="border-t border-border/40 bg-background py-10 text-sm text-muted-foreground"
8+
>
9+
<div
10+
class="mx-auto flex max-w-5xl flex-col items-center justify-between gap-6 px-4 md:flex-row md:px-6"
11+
>
12+
<div class="flex flex-col items-center gap-2 md:items-start">
13+
<RouterLink to="/" class="flex items-center gap-2">
14+
<img
15+
src="/white-logo-outline.webp"
16+
alt="DeepNotes"
17+
class="h-6 w-6"
18+
/>
19+
<span class="font-semibold text-foreground">DeepNotes</span>
20+
</RouterLink>
21+
<span>End-to-end encrypted notes and collaboration.</span>
22+
</div>
23+
24+
<div class="flex flex-wrap items-center justify-center gap-4">
25+
<a
26+
href="https://discord.gg/UaF2gPTUPh"
27+
target="_blank"
28+
class="transition-colors hover:text-foreground"
29+
>
30+
Discord
31+
</a>
32+
<a
33+
href="https://www.reddit.com/r/DeepNotesApp/"
34+
target="_blank"
35+
class="transition-colors hover:text-foreground"
36+
>
37+
Reddit
38+
</a>
39+
<a
40+
href="https://github.com/DeepNotesApp/DeepNotes"
41+
target="_blank"
42+
class="transition-colors hover:text-foreground"
43+
>
44+
GitHub
45+
</a>
46+
</div>
47+
48+
<div class="flex flex-col items-center gap-2 md:items-end">
49+
<span>Licensed under AGPL-3.0.</span>
50+
<span>&copy; {{ currentYear }} DeepNotes</span>
51+
</div>
52+
</div>
53+
</footer>
54+
</template>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<script setup lang="ts">
2+
import { RouterLink } from "vue-router";
3+
4+
import { Button } from "@/components/ui/button";
5+
import { useSession } from "@/features/auth/useSession";
6+
import { unreadNotificationCount } from "@/features/notifications/useNotificationBadge";
7+
import ThemeSwitcher from "@/features/theme/ThemeSwitcher.vue";
8+
9+
const { isAuthenticated, bootstrapped, loading, logout } = useSession();
10+
11+
async function onLogout() {
12+
await logout();
13+
}
14+
</script>
15+
16+
<template>
17+
<header
18+
class="sticky top-0 z-50 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60"
19+
>
20+
<div
21+
class="mx-auto flex h-14 max-w-5xl items-center justify-between px-4 md:px-6"
22+
>
23+
<div class="flex items-center gap-6">
24+
<RouterLink
25+
to="/"
26+
class="flex items-center gap-2 text-lg font-semibold tracking-tight transition-opacity hover:opacity-80"
27+
>
28+
<img
29+
src="/white-logo-outline.webp"
30+
alt="DeepNotes"
31+
class="h-7 w-7"
32+
/>
33+
DeepNotes
34+
</RouterLink>
35+
36+
<nav
37+
v-if="bootstrapped && isAuthenticated"
38+
class="hidden items-center gap-1 md:flex"
39+
>
40+
<Button as-child size="sm" variant="ghost">
41+
<RouterLink to="/pages">Pages</RouterLink>
42+
</Button>
43+
<Button as-child size="sm" variant="ghost">
44+
<RouterLink to="/groups">Groups</RouterLink>
45+
</Button>
46+
<Button as-child size="sm" variant="ghost" class="relative">
47+
<RouterLink to="/notifications">
48+
Notifications
49+
<span
50+
v-if="unreadNotificationCount > 0"
51+
class="bg-primary text-primary-foreground absolute -right-1 -top-1 flex h-4 min-w-[1rem] items-center justify-center rounded-full px-1 text-[10px] font-bold"
52+
>
53+
{{ unreadNotificationCount > 99 ? "99+" : unreadNotificationCount }}
54+
</span>
55+
</RouterLink>
56+
</Button>
57+
<Button as-child size="sm" variant="ghost">
58+
<RouterLink to="/account">Account</RouterLink>
59+
</Button>
60+
</nav>
61+
</div>
62+
63+
<div class="flex items-center gap-2">
64+
<ThemeSwitcher />
65+
<template v-if="bootstrapped">
66+
<template v-if="!isAuthenticated">
67+
<Button as-child variant="ghost" size="sm">
68+
<RouterLink to="/login">Sign in</RouterLink>
69+
</Button>
70+
<Button as-child variant="default" size="sm">
71+
<RouterLink to="/register">Register</RouterLink>
72+
</Button>
73+
</template>
74+
<template v-else>
75+
<Button
76+
:disabled="loading"
77+
size="sm"
78+
variant="ghost"
79+
@click="onLogout"
80+
>
81+
Sign out
82+
</Button>
83+
</template>
84+
</template>
85+
</div>
86+
</div>
87+
</header>
88+
</template>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<script setup lang="ts">
2+
import { cn } from "@/lib/utils";
3+
4+
const props = defineProps<{
5+
modelValue?: boolean;
6+
class?: string;
7+
}>();
8+
9+
const emit = defineEmits<{
10+
(e: "update:modelValue", value: boolean): void;
11+
}>();
12+
13+
function toggle() {
14+
emit("update:modelValue", !props.modelValue);
15+
}
16+
</script>
17+
18+
<template>
19+
<button
20+
type="button"
21+
role="switch"
22+
:aria-checked="modelValue"
23+
:class="
24+
cn(
25+
'relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',
26+
modelValue ? 'bg-primary' : 'bg-muted',
27+
props.class,
28+
)
29+
"
30+
@click="toggle"
31+
>
32+
<span
33+
:class="
34+
cn(
35+
'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-background shadow ring-0 transition duration-200 ease-in-out',
36+
modelValue ? 'translate-x-5' : 'translate-x-0',
37+
)
38+
"
39+
/>
40+
</button>
41+
</template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as Switch } from "./Switch.vue";
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script setup lang="ts">
2+
import Footer from "@/components/Footer.vue";
3+
import NavBar from "@/components/NavBar.vue";
4+
</script>
5+
6+
<template>
7+
<div class="flex min-h-svh flex-col bg-background text-foreground">
8+
<NavBar />
9+
<main class="mx-auto w-full max-w-3xl flex-1 px-4 py-6 sm:px-6">
10+
<slot />
11+
</main>
12+
<Footer />
13+
</div>
14+
</template>

0 commit comments

Comments
 (0)