4px 스케일과 시맨틱 토큰을 정리한 간격 시스템 문서
콘텐츠 블록2~48px 프리미티브 간격을 막대 길이로 보여 주는 표, 컴포넌트·레이아웃·인라인 갭 시맨틱 토큰 카드 3개, 사용 가이드라인 카드 3개로 구성된 디자인 시스템 간격 문서 섹션입니다.
Claude Code · 모름 · React (TSX)
결과 코드펼치기
const FONT_URL = "https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&display=swap";
const PRIMITIVES = [2, 4, 6, 8, 12, 16, 20, 24, 32, 40, 48];
const MAX = 48;
const SEMANTIC = [
{
title: "컴포넌트 (Component)",
desc: "버튼, 인풋, 카드 등 UI 내부 패딩·갭",
color: "#6366f1",
soft: "#efeffc",
rows: [
["spacing/component-xs", 4],
["spacing/component-sm", 8],
["spacing/component-md", 16],
["spacing/component-lg", 24],
],
},
{
title: "레이아웃 (Layout)",
desc: "섹션·페이지 단위의 여백과 간격",
color: "#229868",
soft: "#e6f5ee",
rows: [
["spacing/layout-xs", 16],
["spacing/layout-sm", 24],
["spacing/layout-md", 32],
["spacing/layout-lg", 48],
],
},
{
title: "인라인 갭 (Gap)",
desc: "아이콘·태그 사이, 리스트 아이템 간격",
color: "#bd630e",
soft: "#fcf2e9",
rows: [
["spacing/gap-xs", 4],
["spacing/gap-sm", 8],
["spacing/gap-md", 12],
["spacing/gap-lg", 20],
],
},
] as const;
const GUIDES = [
{ title: "4px 그리드 원칙", body: "모든 간격은 4의 배수를 사용합니다. 2px(spacing/2)는 보더·구분선 등 미세 조정에만 허용합니다." },
{
title: "Semantic 우선 사용",
body: "컴포넌트 구현 시 spacing/N 프리미티브 대신 spacing/component-*, spacing/layout-*, spacing/gap-* 시맨틱 토큰을 사용하세요.",
},
{ title: "일관된 리듬 유지", body: "동일 계층의 요소들은 같은 간격 토큰을 공유하여 시각적 리듬과 정렬을 유지합니다." },
];
function SectionTitle({ title, desc }: { title: string; desc: string }) {
return (
<div className="flex flex-col gap-2.5">
<div className="flex items-center gap-3">
<span className="h-6 w-1 shrink-0 rounded-[2px] bg-[#6366f1]" aria-hidden="true" />
<h3 className="text-[18px] font-bold leading-normal text-[#111827] sm:text-[20px]">{title}</h3>
</div>
<p className="text-[14px] leading-normal text-[#6b7280]">{desc}</p>
</div>
);
}
export default function SpacingSystemDoc() {
return (
<section className="w-full bg-white px-4 py-12 font-['Geist',sans-serif] sm:px-10 sm:py-20 lg:px-20">
<link rel="stylesheet" href={FONT_URL} precedence="default" />
<div className="mx-auto flex w-full max-w-[1280px] flex-col gap-12">
<h2 className="border-b border-[#eceef1] pb-5 text-[24px] font-bold leading-normal text-[#111827] sm:text-[28px]">06 · SPACING SYSTEM</h2>
<div className="flex flex-col gap-6">
<SectionTitle title="프리미티브 스케일 (Primitive Scale)" desc="4px 기반 스케일 — 모든 간격은 이 값을 기초로 합니다." />
<div className="flex flex-col">
<div className="grid grid-cols-[88px_64px_1fr] items-center gap-3 border-b border-[#eceef1] pb-2 text-[11px] font-medium leading-normal text-[#a5a9b2] sm:grid-cols-[208px_100px_1fr]">
<span>TOKEN</span>
<span>VALUE</span>
<span>VISUAL SCALE</span>
</div>
<ul className="mt-2 flex flex-col">
{PRIMITIVES.map((v, i) => (
<li
key={v}
className={`-mx-2 grid h-[46px] grid-cols-[88px_64px_1fr] items-center gap-3 rounded px-2 sm:grid-cols-[208px_100px_1fr] ${i % 2 === 0 ? "bg-[#f9fafc]" : ""}`}
>
<span className="text-[13px] font-medium leading-normal text-[#111827]">spacing/{v}</span>
<span className="w-[58px] rounded bg-[#efeffc] px-2 py-1 text-[12px] font-medium leading-normal text-[#6366f1]">{v}px</span>
<span className="flex min-w-0 items-center gap-2">
<span
className="h-3 rounded-[3px] bg-[#6366f1] transition-[width] duration-500 ease-out"
style={{ width: `${(v / MAX) * 100}%`, maxWidth: "calc(100% - 28px)", opacity: 0.35 + (0.65 * i) / (PRIMITIVES.length - 1) }}
/>
<span className="text-[11px] leading-normal text-[#a5a9b2]">{v}</span>
</span>
</li>
))}
</ul>
</div>
</div>
<div className="flex flex-col gap-6 pt-6">
<SectionTitle title="시맨틱 토큰 (Semantic Tokens)" desc="목적에 따라 분류된 간격 토큰 — 실제 컴포넌트·레이아웃 개발 시 이 토큰을 사용하세요." />
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 lg:gap-10">
{SEMANTIC.map((g) => (
<div key={g.title} className="overflow-hidden rounded-lg border border-[#eceef1] bg-white">
<div className="h-[3px] w-full" style={{ background: g.color }} />
<div className="flex flex-col gap-1.5 px-5 pb-4 pt-4">
<p className="text-[14px] font-bold leading-normal text-[#111827]">{g.title}</p>
<p className="text-[12px] leading-normal text-[#6b7280]">{g.desc}</p>
</div>
<div className="grid grid-cols-[1fr_auto_auto] gap-3 border-b border-[#eceef1] px-5 pb-2 text-[10px] font-medium leading-normal text-[#a5a9b2]">
<span>SEMANTIC</span>
<span className="w-[92px]">PRIMITIVE</span>
<span className="w-10 text-center">PX</span>
</div>
<ul className="flex flex-col gap-5 px-5 py-5">
{g.rows.map(([name, px]) => (
<li key={name} className="flex flex-col gap-1.5">
<div className="grid grid-cols-[1fr_auto_auto] items-center gap-3">
<span className="truncate text-[12px] font-medium leading-normal text-[#111827]">{name}</span>
<span className="flex w-[92px] items-center gap-1.5 text-[11px] leading-normal">
<span className="text-[#a5a9b2]" aria-hidden="true">
→
</span>
<span className="text-[#6b7280]">spacing/{px}</span>
</span>
<span className="w-10 rounded py-0.5 text-center text-[11px] font-medium leading-normal" style={{ background: g.soft, color: g.color }}>
{px}px
</span>
</div>
<span className="h-1 rounded-[2px] opacity-55" style={{ width: (px / 24) * 70, background: g.color }} aria-hidden="true" />
</li>
))}
</ul>
</div>
))}
</div>
</div>
<div className="flex flex-col gap-6 pt-6">
<div className="flex items-center gap-3">
<span className="h-6 w-1 shrink-0 rounded-[2px] bg-[#6366f1]" aria-hidden="true" />
<h3 className="text-[18px] font-bold leading-normal text-[#111827] sm:text-[20px]">사용 가이드라인 (Usage Guidelines)</h3>
</div>
<div className="grid grid-cols-1 gap-6 md:grid-cols-3 lg:gap-10">
{GUIDES.map((g) => (
<div key={g.title} className="flex min-h-[120px] flex-col gap-2.5 rounded-lg border border-[#eceef1] border-l-4 border-l-[#6366f1] bg-[#f9fafc] p-5">
<p className="text-[13px] font-bold leading-normal text-[#111827]">{g.title}</p>
<p className="text-[12px] leading-[1.6] text-[#6b7280]">{g.body}</p>
</div>
))}
</div>
</div>
<p className="whitespace-pre border-t border-[#eceef1] pt-4 text-[12px] leading-normal text-[#a5a9b2]">{"Design System · Spacing System · v1.0"}</p>
</div>
</section>
);
}
적용 사이트 0
이 블록이 실제로 쓰인 사이트입니다.
아직 등록된 사이트가 없습니다. 이 블록을 쓴 사이트가 있다면 알려 주세요.
재현 후기
v1 · 0개아직 이 버전의 프롬프트로 직접 만들어 본 사람이 없습니다. 첫 번째로 재현해 보세요.