redesign the homepage
Build & Deploy / Build & Push Docker Image (push) Failing after 47s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m4s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s

This commit is contained in:
root
2026-06-26 16:27:21 -04:00
parent 256ff0814e
commit d7fb7b7a7b
1030 changed files with 107374 additions and 2657 deletions
@@ -0,0 +1,146 @@
'use client';
import { ActionLink } from '@/components/actions/ActionLink';
import { DemoTrigger } from '@/components/integrations/DemoTrigger';
import type { ShellMessages } from '@/lib/localization/messages';
import { localizedPath, type Locale } from '@/lib/localization/config';
import type { ThemePreference } from '@/lib/theme/config';
import { useEffect, useRef, useState } from 'react';
import { HeaderNavigation } from './HeaderNavigation';
import { LocaleSelector } from './LocaleSelector';
import styles from './SiteHeader.module.css';
import { ThemeSelector } from './ThemeSelector';
function signInUrl(locale: Locale): string {
return localizedPath('sign-in', locale);
}
interface MobileNavigationProps {
locale: Locale;
messages: ShellMessages;
themePreference: ThemePreference;
demoEnabled: boolean;
}
export function MobileNavigation({
locale,
messages,
themePreference,
demoEnabled,
}: MobileNavigationProps) {
const [open, setOpen] = useState(false);
const dialogRef = useRef<HTMLDialogElement>(null);
const triggerRef = useRef<HTMLButtonElement>(null);
const closeRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
const dialog = dialogRef.current;
if (!dialog) return;
if (open && !dialog.open) {
dialog.showModal();
document.body.dataset.navigationOpen = 'true';
closeRef.current?.focus();
} else if (!open && dialog.open) {
dialog.close();
}
return () => {
delete document.body.dataset.navigationOpen;
};
}, [open]);
const close = () => {
dialogRef.current?.close();
setOpen(false);
delete document.body.dataset.navigationOpen;
window.requestAnimationFrame(() => triggerRef.current?.focus());
};
return (
<div className={styles.mobileNavigation}>
<button
ref={triggerRef}
type="button"
className={styles.menuButton}
aria-label={messages.header.menuOpen}
aria-haspopup="dialog"
aria-expanded={open}
onClick={() => setOpen(true)}
>
<span aria-hidden="true" className={styles.menuIcon}>
<span />
<span />
<span />
</span>
</button>
<dialog
ref={dialogRef}
className={styles.drawer}
aria-label={messages.header.navigationLabel}
onClose={() => {
setOpen(false);
delete document.body.dataset.navigationOpen;
}}
onCancel={(event) => {
event.preventDefault();
close();
}}
>
<div className={styles.drawerPanel}>
<div className={styles.drawerHeader}>
<strong>RentalDriveGo</strong>
<button
ref={closeRef}
type="button"
className={styles.closeButton}
aria-label={messages.header.menuClose}
onClick={close}
>
<span aria-hidden="true">×</span>
</button>
</div>
<HeaderNavigation
locale={locale}
label={messages.header.navigationLabel}
labels={messages.header.nav}
mobile
onNavigate={close}
/>
<div
className={styles.drawerControls}
role="group"
aria-label={messages.header.controlsLabel}
>
<LocaleSelector
currentLocale={locale}
label={messages.controls.language}
localeNames={messages.controls.localeNames}
/>
<ThemeSelector
initialPreference={themePreference}
label={messages.controls.theme}
statusTemplate={messages.controls.themeStatus}
optionLabels={messages.controls.themes}
/>
</div>
<div className={styles.drawerActions}>
<ActionLink href={signInUrl(locale)} variant="button-primary">
{messages.header.login}
</ActionLink>
<DemoTrigger
label={messages.header.demo}
source="mobile-header"
fullWidth
disabledReason={demoEnabled ? undefined : messages.header.demoUnavailable}
/>
</div>
</div>
</dialog>
</div>
);
}