Added navbar on public pages
This commit is contained in:
@@ -42,21 +42,13 @@
|
|||||||
|
|
||||||
/* Normal link */
|
/* Normal link */
|
||||||
p a:not([class]) {
|
p a:not([class]) {
|
||||||
color: var(--color-sky-600);
|
color: var(--color-primary);
|
||||||
text-underline-offset: .25rem;
|
text-underline-offset: .25rem;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--color-sky-500);
|
color: var(--color-accent);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
@variant dark {
|
|
||||||
color: var(--color-teal-500);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--color-teal-300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
|||||||
39
app/components/global/Navbar.vue
Normal file
39
app/components/global/Navbar.vue
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
<header role="banner" class="sticky top-0 border-b-1 border-border py-4 px-2 z-50 backdrop-blur">
|
||||||
|
<div class="max-w-4xl mx-auto">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="md:flex-1 flex justify-start" />
|
||||||
|
|
||||||
|
<nav class="md:flex-1">
|
||||||
|
<menu class="text-sm flex items-center justify-center gap-4">
|
||||||
|
<li>
|
||||||
|
<NuxtLink to="/" class="block p-1 font-medium text-foreground/70 hover:text-foreground transition-colors" active-class="text-primary">
|
||||||
|
{{ $t('breadcrumbs.home') }}
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NuxtLink to="/explore" class="block p-1 font-medium text-foreground/70 hover:text-foreground transition-colors" active-class="text-primary">
|
||||||
|
{{ $t('pages.explore.menuLabel') }}
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NuxtLink to="/about" class="block p-1 font-medium text-foreground/70 hover:text-foreground transition-colors" active-class="text-primary">
|
||||||
|
{{ $t('pages.about.menuLabel') }}
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</menu>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="md:flex-1 flex justify-end">
|
||||||
|
<UserDashboardLink size="xs" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
header {
|
||||||
|
background-color: color-mix(in srgb, var(--color-background) 75%, transparent);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -40,7 +40,7 @@ const breakpoints = useBreakpoints(
|
|||||||
<nav
|
<nav
|
||||||
ref="sidebarRef"
|
ref="sidebarRef"
|
||||||
:class="cn(
|
:class="cn(
|
||||||
['md:relative md:isolate w-16 py-6 grid gap-4 grid-rows-[1fr_auto] justify-center md:transition-colors'], // Base appearance
|
['md:relative md:isolate w-16 py-6 grid gap-4 grid-rows-[1fr_auto] bg-background justify-center md:transition-colors'], // Base appearance
|
||||||
['after:opacity-50 after:contrast-125 dark:after:opacity-75'], // After styling
|
['after:opacity-50 after:contrast-125 dark:after:opacity-75'], // After styling
|
||||||
['border-r-[1px] border-r-border dark:border-r-border'], // Colours
|
['border-r-[1px] border-r-border dark:border-r-border'], // Colours
|
||||||
['max-md:justify-stretch max-md:px-4 max-md:py-4 max-md:absolute max-md:left-0 max-md:inset-0 max-md:z-50 max-md:w-40 max-md:max-w-full max-md:transition-all'], // Responsive behaviours
|
['max-md:justify-stretch max-md:px-4 max-md:py-4 max-md:absolute max-md:left-0 max-md:inset-0 max-md:z-50 max-md:w-40 max-md:max-w-full max-md:transition-all'], // Responsive behaviours
|
||||||
|
|||||||
45
app/components/global/user/DashboardLink.vue
Normal file
45
app/components/global/user/DashboardLink.vue
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { PrimitiveProps } from 'radix-vue'
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import type { ButtonVariants } from '@/components/ui/button'
|
||||||
|
|
||||||
|
const { auth } = useSupabaseClient()
|
||||||
|
const user = useSupabaseUser()
|
||||||
|
const profileUrl: string = `${useRequestURL().origin}/my/`
|
||||||
|
|
||||||
|
interface Props extends PrimitiveProps {
|
||||||
|
size?: ButtonVariants["size"]
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<Props>()
|
||||||
|
|
||||||
|
async function handleGoogleLogin() {
|
||||||
|
const { error } = await auth.signInWithOAuth({
|
||||||
|
provider: "google",
|
||||||
|
options: {
|
||||||
|
queryParams: {
|
||||||
|
access_type: "offline",
|
||||||
|
prompt: "consent"
|
||||||
|
},
|
||||||
|
redirectTo: profileUrl
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.log(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TransitionGroup name="fade-group" appear>
|
||||||
|
<UiButton v-if="user" as-child :size>
|
||||||
|
<NuxtLink to="/my">
|
||||||
|
Dashboard
|
||||||
|
</NuxtLink>
|
||||||
|
</UiButton>
|
||||||
|
<UiButton v-else @click="handleGoogleLogin" :size>
|
||||||
|
Log in
|
||||||
|
</UiButton>
|
||||||
|
</TransitionGroup>
|
||||||
|
</template>
|
||||||
@@ -60,38 +60,32 @@ switch (statusCode) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-screen">
|
<div class="h-screen">
|
||||||
<div class="h-full grid grid-cols-[auto_1fr] transition-colors">
|
<div class="h-full w-full grid place-items-center transition-colors">
|
||||||
<Sidebar />
|
<Head>
|
||||||
|
<Title>{{ $t(titleKey) }}</Title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
<div class="wrapper shadow-body-light dark:shadow-body-dark transition-all">
|
<div class="grid text-center justify-items-center opacity-80">
|
||||||
<div class="h-full w-full grid place-items-center">
|
<PhImageBroken v-if="statusCode === 404" size="100" class="opacity-60" />
|
||||||
<Head>
|
<PhLinkBreak v-else-if="statusCode === 500" size="100" class="opacity-60" />
|
||||||
<Title>{{ $t(titleKey) }}</Title>
|
<PhBugBeetle v-else size="100" class="opacity-60" />
|
||||||
</Head>
|
|
||||||
|
|
||||||
<div class="grid text-center justify-items-center opacity-80">
|
<Heading level="h0">
|
||||||
<PhImageBroken v-if="statusCode === 404" size="100" class="opacity-60" />
|
{{ $t(titleKey) }}
|
||||||
<PhLinkBreak v-else-if="statusCode === 500" size="100" class="opacity-60" />
|
</Heading>
|
||||||
<PhBugBeetle v-else size="100" class="opacity-60" />
|
|
||||||
|
|
||||||
<Heading level="h0">
|
<div class="mt-6 md:text-lg">
|
||||||
{{ $t(titleKey) }}
|
<p>{{ $t(descriptionKey) }}</p>
|
||||||
</Heading>
|
<p>{{ $t(subDescriptionKey) }}</p>
|
||||||
|
|
||||||
<div class="mt-6 md:text-lg">
|
|
||||||
<p>{{ $t(descriptionKey) }}</p>
|
|
||||||
<p>{{ $t(subDescriptionKey) }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<UiButton variant="default" class="mt-6 gap-2" as-child>
|
|
||||||
<RouterLink to="/">
|
|
||||||
<PhArrowBendDoubleUpLeft size="24" />
|
|
||||||
|
|
||||||
{{ $t('ui.backToHome') }}
|
|
||||||
</RouterLink>
|
|
||||||
</UiButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<UiButton variant="default" class="mt-6 gap-2" as-child>
|
||||||
|
<RouterLink to="/">
|
||||||
|
<PhArrowBendDoubleUpLeft size="24" />
|
||||||
|
|
||||||
|
{{ $t('ui.backToHome') }}
|
||||||
|
</RouterLink>
|
||||||
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="wrapper max-h-screen h-full transition-all overflow-y-auto"
|
class="wrapper max-h-screen h-full transition-all overflow-y-auto grid grid-rows-[auto_1fr]"
|
||||||
>
|
>
|
||||||
<slot />
|
<Navbar />
|
||||||
|
|
||||||
|
<div class="inner-content">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.inner-content {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
inset-inline: 0;
|
||||||
|
top: 0;
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
height: .1rem;
|
||||||
|
max-width: 100%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 0%,
|
||||||
|
transparent 10%,
|
||||||
|
color-mix(in srgb, var(--color-primary) 50%, transparent) 25%,
|
||||||
|
color-mix(in srgb, var(--color-primary) 50%, transparent) 75%,
|
||||||
|
transparent 90%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -34,6 +34,6 @@ watch(locale, () => refresh())
|
|||||||
<PhCircleNotch size="50" class="opacity-33 animate-spin"/>
|
<PhCircleNotch size="50" class="opacity-33 animate-spin"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LazyContentRenderer v-else-if="status === 'success' && page" :value="page" class="content max-w-5xl" />
|
<LazyContentRenderer v-else-if="status === 'success' && page" :value="page" class="content max-w-4xl" />
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -6,27 +6,6 @@ useHead({
|
|||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "public"
|
layout: "public"
|
||||||
})
|
})
|
||||||
|
|
||||||
const { auth } = useSupabaseClient()
|
|
||||||
const user = useSupabaseUser()
|
|
||||||
const profileUrl: string = `${useRequestURL().origin}/my/`
|
|
||||||
|
|
||||||
async function handleGoogleLogin() {
|
|
||||||
const { error } = await auth.signInWithOAuth({
|
|
||||||
provider: "google",
|
|
||||||
options: {
|
|
||||||
queryParams: {
|
|
||||||
access_type: "offline",
|
|
||||||
prompt: "consent"
|
|
||||||
},
|
|
||||||
redirectTo: profileUrl
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.log(error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -39,20 +18,15 @@ async function handleGoogleLogin() {
|
|||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<div class="py-8 md:py-24 px-4">
|
<div class="py-8 md:py-24 px-4">
|
||||||
<div class="flow text-center max-w-2xl mx-auto">
|
<div class="flow text-center max-w-4xl mx-auto">
|
||||||
<h1 class="text-3xl md:text-5xl font-bold md:font-semibold">A home for your creativity</h1>
|
<h1 class="text-3xl md:text-5xl font-bold md:font-semibold">
|
||||||
<p class="text-sm">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ipsam eos rem accusantium voluptates? Inventore dolorum reprehenderit quibusdam consequatur, totam iusto velit neque dolor dicta possimus cum, deleniti, saepe expedita culpa!</p>
|
{{ $t('pages.home.h1') }}
|
||||||
|
</h1>
|
||||||
|
<p class="text-sm">
|
||||||
|
{{ $t('pages.home.tagline') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<TransitionGroup name="fade-group" appear>
|
<UserDashboardLink />
|
||||||
<UiButton v-if="user" as-child>
|
|
||||||
<NuxtLink to="/my">
|
|
||||||
Dashboard
|
|
||||||
</NuxtLink>
|
|
||||||
</UiButton>
|
|
||||||
<UiButton v-else @click="handleGoogleLogin">
|
|
||||||
Log in
|
|
||||||
</UiButton>
|
|
||||||
</TransitionGroup>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -327,6 +327,10 @@ export default defineI18nConfig(() => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
pages: {
|
pages: {
|
||||||
|
home: {
|
||||||
|
h1: "A home for your creativity",
|
||||||
|
tagline: "Visualize your fantasy or sci-fi worlds with our interactive calendars"
|
||||||
|
},
|
||||||
explore: {
|
explore: {
|
||||||
menuLabel: "Explore",
|
menuLabel: "Explore",
|
||||||
title: "Explore worlds",
|
title: "Explore worlds",
|
||||||
@@ -677,6 +681,10 @@ export default defineI18nConfig(() => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
pages: {
|
pages: {
|
||||||
|
home: {
|
||||||
|
h1: "Un espace pour votre créativité",
|
||||||
|
tagline: "Visualisez vos mondes fantasy ou de science-fiction grâce à nos calendriers interactifs"
|
||||||
|
},
|
||||||
explore: {
|
explore: {
|
||||||
menuLabel: "Explorer",
|
menuLabel: "Explorer",
|
||||||
title: "Explorer les mondes",
|
title: "Explorer les mondes",
|
||||||
|
|||||||
Reference in New Issue
Block a user