쇼케이스 (/design-system.html): - 별도 Vite entry (System Flow 패턴 재사용, 메인 SPA 분리) - 10개 섹션: Intro / Token / Typography / Badge / Button / Form / Card / Layout / Catalog (19+) / Guide - 추적 ID 체계 (TRK-CATEGORY-SLUG): - hover 시 툴팁 + "ID 복사 모드"에서 클릭 시 클립보드 복사 - URL hash 딥링크 (#trk=TRK-BADGE-critical-sm) 스크롤+하이라이트 - 산출문서/논의에서 특정 변형 정확히 참조 가능 - Dark/Light 테마 토글로 양쪽 시각 검증 신규 공통 컴포넌트: - Button (@shared/components/ui/button.tsx) - 5 variant × 3 size = 15 변형 - primary/secondary/ghost/outline/destructive × sm/md/lg - Input / Select / Textarea / Checkbox / Radio - Input · Select 공통 inputVariants 공유 (sm/md/lg × default/error/success) - PageContainer / PageHeader / Section (shared/components/layout/) - PageContainer: size sm/md/lg + fullBleed (지도/풀화면 예외) - PageHeader: title + description + icon + demo 배지 + actions 슬롯 - Section: Card + CardHeader + CardTitle + CardContent 단축 variants.ts 확장: - buttonVariants / inputVariants / pageContainerVariants CVA 정의 - Button/Input/Select는 variants.ts에서 import하여 fast-refresh 경고 회피 빌드 검증 완료: - TypeScript 타입 체크 통과 - ESLint 통과 (경고 0) - vite build: designSystem-*.js 54KB (메인 SPA와 분리) 이 쇼케이스가 확정된 후 실제 40+ 페이지 마이그레이션 진행 예정.
178 lines
7.0 KiB
TypeScript
178 lines
7.0 KiB
TypeScript
import { TrkSectionHeader, Trk } from '../lib/Trk';
|
|
import { PageContainer, PageHeader, Section } from '@shared/components/layout';
|
|
import { Button } from '@shared/components/ui/button';
|
|
import { Input } from '@shared/components/ui/input';
|
|
import { Shield, BarChart3, Plus, Search } from 'lucide-react';
|
|
|
|
export function LayoutSection() {
|
|
return (
|
|
<>
|
|
<TrkSectionHeader
|
|
id="TRK-SEC-layout"
|
|
title="Layout 컴포넌트"
|
|
description="PageContainer · PageHeader · Section. 40+ 페이지 레이아웃 표준."
|
|
/>
|
|
|
|
{/* PageContainer */}
|
|
<h3 className="text-sm font-semibold text-heading mb-2 mt-2">PageContainer</h3>
|
|
<div className="ds-grid ds-grid-3">
|
|
<Trk id="TRK-LAYOUT-page-container-sm" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-1 block">size=sm (p-4 space-y-3)</label>
|
|
<div className="border border-dashed border-slate-600/40 rounded">
|
|
<PageContainer size="sm">
|
|
<div className="h-4 bg-blue-500/30 rounded" />
|
|
<div className="h-4 bg-blue-500/30 rounded" />
|
|
</PageContainer>
|
|
</div>
|
|
</Trk>
|
|
<Trk id="TRK-LAYOUT-page-container-md" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-1 block">size=md · 기본값 (p-5 space-y-4)</label>
|
|
<div className="border border-dashed border-slate-600/40 rounded">
|
|
<PageContainer size="md">
|
|
<div className="h-4 bg-blue-500/30 rounded" />
|
|
<div className="h-4 bg-blue-500/30 rounded" />
|
|
</PageContainer>
|
|
</div>
|
|
</Trk>
|
|
<Trk id="TRK-LAYOUT-page-container-lg" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-1 block">size=lg (p-6 space-y-4)</label>
|
|
<div className="border border-dashed border-slate-600/40 rounded">
|
|
<PageContainer size="lg">
|
|
<div className="h-4 bg-blue-500/30 rounded" />
|
|
<div className="h-4 bg-blue-500/30 rounded" />
|
|
</PageContainer>
|
|
</div>
|
|
</Trk>
|
|
</div>
|
|
|
|
<Trk id="TRK-LAYOUT-page-container-fullbleed" className="ds-sample mt-3">
|
|
<label className="text-[10px] text-hint font-mono mb-1 block">
|
|
fullBleed — 지도/풀화면 페이지 (padding 0, space-y 0)
|
|
</label>
|
|
<div className="border border-dashed border-slate-600/40 rounded h-16 relative">
|
|
<PageContainer fullBleed className="h-full">
|
|
<div className="h-full bg-blue-500/30 rounded flex items-center justify-center text-xs text-heading">
|
|
fullBleed: 가장자리까지 콘텐츠 (LiveMapView / VesselDetail 패턴)
|
|
</div>
|
|
</PageContainer>
|
|
</div>
|
|
</Trk>
|
|
|
|
{/* PageHeader */}
|
|
<h3 className="text-sm font-semibold text-heading mb-2 mt-6">PageHeader</h3>
|
|
<div className="space-y-3">
|
|
<Trk id="TRK-LAYOUT-page-header-simple" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-2 block">단순형 (title + description)</label>
|
|
<PageHeader title="대시보드" description="실시간 종합 상황판" />
|
|
</Trk>
|
|
|
|
<Trk id="TRK-LAYOUT-page-header-icon" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-2 block">아이콘 포함</label>
|
|
<PageHeader
|
|
icon={Shield}
|
|
iconColor="text-blue-400"
|
|
title="권한 관리"
|
|
description="사용자/역할/권한 설정"
|
|
/>
|
|
</Trk>
|
|
|
|
<Trk id="TRK-LAYOUT-page-header-demo" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-2 block">데모 배지</label>
|
|
<PageHeader
|
|
icon={BarChart3}
|
|
iconColor="text-purple-400"
|
|
title="AI 모델 관리"
|
|
description="ML 모델 배포 상태"
|
|
demo
|
|
/>
|
|
</Trk>
|
|
|
|
<Trk id="TRK-LAYOUT-page-header-actions" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-2 block">우측 액션 슬롯</label>
|
|
<PageHeader
|
|
title="보고서 관리"
|
|
description="단속 증거 보고서 목록"
|
|
actions={
|
|
<>
|
|
<Input size="sm" placeholder="검색..." className="w-40" />
|
|
<Button variant="secondary" size="sm" icon={<Search className="w-3.5 h-3.5" />}>
|
|
검색
|
|
</Button>
|
|
<Button variant="primary" size="sm" icon={<Plus className="w-3.5 h-3.5" />}>
|
|
새 보고서
|
|
</Button>
|
|
</>
|
|
}
|
|
/>
|
|
</Trk>
|
|
</div>
|
|
|
|
{/* Section */}
|
|
<h3 className="text-sm font-semibold text-heading mb-2 mt-6">Section (Card 단축)</h3>
|
|
<div className="ds-grid ds-grid-2">
|
|
<Trk id="TRK-LAYOUT-section-basic" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-2 block">기본 Section</label>
|
|
<Section title="해역별 위험도" icon={BarChart3} iconColor="text-orange-400">
|
|
<div className="space-y-1.5">
|
|
<div className="flex justify-between text-[11px]">
|
|
<span className="text-hint">동해</span>
|
|
<span className="text-label">23건</span>
|
|
</div>
|
|
<div className="flex justify-between text-[11px]">
|
|
<span className="text-hint">서해</span>
|
|
<span className="text-label">12건</span>
|
|
</div>
|
|
</div>
|
|
</Section>
|
|
</Trk>
|
|
|
|
<Trk id="TRK-LAYOUT-section-actions" className="ds-sample">
|
|
<label className="text-[10px] text-hint font-mono mb-2 block">우측 액션</label>
|
|
<Section
|
|
title="최근 이벤트"
|
|
icon={BarChart3}
|
|
actions={
|
|
<Button variant="ghost" size="sm">
|
|
전체 보기
|
|
</Button>
|
|
}
|
|
>
|
|
<div className="text-[11px] text-hint">이벤트 3건</div>
|
|
</Section>
|
|
</Trk>
|
|
</div>
|
|
|
|
{/* 전체 조합 예시 */}
|
|
<h3 className="text-sm font-semibold text-heading mb-2 mt-6">전체 조합 예시</h3>
|
|
<Trk id="TRK-LAYOUT-full-example" className="ds-sample">
|
|
<code className="ds-code">
|
|
{`import { PageContainer, PageHeader, Section } from '@shared/components/layout';
|
|
import { Button } from '@shared/components/ui/button';
|
|
import { Shield, Plus } from 'lucide-react';
|
|
|
|
export function AccessControlPage() {
|
|
return (
|
|
<PageContainer>
|
|
<PageHeader
|
|
icon={Shield}
|
|
iconColor="text-blue-400"
|
|
title="권한 관리"
|
|
description="사용자별 역할 및 권한 매핑"
|
|
actions={
|
|
<Button variant="primary" icon={<Plus className="w-4 h-4" />}>
|
|
역할 추가
|
|
</Button>
|
|
}
|
|
/>
|
|
<Section title="사용자 목록">
|
|
<DataTable ... />
|
|
</Section>
|
|
</PageContainer>
|
|
);
|
|
}`}
|
|
</code>
|
|
</Trk>
|
|
</>
|
|
);
|
|
}
|