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>
23 lines
406 B
TypeScript
23 lines
406 B
TypeScript
import React, { memo } from 'react';
|
|
|
|
export const Panel = memo(function Panel({
|
|
children,
|
|
className,
|
|
testid,
|
|
}: {
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
testid?: string;
|
|
}): JSX.Element {
|
|
return (
|
|
<div
|
|
data-testid={testid}
|
|
className={['bg-bg-hover/50 rounded-md p-3', className]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
>
|
|
{children}
|
|
</div>
|
|
);
|
|
});
|