Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion design-system/base.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
:root {
--font-ui: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
--font-ui: 'Atkinson Hyperlegible', Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', sans-serif;
--color-bg: #ffffff;
--color-text: #162033;
Expand Down
96 changes: 90 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,59 @@
name="description"
content="popover, details, commandfor, dialog 등 native HTML만으로 구성하는 UI kit"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet" />
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='12' fill='%23ffffff'/%3E%3Cpath d='M16 18h32v10H16zM16 36h20v10H16z' fill='%23162033'/%3E%3C/svg%3E" />
<title>Native HTML UI Kit</title>
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<a class="skip-link" href="#menus">컴포넌트 예제로 건너뛰기</a>
<header class="site-header">
<a class="brand" href="#top">Native HTML UI Kit</a>
<nav aria-label="컴포넌트">
<a href="#menus">Menus</a>
<a href="#forms">Forms</a>
<a href="#selectors">Selectors</a>
<a href="#dialogs">Dialogs</a>
</nav>
<div class="header-actions">
<nav aria-label="컴포넌트">
<a href="#menus">Menus</a>
<a href="#forms">Forms</a>
<a href="#selectors">Selectors</a>
<a href="#dialogs">Dialogs</a>
</nav>
<button class="header-command" commandfor="component-finder" command="show-modal">빠른 참조</button>
</div>
</header>

<dialog id="component-finder" class="command-dialog" aria-labelledby="component-finder-title">
<div class="command-dialog-content">
<div class="command-dialog-heading">
<div>
<p class="eyebrow">native command</p>
<h2 id="component-finder-title">컴포넌트 빠른 참조</h2>
</div>
<form class="command-dialog-dismiss" method="dialog">
<button class="dialog-close" value="close" aria-label="빠른 참조 닫기">닫기</button>
</form>
</div>
<label for="component-finder-input">
예제 이름 찾기
<input id="component-finder-input" type="search" list="quick-component-options" placeholder="예: dialog" />
</label>
<datalist id="quick-component-options">
<option value="Popover">메뉴와 도움말</option>
<option value="Form validation">입력 오류와 성공 상태</option>
<option value="Selectors">radio, checkbox, picker</option>
<option value="Dialog">commandfor와 modal</option>
</datalist>
<p class="field-hint">입력창은 브라우저 datalist 제안을 사용합니다. 상단 탐색 메뉴로 해당 예제를 확인할 수 있습니다.</p>
<ul class="command-links" aria-label="빠른 참조 항목">
<li><span>01</span> Popover와 메뉴</li>
<li><span>02</span> 입력 검증</li>
<li><span>03</span> 선택 컨트롤</li>
<li><span>04</span> Dialog와 accordion</li>
</ul>
</div>
</dialog>

<main id="top">
<section class="hero">
<h1>브라우저가 이미 가진 UI 계약을 다시 씁니다.</h1>
Expand All @@ -31,6 +69,52 @@ <h1>브라우저가 이미 가진 UI 계약을 다시 씁니다.</h1>
</p>
</section>

<section id="interaction-map" class="component-grid" aria-labelledby="interaction-map-title">
<div class="section-copy">
<p class="eyebrow">keyboard map</p>
<h2 id="interaction-map-title">브라우저가 넘겨주는 상호작용</h2>
<p>각 예제가 제공하는 초점 이동과 닫기 동작을 같은 밀도로 비교합니다.</p>
</div>
<article class="component-card matrix-card">
<table class="interaction-matrix">
<caption>주요 native UI 동작</caption>
<thead>
<tr>
<th scope="col">요소</th>
<th scope="col">키보드</th>
<th scope="col">확인할 상태</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">popover</th>
<td><kbd>Esc</kbd></td>
<td>열린 패널 닫기</td>
</tr>
<tr>
<th scope="row">details</th>
<td><kbd>Enter</kbd></td>
<td>요약 열기와 닫기</td>
</tr>
<tr>
<th scope="row">form</th>
<td><kbd>Tab</kbd></td>
<td>label과 오류 메시지</td>
</tr>
<tr>
<th scope="row">dialog</th>
<td><kbd>Esc</kbd></td>
<td>modal 닫기와 초점 복귀</td>
</tr>
</tbody>
</table>
<details class="matrix-note">
<summary>검토할 때 확인할 순서</summary>
<p>마우스 없이 Tab으로 진입하고, Enter와 Esc로 열고 닫은 뒤, 현재 위치를 보여주는 focus ring이 유지되는지 확인합니다.</p>
</details>
</article>
</section>

<section id="menus" class="component-grid" aria-labelledby="menus-title">
<div class="section-copy">
<h2 id="menus-title">Menus & Popovers</h2>
Expand Down
192 changes: 192 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@
select {
font: inherit;
}

.skip-link {
position: fixed;
top: 12px;
left: 12px;
z-index: 20;
transform: translateY(-160%);
border-radius: 6px;
padding: 10px 12px;
color: var(--color-primary-ink);
background: var(--color-primary);
font-size: 14px;
font-weight: 800;
transition: transform var(--motion-standard);
}

.skip-link:focus {
transform: translateY(0);
}
}

