website refactor

This commit is contained in:
2026-01-20 00:33:24 +01:00
parent 6df1b50536
commit e9dfe15dff
12 changed files with 376 additions and 224 deletions

View File

@@ -1,26 +1,22 @@
import { Box } from '@/ui/Box';
import { Link } from '@/ui/Link';
import { Image } from '@/ui/Image';
import { Link } from '@/ui/Link';
interface BrandMarkProps {
href?: string;
priority?: boolean;
variant?: 'dark' | 'light';
collapsed?: boolean;
}
export function BrandMark({ href = '/' }: BrandMarkProps) {
export function BrandMark({ href = '/', collapsed = false }: BrandMarkProps) {
return (
<Link href={href} variant="inherit" underline="none">
<Box display="flex" alignItems="center" gap={2}>
<Box display="flex" alignItems="center" justifyContent={collapsed ? 'center' : 'start'}>
<Image
src="/images/logos/square-logo-dark.svg"
alt=""
style={{ height: '1.5rem', width: 'auto' }}
/>
<Image
src="/images/logos/wordmark-rectangle-dark.svg"
src="/images/logos/icon-square-dark.svg"
alt="GridPilot"
style={{ height: '1.125rem', width: 'auto' }}
style={{ height: '3rem', width: 'auto' }}
/>
</Box>
</Link>

View File

@@ -1,5 +1,6 @@
import { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from '@/ui/Box';
import { useSidebar } from '@/components/layout/SidebarContext';
export interface LayoutProps {
children: ReactNode;
@@ -22,22 +23,27 @@ export const Layout = ({
sidebar,
fixedSidebar = true,
fixedHeader = true,
fixedFooter = true // Default to true for AppShellBar
fixedFooter = true
}: LayoutProps) => {
const { isCollapsed } = useSidebar();
const sidebarWidth = isCollapsed ? '20' : '64'; // 5rem vs 16rem
const sidebarWidthClass = isCollapsed ? 'lg:w-20' : 'lg:w-64';
const contentMarginClass = isCollapsed ? 'lg:ml-20' : 'lg:ml-64';
return (
<Box display="flex" minHeight="100vh" className="bg-base-black text-text-high">
{/* Sidebar - Primary Vertical Axis - Solid Background */}
{sidebar && (
<Box
as="aside"
width="64" // 16rem / 256px
width={sidebarWidth}
display={{ base: 'none', lg: 'block' }}
position={fixedSidebar ? "fixed" : "relative"}
top={0}
bottom={0}
left={0}
zIndex={50}
className="bg-base-black border-r border-outline-steel"
style={{ zIndex: 60, width: isCollapsed ? '5rem' : '16rem' }} // Explicit style for width transition
className={`bg-base-black border-r border-outline-steel transition-all duration-300 ease-in-out`}
>
{sidebar}
</Box>
@@ -48,7 +54,7 @@ export const Layout = ({
display="flex"
flexDirection="col"
flex={1}
marginLeft={fixedSidebar && sidebar ? { lg: 64 } : undefined}
className={`transition-all duration-300 ease-in-out ${fixedSidebar && sidebar ? contentMarginClass : ''}`}
minWidth="0" // Prevent flex child overflow
>
{/* Header - Rendered directly as it contains AppShellBar (fixed) */}

View File

@@ -1,8 +1,8 @@
import { Box } from '@/ui/Box';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
import Link from 'next/link';
import { Text } from '@/ui/Text';
import { LucideIcon } from 'lucide-react';
import { LucideIcon, ChevronRight } from 'lucide-react';
interface NavLinkProps {
href: string;
@@ -10,58 +10,72 @@ interface NavLinkProps {
icon?: LucideIcon;
isActive?: boolean;
variant?: 'sidebar' | 'top';
collapsed?: boolean;
}
export function NavLink({ href, label, icon, isActive, variant = 'sidebar' }: NavLinkProps) {
export function NavLink({ href, label, icon, isActive, variant = 'sidebar', collapsed = false }: NavLinkProps) {
const isTop = variant === 'top';
// Dieter Rams style: Unobtrusive, Honest, Thorough.
// No glows. No shadows. Just clear contrast and alignment.
// Radical "Game Menu" Style
// Active: Solid Primary Color, Shadow, Bold.
// Inactive: Glass card with strong hover effects.
const content = (
<Box
display="flex"
alignItems="center"
gap={3}
paddingX={isTop ? 4 : 4}
paddingY={isTop ? 2 : 3}
justifyContent={collapsed ? 'center' : 'space-between'}
gap={collapsed ? 0 : 3}
paddingX={collapsed ? 2 : 4}
paddingY={3}
className={`
relative group transition-all duration-200 ease-out
relative transition-all duration-300 ease-out rounded-xl border w-full
${isActive
? 'text-text-high bg-white/5'
: 'text-text-med hover:text-text-high hover:bg-white/5'
? 'bg-primary-accent border-primary-accent shadow-[0_0_20px_rgba(25,140,255,0.3)]'
: 'bg-white/5 border-white/5 group-hover:bg-white/15 group-hover:border-white/20 group-hover:shadow-lg group-hover:shadow-white/5'
}
${!isTop && 'rounded-md mx-2'}
${!collapsed && isActive ? 'translate-x-2' : ''}
${!collapsed && !isActive ? 'group-hover:translate-x-2' : ''}
`}
title={collapsed ? label : undefined}
>
{icon && (
<Icon
icon={icon}
size={4}
className={`transition-colors duration-200 ${isActive ? 'text-primary-accent' : 'text-text-low group-hover:text-text-med'}`}
/>
)}
<Text
size="sm"
weight={isActive ? 'medium' : 'normal'}
variant="inherit"
className="tracking-wide"
>
{label}
</Text>
<Box display="flex" alignItems="center" gap={3} justifyContent={collapsed ? 'center' : 'start'} width={collapsed ? 'full' : 'auto'}>
{icon && (
<Icon
icon={icon}
size={5} // 20px
className={`transition-colors duration-200 ${isActive ? 'text-white' : 'text-text-med group-hover:text-white'}`}
/>
)}
{!collapsed && (
<Text
size="sm"
weight="bold"
variant="inherit"
className={`tracking-wide transition-colors duration-200 ${isActive ? 'text-white' : 'text-text-med group-hover:text-white'}`}
>
{label}
</Text>
)}
</Box>
{/* Minimal Active Indicator */}
{!isTop && isActive && (
<Box
className="absolute left-0 top-1/2 -translate-y-1/2 w-1 h-4 bg-primary-accent rounded-r-full"
{/* Chevron on Hover/Active - Only when expanded */}
{!collapsed && (
<Icon
icon={ChevronRight}
size={4}
className={`transition-all duration-300 ${isActive ? 'text-white opacity-100' : 'text-white opacity-0 group-hover:opacity-100 -translate-x-4 group-hover:translate-x-0'}`}
/>
)}
</Box>
);
return (
<Link href={href} variant="inherit" underline="none" block={!isTop}>
<Link
href={href}
className={`w-full group block ${!isTop ? '' : ''}`}
>
{content}
</Link>
);