Comprehensive UX audit fixes: navigation, feedback, affordances, and accessibility
CI / build-and-push (push) Successful in 28s
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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user