website refactor

This commit is contained in:
2026-01-19 19:15:21 +01:00
parent 4ce89c1cc4
commit 5715e35790
4 changed files with 117 additions and 156 deletions

View File

@@ -1,77 +1,45 @@
import { AppFooter } from '@/components/app/AppFooter';
import { Grid } from '@/ui/Grid';
import { Surface } from '@/ui/Surface';
import { Container } from '@/ui/Container';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Link } from '@/ui/Link';
import { BrandMark } from '@/ui/BrandMark';
import { Box } from '@/ui/Box';
import { BrandMark } from '@/ui/BrandMark';
export interface GlobalFooterViewData {}
export function GlobalFooterTemplate(_props: GlobalFooterViewData) {
return (
<AppFooter>
<Grid cols={{ base: 1, md: 4 }} gap={12}>
<Stack colSpan={{ base: 1, md: 2 }} gap={6}>
<Stack direction="row" align="center" gap={4}>
<Surface as="footer" variant="muted" borderTop paddingY={6}>
<Container size="full">
<Box display="flex" flexDirection={{ base: 'col', md: 'row' }} alignItems="center" justifyContent="between" gap={4}>
{/* Left: Identity */}
<Stack direction="row" align="center" gap={3}>
<BrandMark />
<Box display={{ base: 'none', sm: 'flex' }} alignItems="center" gap={2} borderLeft borderColor="var(--ui-color-border-default)" pl={4}>
<Box w="4px" h="4px" rounded="full" bg="var(--ui-color-intent-primary)" animate="pulse" />
<Text size="xs" variant="low" weight="bold" font="mono" letterSpacing="0.1em">
INFRASTRUCTURE
</Text>
</Box>
</Stack>
<Stack maxWidth="sm">
<Text variant="low" size="sm">
The professional infrastructure for serious sim racing.
Precision telemetry, automated results, and elite league management.
<Text size="xs" variant="low" font="mono" uppercase letterSpacing="wider">
// Infrastructure
</Text>
</Stack>
</Stack>
<Stack gap={4}>
<Text size="xs" weight="bold" variant="high" uppercase letterSpacing="wider">PLATFORM</Text>
<Stack as="ul" direction="col" gap={2}>
<Stack as="li">
<Link href="/leagues" variant="secondary">
Leagues
</Link>
</Stack>
<Stack as="li">
<Link href="/teams" variant="secondary">
Teams
</Link>
</Stack>
<Stack as="li">
<Link href="/leaderboards" variant="secondary">
Leaderboards
</Link>
</Stack>
{/* Center: Technical Links */}
<Stack direction="row" gap={6} display={{ base: 'none', md: 'flex' }}>
<Link href="/leagues" variant="secondary" size="xs" underline="none">LEAGUES</Link>
<Link href="/teams" variant="secondary" size="xs" underline="none">TEAMS</Link>
<Link href="/docs" variant="secondary" size="xs" underline="none">DOCUMENTATION</Link>
</Stack>
</Stack>
<Stack gap={4}>
<Text size="xs" weight="bold" variant="high" uppercase letterSpacing="wider">SUPPORT</Text>
<Stack as="ul" direction="col" gap={2}>
<Stack as="li">
<Link href="/docs" variant="secondary">
Documentation
</Link>
</Stack>
<Stack as="li">
<Link href="/status" variant="secondary">
System Status
</Link>
</Stack>
<Stack as="li">
<Link href="/contact" variant="secondary">
Contact
</Link>
</Stack>
{/* Right: System Status */}
<Stack direction="row" align="center" gap={4}>
<Box display="flex" alignItems="center" gap={2}>
<Box w="6px" h="6px" rounded="full" bg="var(--ui-color-intent-success)" animate="pulse" />
<Text size="xs" variant="low" font="mono">SYSTEM NOMINAL</Text>
</Box>
<Text size="xs" variant="low" font="mono">v1.0.0</Text>
</Stack>
</Stack>
</Grid>
</AppFooter>
</Box>
</Container>
</Surface>
);
}

View File

@@ -41,16 +41,17 @@ export function RootAppShellTemplate({ children }: RootAppShellViewData) {
</TopNav>
</ControlBar>
<Box display="flex" flexGrow={1}>
<Box display="flex" flexGrow={1} width="full">
{showSidebar && <GlobalSidebarTemplate />}
<Box as="main" display="flex" flexGrow={1} flexDirection="col">
<Box as="main" display="flex" flexGrow={1} flexDirection="col" minWidth="0">
<ContentViewport fullWidth={!showSidebar}>
{children}
</ContentViewport>
<GlobalFooterTemplate />
</Box>
</Box>
<GlobalFooterTemplate />
</AppShell>
);
}

View File

