Implement dark-first design system with Geist typography (#28)
All checks were successful
CI / backend-lint (push) Successful in 10s
CI / actions-lint (push) Successful in 16s
CI / frontend-lint (push) Successful in 21s

Co-authored-by: Julian Tabel <juliantabel.jt@gmail.com>
Co-committed-by: Julian Tabel <juliantabel.jt@gmail.com>
This commit was merged in pull request #28.
This commit is contained in:
2026-02-17 20:48:42 +01:00
committed by TheFurya
parent e3b3dc5317
commit 42b66ee9a2
56 changed files with 1151 additions and 1067 deletions

View File

@@ -86,7 +86,7 @@ export function RunDashboard() {
if (error || !run) {
return (
<div className="max-w-4xl mx-auto p-8">
<div className="rounded-lg bg-red-50 dark:bg-red-900/20 p-4 text-red-700 dark:text-red-400">
<div className="rounded-lg bg-status-failed-bg p-4 text-status-failed">
Failed to load run. It may not exist.
</div>
<Link to="/runs" className="inline-block mt-4 text-blue-600 hover:underline">
@@ -106,14 +106,14 @@ export function RunDashboard() {
<div className="mb-6">
<Link
to="/runs"
className="text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 mb-2 inline-block"
className="text-sm text-text-tertiary hover:text-text-primary mb-2 inline-block"
>
&larr; All Runs
</Link>
<div className="flex items-start justify-between">
<div>
<h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100">{run.name}</h1>
<p className="text-gray-600 dark:text-gray-400 mt-1">
<h1 className="text-3xl font-bold text-text-primary">{run.name}</h1>
<p className="text-text-tertiary mt-1">
{run.game.name} &middot;{' '}
{run.game.region.charAt(0).toUpperCase() + run.game.region.slice(1)} &middot; Started{' '}
{new Date(run.startedAt).toLocaleDateString(undefined, {
@@ -137,7 +137,7 @@ export function RunDashboard() {
className={`rounded-lg p-4 mb-6 ${
run.status === 'completed'
? 'bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800'
: 'bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800'
: 'bg-status-failed-bg border border-red-200 dark:border-red-800'
}`}
>
<div className="flex items-center gap-3">
@@ -156,9 +156,7 @@ export function RunDashboard() {
</p>
<p
className={`text-sm ${
run.status === 'completed'
? 'text-blue-600 dark:text-blue-400'
: 'text-red-600 dark:text-red-400'
run.status === 'completed' ? 'text-text-link' : 'text-status-failed'
}`}
>
{run.completedAt && (
@@ -189,21 +187,19 @@ export function RunDashboard() {
{/* Rules */}
<div className="mb-6">
<h2 className="text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">Active Rules</h2>
<h2 className="text-sm font-medium text-text-tertiary mb-2">Active Rules</h2>
<RuleBadges rules={run.rules} />
</div>
{/* Naming Scheme */}
{namingCategories && namingCategories.length > 0 && (
<div className="mb-6">
<h2 className="text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">
Naming Scheme
</h2>
<h2 className="text-sm font-medium text-text-tertiary mb-2">Naming Scheme</h2>
{isActive ? (
<select
value={run.namingScheme ?? ''}
onChange={(e) => updateRun.mutate({ namingScheme: e.target.value || null })}
className="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-1.5 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
className="text-sm border border-border-default rounded-lg px-3 py-1.5 bg-surface-1 text-text-primary"
>
<option value="">None</option>
{namingCategories.map((cat) => (
@@ -213,7 +209,7 @@ export function RunDashboard() {
))}
</select>
) : (
<span className="text-sm text-gray-900 dark:text-gray-100">
<span className="text-sm text-text-primary">
{run.namingScheme
? run.namingScheme.charAt(0).toUpperCase() + run.namingScheme.slice(1)
: 'None'}
@@ -225,14 +221,14 @@ export function RunDashboard() {
{/* Active Team */}
<div className="mb-6">
<div className="flex items-center justify-between mb-3">
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
<h2 className="text-lg font-semibold text-text-primary">
{isActive ? 'Active Team' : 'Final Team'}
</h2>
{alive.length > 1 && (
<select
value={teamSort}
onChange={(e) => setTeamSort(e.target.value as TeamSortKey)}
className="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-1.5 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
className="text-sm border border-border-default rounded-lg px-3 py-1.5 bg-surface-1 text-text-primary"
>
<option value="route">Route Order</option>
<option value="level">Catch Level</option>
@@ -242,7 +238,7 @@ export function RunDashboard() {
)}
</div>
{alive.length === 0 ? (
<p className="text-gray-500 dark:text-gray-400 text-sm">
<p className="text-text-tertiary text-sm">
No pokemon caught yet head to encounters to start building your team!
</p>
) : (
@@ -261,7 +257,7 @@ export function RunDashboard() {
{/* Graveyard */}
{dead.length > 0 && (
<div className="mb-6">
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-3">Graveyard</h2>
<h2 className="text-lg font-semibold text-text-primary mb-3">Graveyard</h2>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-3">
{dead.map((enc) => (
<PokemonCard
@@ -281,13 +277,13 @@ export function RunDashboard() {
<>
<Link
to={`/runs/${runId}/encounters`}
className="px-4 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors"
className="px-4 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-accent-400 focus:ring-offset-2 transition-colors"
>
Log Encounter
</Link>
<button
onClick={() => setShowEndRun(true)}
className="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg font-medium hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors"
className="px-4 py-2 border border-border-default rounded-lg font-medium hover:bg-surface-2 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors"
>
End Run
</button>