@layer layout {
Expand All @@ -65,6 +84,14 @@
font-weight: 900;
}

.header-actions {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-end;
gap: 14px;
}

nav {
display: flex;
align-items: center;
Expand Down Expand Up @@ -158,6 +185,96 @@
box-shadow: 0 10px 24px rgb(15 23 42 / 12%);
}

.header-command,
.dialog-close {
min-height: 34px;
border: 1px solid var(--color-border-strong);
border-radius: 6px;
padding: 0 12px;
color: var(--color-text);
background: var(--color-surface);
box-shadow: none;
font-size: 13px;
font-weight: 800;
}

.header-command:hover,
.dialog-close:hover {
color: var(--color-primary-ink);
background: var(--color-primary);
}

.command-dialog {
width: min(560px, calc(100vw - 32px));
border: 1px solid var(--color-border);
border-radius: var(--radius-frame);
padding: clamp(20px, 4vw, 30px);
background: var(--color-surface);
box-shadow: var(--shadow-popover);
}

.command-dialog::backdrop {
background: rgb(15 23 42 / 42%);
backdrop-filter: blur(3px);
}

.command-dialog-content {
display: grid;
gap: 18px;
}

.command-dialog-dismiss {
margin: 0;
}

.command-dialog-heading {
display: flex;
align-items: start;
justify-content: space-between;
gap: 18px;
}

.command-dialog-heading h2 {
margin: 0;
}

.command-dialog .eyebrow {
margin: 0 0 6px;
color: var(--color-focus);
font-size: 11px;
font-weight: 900;
text-transform: uppercase;
}

.command-links {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
margin: 0;
padding: 0;
color: var(--color-text);
}

.command-links li {
display: grid;
grid-template-columns: 28px minmax(0, 1fr);
gap: 8px;
align-items: center;
min-height: 48px;
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 8px 10px;
font-size: 13px;
font-weight: 800;
list-style: none;
}

.command-links span {
color: var(--color-focus);
font-size: 11px;
font-variant-numeric: tabular-nums;
}

.menu {
width: 220px;
border: 1px solid var(--color-border);
Expand Down Expand Up @@ -209,6 +326,70 @@
gap: 14px;
}

.matrix-card {
display: grid;
gap: 16px;
}

.interaction-matrix {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}

.interaction-matrix caption {
margin-bottom: 10px;
color: var(--color-text);
text-align: left;
font-size: 16px;
font-weight: 900;
}

.interaction-matrix th,
.interaction-matrix td {
border-bottom: 1px solid var(--color-border);
padding: 11px 8px;
text-align: left;
vertical-align: middle;
}

.interaction-matrix thead th {
color: var(--color-muted);
font-size: 11px;
}

.interaction-matrix tbody th {
color: var(--color-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
}

kbd {
display: inline-grid;
min-width: 28px;
place-items: center;
border: 1px solid var(--color-border-strong);
border-bottom-width: 2px;
border-radius: 4px;
padding: 2px 5px;
color: var(--color-text);
background: var(--color-surface-muted);
font-family: var(--font-ui);
font-size: 11px;
font-weight: 800;
}

.matrix-note {
background: var(--color-surface-muted);
}

.matrix-note p {
margin: 10px 0 0;
color: var(--color-muted);
font-size: 14px;
line-height: 1.6;
}

.form-card button {
justify-self: start;
}
Expand Down Expand Up @@ -420,6 +601,13 @@
gap: 12px;
}

.header-actions {
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
gap: 10px;
}

nav {
width: 100%;
gap: 8px 14px;
Expand All @@ -443,4 +631,8 @@
.picker-grid {
grid-template-columns: 1fr;
}

.command-links {
grid-template-columns: 1fr;
}
}
Loading