@@ -21,11 +21,9 @@ export const ContentViewport = ({
};
return (
<Box flexGrow={1}>
<Container size={fullWidth ? 'full' : 'xl'}>
<Box paddingY={paddingMap[padding]}>
{children}
</Box>
<Box flexGrow={1} width="full">
<Container size={fullWidth ? 'full' : 'xl'} py={paddingMap[padding]}>
{children}
</Container>
</Box>
);

View File

@@ -1,140 +1,134 @@
🎨 GridPilot Dev Theme — “Precision Racing Minimal”
🎨 GridPilot Theme — “Precision Racing Minimal”
The core idea:
A UI that feels like a race engineers dashboard — not a game launcher, not corporate SaaS.
A clean, modern racing interface that feels like a cockpit dashboard — calm, sharp, and serious.
1. Identity & Mood
The theme should communicate:
Precision (like telemetry screens)
Calm intensity (the feeling before a qualifying lap)
Authority without ego (used by serious racers)
Modern minimalism (dev-friendly, clean structure)
Soft gaming hints (subtle neon touches, not RGB vomit)
GridPilot should feel like:
a real motorsport instrument, not a game launcher
calm and focused, like the moment before a qualifying lap
precise, like a telemetry screen
modern and minimal, without visual noise
slightly futuristic, but never “RGB gamer chaos”
It appeals equally to:
• Devs (clean, modular, readable components)
• Gamers (immersive, familiar atmosphere)
• Simracers (motorsport seriousness)
It should appeal equally to sim racers, gamers, and casual fans.
2. Visual Language
2. Visual Style
Primary Look
Dark, matte surfaces
Thin, crisp separators
Soft glow accents in blue / cyan / purple
Avoid aggressive neon or gamer-overload
Subtle gradient tints (barely visible)
Core Aesthetic
• matte dark surfaces
thin, crisp separators
soft blue/cyan glows on interaction
no aggressive neon
subtle gradients for depth
• everything feels instrument-grade, not decorative
Color System
Base: Near-black graphite (#0C0D0F)
Surface: Deep charcoal (#141619)
Outline: Soft steel grey (#23272B)
Primary Accent: Electric blue (#198CFF)
• Telemetry Accent: Aqua (#4ED4E0)
Warning: Motorsport amber (#FFBE4D)
Graphite Black — base background
Charcoal — panel surfaces
Steel Grey — separators & outlines
• Electric Blue — primary actions
• Telemetry Aqua — interactive highlights
• Motorsport Amber — warnings & signals
Everything should feel instrument-grade, not decorative.
Colors should feel like motorsport, not corporate SaaS.
3. Component Philosophy
3. Components & Interaction
Cards
Functional over flashy
Slight bevel or inset shadow (hint of cockpit panels)
Dense info, clean hierarchy
Panels & Cards
slightly inset or raised
reminiscent of cockpit modules
structured and clean
Tables
High-density
Thin row dividers
Highlight on hover only
Telemetry-coded status colors
information-dense
instantly scannable
• light hover highlights
telemetry-style status colors
Buttons
Flat by default
Glow + gradient only on hover
Snappy micro-animation (motorsport feedback)
flat by default
glow only on hover
snappy, “race-engineer” response speed
Modals
Soft frosted blur
Fast open/close animation
Dimmed pit-lane-lighting vibe
soft frosted blur
fast open/close
subtle pit-lane lighting vibes
4. Motion & Feedback
Racing-inspired, but minimal:
Short accelerations (fast ease-out)
No bounces — this isnt a game store
Hover = slight lift + color pulse
Loading = progress line (like pit limiter light)
Switching tabs = sliding underline (chicane motion)
Motion should feel racing-inspired:
short, crisp animations
no bounce or playful movement
hover = slight lift + color pulse
loading = a thin progress line (pit limiter style)
tab switching = sliding underline (chicane motion)
Devs should feel the UI is responsive, not playful.
Responsive, not playful.
5. Layout Structure
Think Telemetry Workspace:
• Sidebar = dashboard rail
• Header = control bar
Content = track map / data table zone
• Right panel = session or context info
Think Telemetry Workspace:
• Sidebar → control rail
• Header → context + session controls
Main Area → race tables, session details, track maps
• Right Panel contextual info, drivers, actions
Everything modular, easily replaceable, easy to reason about.
Everything modular, readable, and effortless to navigate.
6. Tone for Dev-Facing Text
• Short
• Neutral
Calm
Technical
Real-world language (not corporate slang)
6. Tone & Copywriting
The product tone is:
calm
concise
direct
• technical but human
• zero hype
Examples:
• “Add race
• “Review protest
• “Session updated
• “Export standings
• “Sponsor payout queued”
• “Race added.
• “Standings updated.
• “Session ready.
• “Review protest.
• “Sponsor payout queued.
No hype. No marketing tone inside the app.
Never corporate. Never salesy. Never loud.
7. Emotional Target
7. Emotional Experience
Users should feel:
In control
Supported
Efficient
Connected to motorsport culture
Trusting (nothing looks cheap or gimmicky)
in control
supported
efficient
connected to motorsport culture
confident in the system
Its basically:
A disciplined, trustworthy tool — not a flashy app.
“A premium cockpit dashboard… built by people who race and code.”
8. UI Layering & Primitives
8. Overall Vibe
To maintain architectural integrity and prevent "div wrapper" abuse, we enforce a strict layering boundary:
“A premium cockpit dashboard — for people who actually race.”
• minimal
• precise
• clean
• serious
• attractive without noise
### Semantic UI (`apps/website/ui/`)
- **Building blocks for components**: `Card`, `Panel`, `Button`, `Table`, `Stack`, `Grid`.
- **Restricted flexibility**: Semantic layout components (like `Stack`, `Grid`) are restricted to layout-only props. They do NOT allow styling props (bg, border, etc.).
- **Public API**: These are the only UI elements that should be imported by `components/` or `pages/`.
### Components (`apps/website/components/`)
- **Domain-specific**: `RecentRacesPanel`, `DriverCard`, `LeagueHeader`.
- **No raw HTML**: Components must use semantic UI elements. Direct use of raw HTML tags is forbidden.
**Rule of thumb**: If you need a styled container in a component, use `Panel` or `Card`. If you need a new type of styled container, create it in `ui/` using primitives.
A tool youre happy to use, because it respects your time and your craft.