Comprehensive UX audit fixes: navigation, feedback, affordances, and accessibility
CI / build-and-push (push) Successful in 28s

Address 18 issues across high/medium/low impact tiers identified in a full
interface review. Key changes: Models page decomposed into tabs, confirmation
dialogs for irreversible actions (deploy/open-source/acquire), chart Y-axes
made visible, hash router extended for Market tab persistence, collapsible
sidebar, keyboard navigation shortcuts (g+key chords), notification bulk
actions, achievement progress bars, and ARIA label improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 09:05:26 -04:00
parent 09a5cb69a7
commit 8d650fefae
17 changed files with 332 additions and 82 deletions
+13 -8
View File
@@ -2,7 +2,7 @@ import { useGameStore } from '@/store';
import { formatMoney, formatNumber, formatPercent } from '@ai-tycoon/shared';
import {
DollarSign, Server, Brain, Users, TrendingUp,
TrendingDown, Minus, Cpu, Zap, Shield,
TrendingDown, Minus, Cpu, Zap, Shield, ChevronRight,
} from 'lucide-react';
import { XAxis, YAxis, Tooltip, ResponsiveContainer, Area, AreaChart } from 'recharts';
import { TutorialHint } from '@/components/game/TutorialHint';
@@ -94,7 +94,7 @@ export function DashboardPage() {
</linearGradient>
</defs>
<XAxis dataKey="tick" hide />
<YAxis hide />
<YAxis width={50} tickFormatter={(v: number) => formatMoney(v)} tick={{ fontSize: 10, fill: '#64748b' }} axisLine={false} tickLine={false} />
<Tooltip
contentStyle={{ backgroundColor: '#1e293b', border: '1px solid #334155', borderRadius: '8px' }}
labelStyle={{ color: '#94a3b8' }}
@@ -151,7 +151,7 @@ export function DashboardPage() {
</linearGradient>
</defs>
<XAxis dataKey="tick" hide />
<YAxis hide />
<YAxis width={50} tickFormatter={(v: number) => formatNumber(v)} tick={{ fontSize: 10, fill: '#64748b' }} axisLine={false} tickLine={false} />
<Tooltip
contentStyle={{ backgroundColor: '#1e293b', border: '1px solid #334155', borderRadius: '8px' }}
formatter={(value: number) => [formatNumber(value), 'Subscribers']}
@@ -178,7 +178,7 @@ export function DashboardPage() {
</linearGradient>
</defs>
<XAxis dataKey="tick" hide />
<YAxis hide domain={[0, 100]} />
<YAxis width={30} domain={[0, 100]} tickFormatter={(v: number) => `${v}`} tick={{ fontSize: 10, fill: '#64748b' }} axisLine={false} tickLine={false} />
<Tooltip
contentStyle={{ backgroundColor: '#1e293b', border: '1px solid #334155', borderRadius: '8px' }}
formatter={(value: number) => [`${value}/100`, 'Reputation']}
@@ -225,12 +225,15 @@ function StatCard({
}) {
return (
<div
className={`bg-surface-900 border border-surface-700 rounded-xl p-4 ${onClick ? 'cursor-pointer hover:border-accent/30 transition-colors' : ''}`}
className={`bg-surface-900 border border-surface-700 rounded-xl p-4 ${onClick ? 'cursor-pointer hover:border-accent/50 transition-colors group' : ''}`}
onClick={onClick}
>
<div className="flex items-center gap-2 mb-2">
<Icon size={16} className={color ?? 'text-surface-400'} />
<span className="text-xs text-surface-400 uppercase tracking-wider">{label}</span>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<Icon size={16} className={color ?? 'text-surface-400'} />
<span className="text-xs text-surface-400 uppercase tracking-wider">{label}</span>
</div>
{onClick && <ChevronRight size={14} className="text-surface-500 group-hover:text-accent-light group-hover:translate-x-0.5 transition-all" />}
</div>
<div className="text-2xl font-bold font-mono">{value}</div>
{subValue && (
@@ -256,12 +259,14 @@ function StatusRow({
bar: number;
barColor: string;
}) {
const severity = barColor.includes('danger') ? 'Critical' : barColor.includes('warning') ? 'Warning' : null;
return (
<div>
<div className="flex items-center justify-between mb-1">
<div className="flex items-center gap-2">
<Icon size={14} className="text-surface-400" />
<span className="text-sm text-surface-300">{label}</span>
{severity && <span className={`text-[10px] px-1.5 py-0.5 rounded ${barColor.includes('danger') ? 'bg-danger/20 text-danger' : 'bg-warning/20 text-warning'}`}>{severity}</span>}
</div>
<span className="text-sm font-mono text-surface-200">{value}</span>
</div>