feat: Add user display in navigation
misc: styling/css cleanup
This commit is contained in:
126
src/assets/styles/nav.css
Normal file
126
src/assets/styles/nav.css
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/* Desktop navigation - visible on medium screens and up */
|
||||||
|
.desktop-nav {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.desktop-nav {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile navigation - visible below medium screens */
|
||||||
|
.mobile-nav {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.mobile-nav {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile menu dropdown */
|
||||||
|
.mobile-menu-dropdown {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease-in-out, opacity 0.3s ease-in-out;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-menu-dropdown.open {
|
||||||
|
max-height: 500px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.mobile-menu-dropdown {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
transition: background-color 0.2s ease, border-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-bar-row {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.desktop-nav {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 0;
|
||||||
|
margin-left: 2rem;
|
||||||
|
gap: clamp(0.75rem, 1.5vw, 1.25rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-nav-list {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: clamp(0.75rem, 1.5vw, 1.25rem);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-nav-list li {
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-nav-list a {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-user-inline {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
padding: 0.3rem 0.85rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.4);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #1e293b;
|
||||||
|
background: linear-gradient(120deg, rgba(255, 255, 255, 0.9), rgba(226, 232, 240, 0.85));
|
||||||
|
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .nav-user-inline {
|
||||||
|
color: #f1f5f9;
|
||||||
|
border-color: rgba(59, 130, 246, 0.25);
|
||||||
|
background: linear-gradient(120deg, rgba(15, 23, 42, 0.85), rgba(30, 41, 59, 0.7));
|
||||||
|
box-shadow: 0 14px 35px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-user-inline__icon {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 0.95rem;
|
||||||
|
height: 0.95rem;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-user-inline__icon svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-user-inline__label {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.65rem;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-user-inline__name {
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-user-inline--mobile {
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { AutoComplete } from "primereact/autocomplete";
|
|||||||
import { authFetch } from "@/utils/authFetch";
|
import { authFetch } from "@/utils/authFetch";
|
||||||
import BreadcrumbNav from "./BreadcrumbNav";
|
import BreadcrumbNav from "./BreadcrumbNav";
|
||||||
import { API_URL, ENVIRONMENT } from "@/config";
|
import { API_URL, ENVIRONMENT } from "@/config";
|
||||||
|
import "./MediaRequestForm.css";
|
||||||
|
|
||||||
export default function MediaRequestForm() {
|
export default function MediaRequestForm() {
|
||||||
const [type, setType] = useState("artist");
|
const [type, setType] = useState("artist");
|
||||||
|
|||||||
@@ -1,29 +1,22 @@
|
|||||||
---
|
---
|
||||||
import { metaData, API_URL } from "../config";
|
import { metaData, API_URL } from "../config";
|
||||||
import { Icon } from "astro-icon/components";
|
import { Icon } from "astro-icon/components";
|
||||||
|
import { requireAuthHook } from "@/hooks/requireAuthHook";
|
||||||
|
import { padlockIconSvg, userIconSvg, externalLinkIconSvg } from "@/utils/navAssets";
|
||||||
|
import "@/assets/styles/nav.css";
|
||||||
|
|
||||||
const isLoggedIn = Boolean(Astro.cookies.get('access_token') || Astro.cookies.get('refresh_token'));
|
const user = await requireAuthHook(Astro);
|
||||||
|
const isLoggedIn = Boolean(user);
|
||||||
|
const userDisplayName = user?.user ?? null;
|
||||||
|
const userInitial = userDisplayName ? String(userDisplayName).charAt(0).toUpperCase() : '?';
|
||||||
|
|
||||||
const padlockIconSvg = `
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M8.5 11V9a3.5 3.5 0 1 1 7 0v2" />
|
|
||||||
<rect x="7" y="11" width="10" height="8.5" rx="1.8" />
|
|
||||||
<circle cx="12" cy="15" r="1.2" fill="currentColor" />
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
|
|
||||||
const externalLinkIconSvg = `
|
|
||||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ label: "Home", href: "/" },
|
{ label: "Home", href: "/" },
|
||||||
{ label: "Radio", href: "/radio" },
|
{ label: "Radio", href: "/radio" },
|
||||||
{ label: "Memes", href: "/memes" },
|
{ label: "Memes", href: "/memes" },
|
||||||
|
{ label: "TRip", href: "/TRip", auth: true, icon: "pirate" },
|
||||||
{ label: "Lighting", href: "/lighting", auth: true },
|
{ label: "Lighting", href: "/lighting", auth: true },
|
||||||
{ label: "TRip", href: "/TRip", auth: true, icon: "pirate" },
|
|
||||||
{ label: "Status", href: "https://status.boatson.boats", icon: "external" },
|
{ label: "Status", href: "https://status.boatson.boats", icon: "external" },
|
||||||
{ label: "Git", href: "https://kode.boatson.boats", icon: "external" },
|
{ label: "Git", href: "https://kode.boatson.boats", icon: "external" },
|
||||||
{ label: "Login", href: "/login", guestOnly: true },
|
{ label: "Login", href: "/login", guestOnly: true },
|
||||||
@@ -102,6 +95,13 @@ const currentPath = Astro.url.pathname;
|
|||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{isLoggedIn && userDisplayName && (
|
||||||
|
<div class="nav-user-inline" title={`Logged in as ${userDisplayName}`}>
|
||||||
|
<span class="nav-user-inline__icon" aria-hidden="true" set:html={userIconSvg}></span>
|
||||||
|
<span class="nav-user-inline__name">{userDisplayName}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<!-- Theme Toggle Desktop -->
|
<!-- Theme Toggle Desktop -->
|
||||||
<button
|
<button
|
||||||
aria-label="Toggle theme"
|
aria-label="Toggle theme"
|
||||||
@@ -152,6 +152,12 @@ const currentPath = Astro.url.pathname;
|
|||||||
id="mobile-menu"
|
id="mobile-menu"
|
||||||
class="mobile-menu-dropdown md:hidden"
|
class="mobile-menu-dropdown md:hidden"
|
||||||
>
|
>
|
||||||
|
{isLoggedIn && userDisplayName && (
|
||||||
|
<div class="nav-user-inline nav-user-inline--mobile" title={`Logged in as ${userDisplayName}`}>
|
||||||
|
<span class="nav-user-inline__icon" aria-hidden="true" set:html={userIconSvg}></span>
|
||||||
|
<span class="nav-user-inline__name">{userDisplayName}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<ul class="flex flex-col gap-1 py-4">
|
<ul class="flex flex-col gap-1 py-4">
|
||||||
{visibleNavItems.map((item) => {
|
{visibleNavItems.map((item) => {
|
||||||
const isExternal = item.href?.startsWith("http");
|
const isExternal = item.href?.startsWith("http");
|
||||||
@@ -195,84 +201,3 @@ const currentPath = Astro.url.pathname;
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Desktop navigation - visible on medium screens and up */
|
|
||||||
.desktop-nav {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.desktop-nav {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile navigation - visible below medium screens */
|
|
||||||
.mobile-nav {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.mobile-nav {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile menu dropdown */
|
|
||||||
.mobile-menu-dropdown {
|
|
||||||
max-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
transition: max-height 0.3s ease-in-out, opacity 0.3s ease-in-out;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-menu-dropdown.open {
|
|
||||||
max-height: 500px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.mobile-menu-dropdown {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-bar-row {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.desktop-nav {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-width: 0;
|
|
||||||
margin-left: 2rem;
|
|
||||||
gap: clamp(0.75rem, 1.5vw, 1.25rem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav-list {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
gap: clamp(0.75rem, 1.5vw, 1.25rem);
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav-list li {
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav-list a {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ if (!user || !user.roles.includes('lighting')) {
|
|||||||
<Base>
|
<Base>
|
||||||
<section>
|
<section>
|
||||||
<div class="prose prose-neutral dark:prose-invert">
|
<div class="prose prose-neutral dark:prose-invert">
|
||||||
<Root child="Lighting" user={user} client:only="react" />
|
<Root child="Lighting" user?={user} client:only="react" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</Base>
|
</Base>
|
||||||
|
|||||||
20
src/utils/navAssets.js
Normal file
20
src/utils/navAssets.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export const padlockIconSvg = `
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M8.5 11V9a3.5 3.5 0 1 1 7 0v2" />
|
||||||
|
<rect x="7" y="11" width="10" height="8.5" rx="1.8" />
|
||||||
|
<circle cx="12" cy="15" r="1.2" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const userIconSvg = `
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="9" r="3.2" />
|
||||||
|
<path d="M5.5 19.5a6.5 6.5 0 0 1 13 0" />
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const externalLinkIconSvg = `
|
||||||
|
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
Reference in New Issue
Block a user