- react-router-dom 도입, /design 경로에 디자인 토큰/컴포넌트 카탈로그 페이지 추가 - SCAT 지도에서 하드코딩된 제주 해안선 좌표 제거, 인접 구간 기반 동적 방향 계산으로 전환 - @/ path alias 추가, SVG 아이콘 에셋 추가
280 lines
9.8 KiB
TypeScript
280 lines
9.8 KiB
TypeScript
// RadiusContent.tsx — WING-OPS Radius 콘텐츠 (다크/라이트 테마 지원)
|
|
|
|
import type { DesignTheme } from './designTheme';
|
|
|
|
// ---------- 데이터 타입 ----------
|
|
|
|
interface RadiusToken {
|
|
name: string;
|
|
value: string;
|
|
px: number;
|
|
isCustom?: boolean;
|
|
}
|
|
|
|
interface ComponentRadius {
|
|
className: string;
|
|
radius: string;
|
|
components: string[];
|
|
}
|
|
|
|
// ---------- Radius Token 데이터 ----------
|
|
|
|
const RADIUS_TOKENS: RadiusToken[] = [
|
|
{ name: 'rounded-sm', value: '6px', px: 6, isCustom: true },
|
|
{ name: 'rounded', value: '4px (0.25rem)', px: 4 },
|
|
{ name: 'rounded-md', value: '10px', px: 10, isCustom: true },
|
|
{ name: 'rounded-lg', value: '8px (0.5rem)', px: 8 },
|
|
{ name: 'rounded-xl', value: '12px (0.75rem)', px: 12 },
|
|
{ name: 'rounded-2xl', value: '16px (1rem)', px: 16 },
|
|
{ name: 'rounded-full', value: '9999px', px: 9999 },
|
|
];
|
|
|
|
// ---------- 컴포넌트 매핑 데이터 ----------
|
|
|
|
const COMPONENT_RADIUS: ComponentRadius[] = [
|
|
{ className: 'rounded-sm (6px)', radius: '6px', components: ['.wing-btn', '.wing-input', '.wing-card-sm'] },
|
|
{ className: 'rounded (4px)', radius: '4px', components: ['.wing-badge'] },
|
|
{ className: 'rounded-md (10px)', radius: '10px', components: ['.wing-card', '.wing-section', '.wing-tab'] },
|
|
{ className: 'rounded-lg (8px)', radius: '8px', components: ['.wing-tab-bar'] },
|
|
{ className: 'rounded-xl (12px)', radius: '12px', components: ['.wing-modal'] },
|
|
];
|
|
|
|
// ---------- Props ----------
|
|
|
|
interface RadiusContentProps {
|
|
theme: DesignTheme;
|
|
}
|
|
|
|
// ---------- 컴포넌트 ----------
|
|
|
|
export const RadiusContent = ({ theme }: RadiusContentProps) => {
|
|
const t = theme;
|
|
const isDark = t.mode === 'dark';
|
|
|
|
return (
|
|
<div className="pt-24 px-8 pb-16 flex flex-col gap-16 items-start justify-start max-w-[1440px]">
|
|
|
|
{/* ── 섹션 1: 헤더 ── */}
|
|
<div
|
|
className="w-full border-b border-solid pb-8 flex flex-col gap-4"
|
|
style={{ borderColor: isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0' }}
|
|
>
|
|
<div className="flex flex-col gap-2">
|
|
<h1
|
|
className="font-sans text-3xl leading-9 font-bold"
|
|
style={{ color: t.textPrimary }}
|
|
>
|
|
Radius
|
|
</h1>
|
|
<p
|
|
className="font-korean text-sm leading-5"
|
|
style={{ color: t.textSecondary }}
|
|
>
|
|
Radius는 컴포넌트 혹은 콘텐츠 모서리의 둥글기를 표현합니다.
|
|
</p>
|
|
</div>
|
|
<p
|
|
className="font-korean text-sm leading-6"
|
|
style={{ color: t.textSecondary }}
|
|
>
|
|
Radius는 UI 구성 요소의 모서리를 둥글게 처리하여 부드럽고 현대적인 느낌을 제공합니다. 일관된 Radius 값은 브랜드 아이덴티티를 강화하고, 사용자 경험을 향상시키며, 다양한 화면과 컨텍스트에서 시각적 일관성을 유지하는 데 중요한 역할을 합니다.
|
|
</p>
|
|
<ul
|
|
className="flex flex-col gap-1 list-disc list-inside font-korean text-sm"
|
|
style={{ color: t.textSecondary }}
|
|
>
|
|
<li>
|
|
<code style={{ color: t.textAccent, fontSize: '12px' }}>rounded-sm</code>(6px)과{' '}
|
|
<code style={{ color: t.textAccent, fontSize: '12px' }}>rounded-md</code>(10px)는 Tailwind 기본값을 오버라이드한 프로젝트 커스텀 값입니다.
|
|
</li>
|
|
<li>나머지 토큰은 Tailwind CSS 기본 border-radius 스케일을 따릅니다.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
{/* ── 섹션 2: Radius Tokens 테이블 ── */}
|
|
<div className="w-full flex flex-col gap-8">
|
|
<h2
|
|
className="font-sans text-2xl leading-8 font-bold"
|
|
style={{ color: t.textPrimary }}
|
|
>
|
|
Radius Tokens
|
|
</h2>
|
|
|
|
<div
|
|
className="rounded-lg border border-solid overflow-hidden w-full"
|
|
style={{
|
|
backgroundColor: t.tableContainerBg,
|
|
borderColor: t.cardBorder,
|
|
boxShadow: t.cardShadow,
|
|
}}
|
|
>
|
|
{/* 헤더 */}
|
|
<div
|
|
className="grid"
|
|
style={{
|
|
gridTemplateColumns: '200px 200px 1fr',
|
|
backgroundColor: t.tableHeaderBg,
|
|
borderBottom: `1px solid ${t.tableRowBorder}`,
|
|
}}
|
|
>
|
|
{(['이름', '값', 'Preview'] as const).map((col) => (
|
|
<div key={col} className="py-3 px-4">
|
|
<span
|
|
className="font-mono text-[10px] font-medium uppercase"
|
|
style={{ letterSpacing: '1px', color: t.textMuted }}
|
|
>
|
|
{col}
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* 데이터 행 */}
|
|
{RADIUS_TOKENS.map((token, rowIdx) => (
|
|
<div
|
|
key={token.name}
|
|
className="grid items-center"
|
|
style={{
|
|
gridTemplateColumns: '200px 200px 1fr',
|
|
borderTop: rowIdx === 0 ? 'none' : `1px solid ${t.tableRowBorder}`,
|
|
}}
|
|
>
|
|
{/* 이름 */}
|
|
<div className="py-4 px-4 flex items-center gap-2">
|
|
<span
|
|
className="font-mono rounded border border-solid px-2 py-0.5"
|
|
style={{
|
|
fontSize: '11px',
|
|
lineHeight: '17px',
|
|
color: t.textAccent,
|
|
backgroundColor: t.cardBg,
|
|
borderColor: t.cardBorder,
|
|
}}
|
|
>
|
|
{token.name}
|
|
</span>
|
|
{token.isCustom && (
|
|
<span
|
|
className="font-mono text-[9px] rounded px-1.5 py-0.5"
|
|
style={{
|
|
color: isDark ? '#f97316' : '#c2410c',
|
|
backgroundColor: isDark ? 'rgba(249,115,22,0.10)' : 'rgba(249,115,22,0.08)',
|
|
}}
|
|
>
|
|
custom
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{/* 값 */}
|
|
<div className="py-4 px-4">
|
|
<span
|
|
className="font-mono text-[11px]"
|
|
style={{ color: t.textPrimary }}
|
|
>
|
|
{token.value}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Preview */}
|
|
<div className="py-4 px-4 flex items-center gap-4">
|
|
<div
|
|
style={{
|
|
width: '80px',
|
|
height: '48px',
|
|
borderRadius: token.px >= 9999 ? '9999px' : `${token.px}px`,
|
|
backgroundColor: isDark ? 'rgba(6,182,212,0.15)' : 'rgba(6,182,212,0.12)',
|
|
border: `1.5px solid ${isDark ? 'rgba(6,182,212,0.40)' : 'rgba(6,182,212,0.50)'}`,
|
|
}}
|
|
/>
|
|
<div
|
|
style={{
|
|
width: '48px',
|
|
height: '48px',
|
|
borderRadius: token.px >= 9999 ? '9999px' : `${token.px}px`,
|
|
backgroundColor: isDark ? 'rgba(6,182,212,0.15)' : 'rgba(6,182,212,0.12)',
|
|
border: `1.5px solid ${isDark ? 'rgba(6,182,212,0.40)' : 'rgba(6,182,212,0.50)'}`,
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* ── 섹션 3: 컴포넌트 매핑 ── */}
|
|
<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 }}
|
|
>
|
|
컴포넌트 매핑
|
|
</h2>
|
|
<p
|
|
className="font-korean text-sm leading-5"
|
|
style={{ color: t.textSecondary }}
|
|
>
|
|
wing.css 컴포넌트 클래스에 적용된 Radius 토큰입니다.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-4" style={{ maxWidth: '800px' }}>
|
|
{COMPONENT_RADIUS.map((item) => (
|
|
<div
|
|
key={item.className}
|
|
className="rounded-lg border border-solid px-5 py-4 flex flex-row items-center gap-6"
|
|
style={{
|
|
backgroundColor: t.cardBg,
|
|
borderColor: t.cardBorder,
|
|
boxShadow: t.cardShadow,
|
|
}}
|
|
>
|
|
{/* 미리보기 박스 */}
|
|
<div
|
|
className="shrink-0"
|
|
style={{
|
|
width: '48px',
|
|
height: '48px',
|
|
borderRadius: item.radius,
|
|
backgroundColor: isDark ? 'rgba(6,182,212,0.12)' : 'rgba(6,182,212,0.10)',
|
|
border: `1.5px solid ${isDark ? 'rgba(6,182,212,0.30)' : 'rgba(6,182,212,0.40)'}`,
|
|
}}
|
|
/>
|
|
|
|
{/* 정보 */}
|
|
<div className="flex flex-col gap-1.5 flex-1">
|
|
<span
|
|
className="font-mono text-xs font-bold"
|
|
style={{ color: t.textPrimary }}
|
|
>
|
|
{item.className}
|
|
</span>
|
|
<div className="flex flex-row flex-wrap gap-2">
|
|
{item.components.map((comp) => (
|
|
<span
|
|
key={comp}
|
|
className="font-mono rounded border border-solid px-2 py-0.5"
|
|
style={{
|
|
fontSize: '10px',
|
|
lineHeight: '15px',
|
|
color: t.textAccent,
|
|
backgroundColor: t.cardBg,
|
|
borderColor: t.cardBorder,
|
|
}}
|
|
>
|
|
{comp}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default RadiusContent;
|