- LyricSearch: misc/field focus, validation
- Nav: further improvements
This commit is contained in:
BIN
public/images/zim.png
Normal file
BIN
public/images/zim.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -195,6 +195,11 @@ blockquote p:first-of-type::after {
|
||||
Custom
|
||||
*/
|
||||
|
||||
.logo-auth {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: grid;
|
||||
align-items: end;
|
||||
|
||||
@@ -101,8 +101,8 @@ export default function LoginPage() {
|
||||
<div className="flex items-start justify-center bg-gray-50 dark:bg-[#121212] px-4 pt-20 py-10">
|
||||
<div className="max-w-md w-full bg-white dark:bg-[#1E1E1E] rounded-2xl shadow-xl px-10 pb-6">
|
||||
<h2 className="flex flex-col items-center text-3xl font-semibold text-gray-900 dark:text-white mb-8 font-sans">
|
||||
<img className="logo-auth mb-4" src="/images/kode.png" alt="Logo" />
|
||||
Authentication Required
|
||||
<img className="logo-auth mb-4" src="/images/zim.png" alt="Logo" />
|
||||
Log In
|
||||
</h2>
|
||||
|
||||
<form className="space-y-6 relative" onSubmit={handleSubmit} noValidate>
|
||||
|
||||
@@ -324,6 +324,16 @@ export function LyricSearchInputField({ id, placeholder, setShowLyrics }) {
|
||||
const statusTitle = statusLabels[inputStatus];
|
||||
const StatusIcon = statusIcons[inputStatus] || RemoveRoundedIcon;
|
||||
|
||||
useEffect(() => {
|
||||
const inputEl = autoCompleteInputRef.current;
|
||||
if (!inputEl) return;
|
||||
if (statusTitle) {
|
||||
inputEl.setAttribute("title", statusTitle);
|
||||
} else {
|
||||
inputEl.removeAttribute("title");
|
||||
}
|
||||
}, [statusTitle]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="lyric-search-input-wrapper">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { metaData, API_URL } from "../config";
|
||||
import { Icon } from "astro-icon/components";
|
||||
|
||||
const isLoggedIn = Astro.cookies.get('access_token') || Astro.cookies.get('refresh_token');
|
||||
const isLoggedIn = Boolean(Astro.cookies.get('access_token') || Astro.cookies.get('refresh_token'));
|
||||
|
||||
const padlockIconSvg = `
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24">
|
||||
@@ -22,13 +22,26 @@ const navItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
{ label: "Radio", href: "/radio" },
|
||||
{ label: "Memes", href: "/memes" },
|
||||
{ label: "Lighting", href: "/lighting", auth: true, icon: "padlock" },
|
||||
{ label: "TRip", href: "/TRip", auth: true, icon: "padlock" },
|
||||
{ label: "Lighting", href: "/lighting", auth: true },
|
||||
{ label: "TRip", href: "/TRip", auth: true, icon: "pirate" },
|
||||
{ label: "Status", href: "https://status.boatson.boats", icon: "external" },
|
||||
{ label: "Git", href: "https://kode.boatson.boats", icon: "external" },
|
||||
{ label: "Login", href: "/login", guestOnly: true },
|
||||
...(isLoggedIn ? [{ label: "Logout", href: "#logout", onclick: "handleLogout()" }] : []),
|
||||
];
|
||||
|
||||
const visibleNavItems = navItems.filter((item) => {
|
||||
if (item.auth && !isLoggedIn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.guestOnly && isLoggedIn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
const currentPath = Astro.url.pathname;
|
||||
|
||||
---
|
||||
@@ -37,7 +50,7 @@ const currentPath = Astro.url.pathname;
|
||||
|
||||
<nav class="w-full px-4 sm:px-6 py-4 bg-transparent sticky top-0 z-50 backdrop-blur-sm bg-white/80 dark:bg-[#121212]/80 border-b border-neutral-200/50 dark:border-neutral-800/50">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="nav-bar-row flex items-center gap-4 justify-between">
|
||||
<!-- Logo/Brand -->
|
||||
<a
|
||||
href="/"
|
||||
@@ -47,9 +60,9 @@ const currentPath = Astro.url.pathname;
|
||||
</a>
|
||||
|
||||
<!-- Desktop Navigation -->
|
||||
<div class="desktop-nav flex items-center gap-0.5">
|
||||
<ul class="flex items-center gap-0.5">
|
||||
{navItems.map((item) => {
|
||||
<div class="desktop-nav flex items-center">
|
||||
<ul class="desktop-nav-list">
|
||||
{visibleNavItems.map((item) => {
|
||||
const isExternal = item.href?.startsWith("http");
|
||||
const isAuthedPath = item.auth ?? false;
|
||||
const normalize = (url) => (url || '/').replace(/\/+$/, '') || '/';
|
||||
@@ -80,6 +93,9 @@ const currentPath = Astro.url.pathname;
|
||||
{item.icon === "padlock" && (
|
||||
<span class="inline-flex" aria-hidden="true" set:html={padlockIconSvg}></span>
|
||||
)}
|
||||
{item.icon === "pirate" && (
|
||||
<span class="inline-flex ml-1" role="img" aria-label="Pirate flag">🏴☠️</span>
|
||||
)}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -90,7 +106,7 @@ const currentPath = Astro.url.pathname;
|
||||
<button
|
||||
aria-label="Toggle theme"
|
||||
type="button"
|
||||
class="flex items-center justify-center w-8 h-8 ml-1 rounded-md hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"
|
||||
class="flex items-center justify-center w-8 h-8 rounded-md hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"
|
||||
onclick="toggleTheme()"
|
||||
>
|
||||
<Icon
|
||||
@@ -137,7 +153,7 @@ const currentPath = Astro.url.pathname;
|
||||
class="mobile-menu-dropdown md:hidden"
|
||||
>
|
||||
<ul class="flex flex-col gap-1 py-4">
|
||||
{navItems.map((item) => {
|
||||
{visibleNavItems.map((item) => {
|
||||
const isExternal = item.href?.startsWith("http");
|
||||
const isAuthedPath = item.auth ?? false;
|
||||
const normalize = (url) => (url || '/').replace(/\/+$/, '') || '/';
|
||||
@@ -168,6 +184,9 @@ const currentPath = Astro.url.pathname;
|
||||
{item.icon === "padlock" && (
|
||||
<span class="inline-flex" aria-hidden="true" set:html={padlockIconSvg}></span>
|
||||
)}
|
||||
{item.icon === "pirate" && (
|
||||
<span class="inline-flex ml-1" role="img" aria-label="Pirate flag">🏴☠️</span>
|
||||
)}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -222,4 +241,38 @@ const currentPath = Astro.url.pathname;
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user