feat(frontend): Phase 1 UX foundation — react-router v6 + responsive AppShell
Atomic foundation for the consensus-approved UX modernization (makes the platform URL-addressable, refresh-safe, and mobile-usable for hospital demos). - Migrate hand-rolled useState page switching → react-router v6 (routes.tsx, thin App.tsx auth gate, NavLink SideNav, lazy+Suspense per route) - Add responsive AppShell: persistent rail (lg:) ⇄ off-canvas drawer + hamburger (<lg); kills hardcoded ml-[200px]; usable at 375px - Add ui primitive kit (Skeleton/LoadingState/EmptyState/Card/Panel/Segmented) - Sweep all raw "加载中..." text loaders → skeleton primitives (G4) - Centralize test ids (utils/testids.ts); rewrite e2e for URL nav (17/17 pass: deep-link, refresh-preserves-page, back, 375px drawer/no-scroll) - Harden DemographicAnalysis against API shape mismatch (defensive normalize) - gitignore playwright-report/ and test-results/ Gates: tsc --noEmit 0 · pnpm build ok · e2e 17/17 · grep 加载中 zero outside ui/ Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
29
frontend/src/components/ui/EmptyState.tsx
Normal file
29
frontend/src/components/ui/EmptyState.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React, { memo } from 'react';
|
||||
|
||||
export const EmptyState = memo(function EmptyState({
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
action,
|
||||
}: {
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: React.ReactNode;
|
||||
action?: React.ReactNode;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
data-testid="empty-state"
|
||||
className="flex flex-col items-center justify-center gap-3 py-12 px-6 text-center"
|
||||
>
|
||||
{icon && (
|
||||
<div className="text-text-muted text-4xl">{icon}</div>
|
||||
)}
|
||||
<p className="text-sm font-medium text-text-secondary">{title}</p>
|
||||
{description && (
|
||||
<p className="text-xs text-text-muted max-w-xs">{description}</p>
|
||||
)}
|
||||
{action && <div className="mt-2">{action}</div>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user