298 lines
12 KiB
TypeScript
298 lines
12 KiB
TypeScript
// LayoutContent.tsx — WING-OPS Layout 카탈로그 (신한 UX 벤치마킹)
|
|
|
|
import type { DesignTheme } from './designTheme';
|
|
|
|
// ---------- Props ----------
|
|
|
|
interface LayoutContentProps {
|
|
theme: DesignTheme;
|
|
}
|
|
|
|
// ---------- 데이터 타입 ----------
|
|
|
|
interface WebResolution {
|
|
label: string;
|
|
gridLabel: string;
|
|
gutter: string;
|
|
margin: string;
|
|
}
|
|
|
|
const WEB_RESOLUTIONS: WebResolution[] = [
|
|
{ label: 'WEB - 1280', gridLabel: '12 Grid (1280)', gutter: '24px', margin: '24px (px-6)' },
|
|
{ label: 'WEB - 1440', gridLabel: '12 Grid (1440)', gutter: '24px', margin: '32px (px-8)' },
|
|
{ label: 'WEB - 1600', gridLabel: '12 Grid (1600)', gutter: '24px', margin: '32px (px-8)' },
|
|
{ label: 'WEB - 1920', gridLabel: '12 Grid (1920)', gutter: '24px', margin: '32px (px-8)' },
|
|
];
|
|
|
|
// ---------- 컴포넌트 ----------
|
|
|
|
export const LayoutContent = ({ theme }: LayoutContentProps) => {
|
|
const t = theme;
|
|
const isDark = t.mode === 'dark';
|
|
const previewBg = isDark ? '#1a1f30' : '#f1f5f9';
|
|
const innerBg = isDark ? '#0a0e1a' : '#ffffff';
|
|
const colCyan = 'rgba(6,182,212,0.18)';
|
|
const gutterCyan = 'rgba(6,182,212,0.45)';
|
|
const marginCyan = 'rgba(6,182,212,0.5)';
|
|
|
|
return (
|
|
<div className="pt-24 px-8 pb-16 flex flex-col gap-16 items-start justify-start max-w-[1440px]">
|
|
{/* ── 섹션 1: Layout grid ── */}
|
|
<div className="w-full flex flex-col gap-6">
|
|
<div className="flex flex-col gap-2">
|
|
<h2 className="font-sans text-2xl leading-8 font-bold" style={{ color: t.textPrimary }}>
|
|
Layout grid
|
|
</h2>
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
그리드 시스템은 columns, gutters, margins 세 가지 요소로 구성됩니다.
|
|
</p>
|
|
</div>
|
|
|
|
{/* 다이어그램 */}
|
|
<div
|
|
className="w-full rounded-lg p-6 flex flex-col gap-4"
|
|
style={{ backgroundColor: previewBg }}
|
|
>
|
|
{/* Gutters 어노테이션 상단 */}
|
|
<div className="flex items-center justify-center">
|
|
<span className="font-mono text-caption font-medium" style={{ color: t.textAccent }}>
|
|
⌐ Gutters ¬
|
|
</span>
|
|
</div>
|
|
|
|
{/* 그리드 시각화 */}
|
|
<div className="flex flex-row items-stretch gap-0" style={{ height: '120px' }}>
|
|
{/* Margin 좌 */}
|
|
<div className="w-10 rounded-l-sm shrink-0" style={{ backgroundColor: marginCyan }} />
|
|
{/* 내부 컬럼 4개 그룹 */}
|
|
<div className="flex-1 flex flex-row gap-1 px-1">
|
|
{[0, 1, 2, 3].map((g) => (
|
|
<div key={g} className="flex-1 rounded-sm" style={{ backgroundColor: colCyan }} />
|
|
))}
|
|
</div>
|
|
{/* Margin 우 */}
|
|
<div
|
|
className="w-10 rounded-r-sm shrink-0 flex flex-col items-end justify-between py-2 pr-2"
|
|
style={{ backgroundColor: marginCyan }}
|
|
/>
|
|
</div>
|
|
|
|
{/* 어노테이션 하단 레이블 */}
|
|
<div className="flex flex-row justify-between px-0">
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: marginCyan }} />
|
|
<span className="font-mono text-caption" style={{ color: t.textMuted }}>
|
|
Margin
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: colCyan }} />
|
|
<span className="font-mono text-caption" style={{ color: t.textMuted }}>
|
|
Columns
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<div
|
|
className="w-3 h-3 rounded-sm"
|
|
style={{ backgroundColor: isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)' }}
|
|
/>
|
|
<span className="font-mono text-caption" style={{ color: t.textMuted }}>
|
|
Gutters
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* ── 섹션 2: 컬럼 ── */}
|
|
<div className="w-full flex flex-col gap-8">
|
|
<div className="flex flex-col gap-2">
|
|
<h2 className="font-sans text-2xl leading-8 font-bold" style={{ color: t.textPrimary }}>
|
|
컬럼 (Column)
|
|
</h2>
|
|
<div className="flex flex-col gap-1">
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
컬럼 단위를 사용해 콘텐츠의 크기를 조정합니다.
|
|
</p>
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
콘텐츠 영역을 동일 너비의 균일한 컬럼으로 나눠 1개 이상의 컬럼을 조합해 콘텐츠의
|
|
크기를 결정합니다.
|
|
</p>
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
WING-OPS는 데스크톱 전용 앱으로 12컬럼 그리드를 사용하며, 거터는 24px(gap-6)입니다.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 해상도별 서브섹션 */}
|
|
<div className="flex flex-col gap-10">
|
|
{WEB_RESOLUTIONS.map((res) => (
|
|
<div key={res.label} className="w-full flex flex-col gap-4">
|
|
<div className="flex flex-col gap-1.5">
|
|
<h3
|
|
className="font-sans text-xl leading-7 font-bold"
|
|
style={{ color: t.textPrimary }}
|
|
>
|
|
{res.label}
|
|
</h3>
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
해상도 {res.label.replace('WEB - ', '')}은 12컬럼 {res.gutter}거터 사용을
|
|
권장합니다.
|
|
</p>
|
|
</div>
|
|
|
|
{/* 프리뷰 박스 */}
|
|
<div className="w-full rounded-lg p-4" style={{ backgroundColor: previewBg }}>
|
|
<span className="font-mono text-caption" style={{ color: t.textMuted }}>
|
|
{res.gridLabel}
|
|
</span>
|
|
<div
|
|
className="mt-3 rounded"
|
|
style={{
|
|
backgroundColor: innerBg,
|
|
padding: '12px',
|
|
height: '200px',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(12, 1fr)',
|
|
gap: '8px',
|
|
height: '100%',
|
|
}}
|
|
>
|
|
{Array.from({ length: 12 }).map((_, colIdx) => (
|
|
<div
|
|
key={colIdx}
|
|
className="rounded-sm flex flex-col gap-1 p-1"
|
|
style={{ backgroundColor: colCyan }}
|
|
>
|
|
{/* 이미지 영역 */}
|
|
<div
|
|
className="rounded-sm shrink-0"
|
|
style={{
|
|
backgroundColor: 'rgba(6,182,212,0.3)',
|
|
height: '48px',
|
|
}}
|
|
/>
|
|
{/* 텍스트 라인 3개 */}
|
|
<div
|
|
className="rounded-full"
|
|
style={{
|
|
height: '6px',
|
|
width: '80%',
|
|
backgroundColor: t.textMuted,
|
|
opacity: 0.3,
|
|
}}
|
|
/>
|
|
<div
|
|
className="rounded-full"
|
|
style={{
|
|
height: '6px',
|
|
width: '60%',
|
|
backgroundColor: t.textMuted,
|
|
opacity: 0.3,
|
|
}}
|
|
/>
|
|
<div
|
|
className="rounded-full"
|
|
style={{
|
|
height: '6px',
|
|
width: '40%',
|
|
backgroundColor: t.textMuted,
|
|
opacity: 0.3,
|
|
}}
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* ── 섹션 3: 거터 ── */}
|
|
<div className="w-full flex flex-col gap-6">
|
|
<div className="flex flex-col gap-2">
|
|
<h2 className="font-sans text-2xl leading-8 font-bold" style={{ color: t.textPrimary }}>
|
|
거터 (Gutters)
|
|
</h2>
|
|
<div className="flex flex-col gap-1">
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
거터는 컬럼간의 사이 공간으로 콘텐츠 간의 간격입니다. 거터의 너비는 고정값으로
|
|
정의됩니다.
|
|
</p>
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
상황에 따라 화면의 너비에 비례하는 거터값을 사용할 수 있습니다.
|
|
</p>
|
|
<p className="font-korean text-body-2 leading-5" style={{ color: t.textSecondary }}>
|
|
거터값은 4의 배수를 기본으로 합니다. WING-OPS 기본 거터: 24px (gap-6)
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 거터 다이어그램 */}
|
|
<div
|
|
className="w-full rounded-lg p-6 flex flex-col gap-3"
|
|
style={{ backgroundColor: previewBg }}
|
|
>
|
|
{/* Gutters 어노테이션 */}
|
|
<div className="flex items-center justify-center">
|
|
<span className="font-mono text-caption font-medium" style={{ color: t.textAccent }}>
|
|
[ Gutters ]
|
|
</span>
|
|
</div>
|
|
|
|
{/* 3컬럼 거터 하이라이트 */}
|
|
<div
|
|
className="w-full rounded"
|
|
style={{ backgroundColor: innerBg, padding: '16px', height: '160px' }}
|
|
>
|
|
<div
|
|
style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
gap: '0',
|
|
height: '100%',
|
|
}}
|
|
>
|
|
{[0, 1, 2].map((colIdx) => (
|
|
<div key={colIdx} className="flex flex-row" style={{ height: '100%' }}>
|
|
{/* 컬럼 본체 */}
|
|
<div
|
|
className="flex-1 rounded-sm"
|
|
style={{
|
|
backgroundColor: isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)',
|
|
}}
|
|
/>
|
|
{/* 거터 (마지막 컬럼 제외) */}
|
|
{colIdx < 2 && (
|
|
<div
|
|
style={{
|
|
width: '24px',
|
|
backgroundColor: gutterCyan,
|
|
flexShrink: 0,
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 거터 레이블 */}
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: gutterCyan }} />
|
|
<span className="font-mono text-caption" style={{ color: t.textMuted }}>
|
|
Gutter — 24px (gap-6)
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|