# Aksel 디자인 시스템

## Aksel 디자인 시스템 인터페이스 미리보기

숫자로 된 대기 일수를 정렬하고, 항목을 선택하고, 밀도를 전환하며, 라이트 및 다크 테마의 색상 역할을 비교하세요.

## Aksel 디자인 시스템 디자인 참고 자료

@navikt/ds-css 8.18.0의 네이티브 스타일시트와 최신 v8 문서를 확인했습니다. 라이트 및 다크 값은 각각 범위가 지정되어 있습니다. 미리보기에서는 원격 글꼴 대신 Arial을 사용하고 원본 예제 레코드를 활용합니다.

### v8 타이포그래피

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --ax-font-family | Source Sans 3, Source Sans Pro, Arial, sans-serif | 미리보기에서 Arial 대체 글꼴을 명시적으로 사용합니다. |
| --ax-font-weight-regular / bold | 400 / 600 | 이름이 붙은 굵게 토큰을 700과 동일시하지 마세요. |
| --ax-font-size-medium / large | 1rem / 1.125rem | 기본 루트 크기에서 16px / 18px. |
| --ax-font-size-heading-xlarge / 2xlarge | 2rem / 2.5rem | 32px / 40px. |
### 간격 및 중단점

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --ax-space-8 / 16 / 24 / 32 | 0.5 / 1 / 1.5 / 2rem | 토큰 이름은 표준 픽셀 환산값을 나타냅니다. |
| --ax-radius-2 / 4 / 8 / 12 / 16 | 2 / 4 / 8 / 12 / 16px | 모서리 반경 역할. |
| sm / md / lg / xl / 2xl | 480 / 768 / 1024 / 1280 / 1440px | 버전이 명시된 CSS에서 확인한 값입니다. |
### 네이티브 테이블 크기

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| Medium cell padding | 12px 8px | 기본 세로 / 가로 패딩. |
| Small / large vertical padding | 4px / 16px | 네이티브 밀도 수정자이며 가로 패딩은 8px로 유지됩니다. |
| Header divider | 2px | 본문 행 구분선은 1px로 유지됩니다. |
### 테마 역할

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| --ax-bg-default | #fff light / #0e151f dark | 루트 표면. |
| --ax-text-neutral | #202733 light / #dfe1e5 dark | 계산된 neutral-1000 값. |
| --ax-bg-accent-strong | #2176d4 light / #4580ca dark | 계산된 accent-600 값입니다. 코드에서는 역할을 사용하세요. |
## Aksel 디자인 시스템 전체 가이드

실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.

완전한 안내와 구현 시작점, 소스 링크.

## Aksel 디자인 시스템: v8 계약을 기준으로 시작하기

### 이전 클래스와 새 토큰을 혼용하지 마세요

> Aksel v8은 --ax-* 토큰과 .aksel 컴포넌트 클래스를 사용합니다. 마이그레이션 가이드에 따르면 이전 .navds 클래스는 더 이상 작동하지 않으며 컴포넌트별 토큰도 제거되었습니다. 따라서 오래된 스크린샷을 바탕으로 만든 튜토리얼은 그럴듯해 보여도 구현 안내가 잘못되었을 수 있습니다.

이 페이지는 네이티브 CSS 버전을 8.18.0으로 고정하고 이에 맞는 React 설치 방법을 제공합니다. 미리보기는 일반 HTML와 함께 확인된 네이티브 테이블 클래스를 사용하며, 선택과 정렬은 애플리케이션의 JavaScript에서 처리합니다. 스타일시트를 다운로드하면 React Table이 생성된다고 주장하지 않습니다.

지원 사양 읽기

## Aksel 디자인 시스템: 타입 역할 및 글꼴 로드

### 굵게 토큰에는 600을 사용하세요

토큰 참조 문서에 따르면 글꼴 모음은 Source Sans 3, Source Sans Pro, Arial, sans-serif 순입니다. 보통 굵기는 400이며, 이름이 붙은 굵게 토큰은 600입니다. 본문 크기에는 14, 16, 18, 20px이 있고, 제목 역할은 24, 28, 32, 40px까지 제공됩니다.

로컬 미리보기는 글꼴 토큰을 Arial로 설정하고 상속된 글꼴 사용을 명시적으로 재정의하므로 원격 글꼴을 요청하지 않습니다. 이는 대체 글꼴을 사용한다는 점을 밝힌 것이며, Arial이 기본 Aksel 서체라고 주장하는 것이 아닙니다. 컴포넌트 텍스트 크기는 CSS에서 계속 제공합니다.

지원 사양 읽기

## Aksel 디자인 시스템: 간격, 모서리 반경 및 레이아웃

### 픽셀 단위 이름의 토큰은 rem으로 환산됩니다

--ax-space-16은 1rem이고 --ax-space-24는 1.5rem입니다. v8의 기본 문법은 이러한 이름을 따릅니다. padding="space-16" 및 gap={{xs:"space-8",md:"space-16"}}처럼 사용하세요. 마이그레이션 지침을 확인하지 않은 채 이전 숫자형 간격 prop으로 대체하지 마세요.

문서에 정의된 모서리 반경 역할에는 2, 4, 8, 12, 16px과 full이 포함됩니다. 미리보기에서는 네이티브 테이블 크기를 유지하고 애플리케이션 컨트롤 주변에 space-24를 사용합니다. 64rem의 콘텐츠 너비는 이 페이지에서 선택한 값이며, 중단점 값은 확인한 스타일시트에서 가져옵니다.

지원 사양 읽기

## Aksel 디자인 시스템: 테마에 대응하는 시맨틱 색상

### 특정 16진수 값이 아니라 역할을 유지하세요

네이티브 스타일시트에서 --ax-text-neutral은 neutral-1000으로 계산됩니다. 라이트 모드에서는 #202733, 다크 모드에서는 #dfe1e5입니다. --ax-bg-default는 흰색에서 #0e151f로 바뀝니다. 다크 컨테이너에서 라이트 모드의 텍스트 값을 하드코딩하면 역할 매핑이 무효화됩니다.

미리보기에서 .light/.dark 테마 클래스를 전환하면 테이블의 줄무늬, 테두리 및 선택된 행 색상이 공식 토큰을 따릅니다. 선택 상태에는 체크된 체크박스와 눈에 보이는 개수가 함께 표시됩니다. 행에 색상만 입히는 것은 선택 인터페이스가 아닙니다.

지원 사양 읽기

## Aksel 디자인 시스템: 시맨틱 테이블 구조

### 헤더는 일반 셀이 아닙니다

네이티브 테이블에는 헤더, 본문, 행, 헤더 셀 및 데이터 셀에 각각 별도의 클래스가 있습니다. React에서 이에 해당하는 요소는 Table.Header, Table.Body, Table.Row, Table.HeaderCell 및 Table.DataCell입니다. 참조 열은 행 헤더이며, 각 열 헤더에는 scope=col을 지정합니다.

캡션에 항목의 이름을 지정합니다. 대기 일수는 수량이므로 오른쪽 정렬하고, 참조 ID는 왼쪽 정렬합니다. 좁은 화면에서는 카드 형태의 행으로 바꿔 테이블의 관계를 훼손하는 대신, 레이블이 있고 키보드로 포커스할 수 있는 영역 안에서 가로 스크롤을 제공합니다.

- 열 레이블과 행 식별자 모두에 헤더 셀을 사용하세요.

- 우편번호나 식별자가 아니라 수량을 오른쪽 정렬하세요.

- 테이블에 의미 있는 이름을 제공하도록 캡션을 추가하세요.

지원 사양 읽기

## Aksel 디자인 시스템: 밀도 및 정렬

### 밀도를 변경하면 패딩이 바뀝니다

확인한 네이티브 CSS에서 중간 밀도 셀은 세로로 space-12, 가로로 space-8을 사용합니다. 작은 밀도는 세로로 space-4를, 큰 밀도는 세로로 space-16을 사용합니다. 밀도 선택기는 네이티브 수정자 클래스를 바꾸며, 뷰포트에 더 많은 정보를 넣기 위해 본문 글꼴 크기를 줄이지 않습니다.

Waiting days 헤더는 네이티브 스타일의 정렬 버튼입니다. 핸들러는 숫자 값을 정렬하고 해당 헤더의 aria-sort를 업데이트합니다. 이 변환은 애플리케이션이 담당합니다. React API도 마찬가지로 정렬 상태와 onSortChange를 제공하며, 임의의 도메인 레코드를 자동으로 정렬하지 않습니다.

지원 사양 읽기

## Aksel 디자인 시스템: 키보드로 안전하게 행 선택하기

### 각 행에 명시적인 컨트롤 제공

Table 문서에서는 onRowClick만으로는 키보드 접근성을 보장할 수 없다고 안내합니다. 따라서 예제에서는 각 레코드에 레이블이 지정된 체크박스를 제공하고, 전체 선택용 체크박스도 제공합니다. 일부 행만 선택된 경우 전체 선택 체크박스는 불확정 상태가 됩니다.

정렬해도 안정적인 레코드 식별자를 기준으로 선택 상태를 유지합니다. 순서가 바뀔 때 체크 표시가 다른 레코드로 옮겨 가지 않도록 현재 행 인덱스를 선택 키로 사용하지 않습니다. 선택 항목 수는 공손한 상태 알림 영역에 업데이트됩니다. 선택한 레코드는 어디에도 전송되지 않습니다.

지원 사양 읽기

## Aksel 디자인 시스템: 일치하는 CSS 및 React 불러오기

### 패키지 버전 일치시키기

@navikt/ds-react와 @navikt/ds-css를 같은 버전으로 설치한 다음, 애플리케이션 루트에 가까운 곳에서 CSS를 한 번 불러옵니다. 패키지에는 이미 토큰이 포함되어 있습니다. 공식 CSS 가져오기 가이드에서는 전역 파일과 컴포넌트 파일을 세분화해 불러오는 방법도 지원하지만, 기본 파일은 필수이며 글꼴과 토큰을 제공하거나 명시적으로 대체해야 합니다.

Aksel는 CSS 레이어를 사용합니다. 컴포넌트 스타일을 의도치 않게 덮어쓰는 광범위한 비레이어 선택자는 피하세요. 애플리케이션의 사용자 지정 레이아웃에는 자체 클래스를 사용하세요. 독립형 미리보기에는 로컬 버전 관리 CSS와 의도적으로 대체한 글꼴이 사용됩니다. React 예제는 별도의 소스 검증된 통합 경로입니다.

1. React와 CSS 패키지 버전을 함께 고정하세요.

2. 스타일시트를 한 번 불러오고 시맨틱 Table 하위 요소를 렌더링하세요.

3. 정렬과 선택 상태는 애플리케이션 상태로 관리하세요.

4. 테마 전환, 키보드 컨트롤, 좁은 스크롤 영역을 확인하세요.

지원 사양 읽기

## Aksel 디자인 시스템 컴포넌트 예제

### 시맨틱 React Table

실제 Table 하위 요소와 행 헤더를 사용하고, 수량은 오른쪽에 정렬합니다.

```
import { Table } from '@navikt/ds-react';
import '@navikt/ds-css';

export function CaseTable() {
  return <Table size="medium" zebraStripes>
    <caption>Fictional follow-up records</caption>
    <Table.Header><Table.Row>
      <Table.HeaderCell scope="col">Reference</Table.HeaderCell>
      <Table.HeaderCell scope="col">Next activity</Table.HeaderCell>
      <Table.HeaderCell scope="col" align="right">Waiting days</Table.HeaderCell>
    </Table.Row></Table.Header>
    <Table.Body><Table.Row>
      <Table.HeaderCell scope="row">DEMO-204</Table.HeaderCell>
      <Table.DataCell>Confirm appointment preference</Table.DataCell>
      <Table.DataCell align="right">4</Table.DataCell>
    </Table.Row></Table.Body>
  </Table>;
}
```

코드 참조

### 현재 프리미티브 구문

프리미티브 속성에는 v8 토큰 이름을 사용하세요.

```
import { HStack, Box } from '@navikt/ds-react';
<HStack gap={{ xs: 'space-8', md: 'space-16' }}>
  <Box padding="space-16">First region</Box>
  <Box padding="space-16">Second region</Box>
</HStack>
```

코드 참조

### 완전한 독립 실행형 예시

전체 문서에 레이아웃, 컨트롤 및 초기화가 포함되어 있습니다. 링크된 예시 아카이브의 압축을 풀면 정확한 상대 경로의 벤더 에셋을 얻을 수 있습니다. 그런 다음 HTTP로 제공하세요.

```
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Aksel table workbench</title><link rel="stylesheet" href="vendor/aksel-8.18.0/index.css"><style>:root{--ax-font-family:Arial,sans-serif}body,body *,body *:before,body *:after{font-family:Arial,sans-serif!important}body{background:var(--ax-bg-default);color:var(--ax-text-neutral);font-size:18px;line-height:1.5}main{max-width:64rem;padding:32px 24px;margin:auto}h1{font-size:32px;font-weight:600;line-height:1.25;margin:16px 0 24px}p{margin:16px 0}.toolbar{display:flex;gap:24px;flex-wrap:wrap;padding:24px;background:var(--ax-bg-sunken);margin:24px 0}select{font-size:16px;padding:8px;background:var(--ax-bg-input);color:var(--ax-text-neutral);border:1px solid var(--ax-border-neutral)}label{font-size:16px;display:flex;gap:8px;align-items:center}.scroll{overflow-x:auto}table{min-width:38rem}caption{text-align:left;font-weight:600;margin-bottom:16px}input[type=checkbox]{width:20px;height:20px;accent-color:var(--ax-bg-accent-strong);cursor:pointer}small{font-size:14px;display:block;margin-top:24px;color:var(--ax-text-neutral-subtle)}:focus-visible{outline:3px solid var(--ax-border-focus);outline-offset:3px}@media(max-width:767px){main{padding:24px 16px}.toolbar{padding:16px;gap:16px}h1{font-size:28px}}</style><body class="light"><main><p>AKSEL v8 · NATIVE TABLE CSS</p><h1>Follow-up record workbench</h1><p>Compare density and theme while sorting and selecting fictional records. Selection follows each reference when the rows move.</p><div class="toolbar"><label>Density <select id="density"><option value="medium">Medium</option><option value="small">Small</option><option value="large">Large</option></select></label><label>Theme <select id="theme"><option value="light">Light</option><option value="dark">Dark</option></select></label></div><p id="selection" role="status">0 records selected</p><div class="scroll" tabindex="0" role="region" aria-label="Fictional follow-up records, horizontally scrollable"><table class="aksel-table aksel-table--zebra-stripes" id="records"><caption>Fictional follow-up records</caption><thead class="aksel-table__header"><tr class="aksel-table__row"><th class="aksel-table__header-cell" scope="col"><input id="all" type="checkbox" aria-label="Select all records"></th><th class="aksel-table__header-cell" scope="col">Reference</th><th class="aksel-table__header-cell" scope="col">Next activity</th><th class="aksel-table__header-cell" id="sort-header" scope="col" aria-sort="ascending"><button id="sort" type="button" class="aksel-table__sort-button">Waiting days ↑</button></th></tr></thead><tbody class="aksel-table__body" id="rows"></tbody></table></div><small>OpenDesign specimen using native Aksel 8.18.0 CSS and an explicit Arial fallback. Fictional data, no NAV identity or external actions.</small></main><script>const data=[{id:'DEMO-204',activity:'Confirm appointment preference',days:4},{id:'DEMO-218',activity:'Read the submitted example note',days:12},{id:'DEMO-231',activity:'Arrange an example callback',days:7}];let ascending=true;const selected=new Set(),all=document.querySelector('#all');function render(){const body=document.querySelector('#rows');body.replaceChildren();for(const r of [...data].sort((a,b)=>ascending?a.days-b.days:b.days-a.days)){const tr=document.createElement('tr');tr.className='aksel-table__row'+(selected.has(r.id)?' aksel-table__row--selected':'');const td=document.createElement('td');td.className='aksel-table__data-cell';const c=document.createElement('input');c.type='checkbox';c.setAttribute('aria-label','Select '+r.id);c.checked=selected.has(r.id);c.onchange=()=>{c.checked?selected.add(r.id):selected.delete(r.id);updateSelection();tr.classList.toggle('aksel-table__row--selected',c.checked)};td.append(c);const th=document.createElement('th');th.scope='row';th.className='aksel-table__header-cell';th.textContent=r.id;const activity=document.createElement('td');activity.className='aksel-table__data-cell';activity.textContent=r.activity;const days=document.createElement('td');days.className='aksel-table__data-cell aksel-table__data-cell--align-right';days.textContent=r.days;tr.append(td,th,activity,days);body.append(tr)}updateSelection()}function updateSelection(){all.checked=selected.size===data.length;all.indeterminate=selected.size>0&&selected.size<data.length;document.querySelector('#selection').textContent=selected.size+' records selected'}all.onchange=()=>{selected.clear();if(all.checked)data.forEach(r=>selected.add(r.id));render()};document.querySelector('#sort').onclick=()=>{ascending=!ascending;document.querySelector('#sort-header').setAttribute('aria-sort',ascending?'ascending':'descending');document.querySelector('#sort').textContent='Waiting days '+(ascending?'↑':'↓');render()};document.querySelector('#density').onchange=e=>document.querySelector('table').className='aksel-table aksel-table--zebra-stripes aksel-table--'+e.target.value;document.querySelector('#theme').onchange=e=>document.body.className=e.target.value;render();</script></body></html>
```

코드 참조

- Sources에서 완전한 예시를 다운로드하세요. README에 정확한 로컬 실행 명령이 안내되어 있습니다.

- 벤더 경로는 이 문서에 대한 상대 경로로 유지하세요. 아카이브에는 이 미리보기에 사용된 에셋이 모두 포함되어 있습니다.

## Aksel 디자인 시스템 에이전트 설정

### 구현 시작점

미리보기에서는 네이티브 CSS 8.18.0을 로컬에서 렌더링합니다. React 구성은 소스로 검증했지만 별도로 빌드하지 않았습니다. 버전을 일치시키고 v7 navds 클래스와 v8 CSS를 함께 사용하지 마세요. Sources에 있는 전체 작업 예제 ZIP에는 미리보기에 필요한 정확한 의존성과 전체 문서도 포함되어 있습니다. 압축을 푼 디렉터리에서 python3 -m http.server 8080을 실행한 다음 http://localhost:8080/nav-aksel.html을 여세요. 모듈 기반 예제를 file://로 열지 마세요.

```
npm install @navikt/ds-react@8.18.0 @navikt/ds-css@8.18.0
# React entry:
# import "@navikt/ds-css";
# import { Table, HStack, Box } from "@navikt/ds-react";
```

### 프로젝트를 위한 프롬프트

```
일치하는 8.18.0 CSS/React 패키지를 사용해 시맨틱 Aksel v8 테이블을 만드세요. 캡션, 열 헤더, 레코드 행 헤더를 유지하세요. 실제 ax 토큰과 space-* 프리미티브 속성을 사용하세요. aria-sort를 사용하는 숫자 정렬, 안정적인 ID를 기반으로 한 체크박스 선택, 불확정 상태를 지원하는 전체 선택 기능을 제공하세요. 키보드 상호작용에 onRowClick만 의존하지 마세요. 밝은 테마와 어두운 테마의 역할 토큰을 지원하고, 좁은 화면에는 레이블이 있는 가로 스크롤 영역을 제공하세요.
```

## Aksel 디자인 시스템의 출처와 범위

NAV와 무관한 독립 예제 레코드입니다. 공개한 글꼴 대체 설정과 함께 네이티브 스타일시트를 사용합니다. 정렬, 선택, 레이아웃은 애플리케이션 동작이며 실제 혜택이나 사례 데이터는 표시하지 않습니다.

- Aksel 디자인 시스템 공식 컴포넌트, 프리미티브, 패턴 및 구현 시작점.

- 디자인 토큰 공식 토큰 참조.

- Aksel 소스 공식 소스 프로젝트 및 개발 이력.

- 완전한 작동 예시 다운로드 전체 HTML, 로컬 CSS/JavaScript 종속 항목, 제공된 라이선스와 정확한 실행 지침이 포함된 ZIP 파일입니다. 빌드 단계는 필요하지 않습니다.

## Aksel 디자인 시스템 관련 자료

### NHS 디자인 시스템

NHS.UK 타이포그래피와 반응형 간격, 그룹화된 라디오 선택지, 맥락에 맞는 세부 정보를 활용해 명확한 예약 선호도 선택 흐름을 구성하세요.

### NL 디자인 시스템

실제 기여자 구성 요소와 명시적인 테마를 조합해 공공 서비스 인터페이스를 구성하세요. 이 참고 자료에서는 Utrecht CSS를 사용해 토큰 매핑, 데이터 목록의 구성 요소, 동일한 편집 워크플로를 사용하는 두 가지 독자적인 테마를 보여 줍니다.

### NSW 디자인 시스템

독립적인 로컬 참고 자료 목록과 함께 NSW 디자인 토큰, Public Sans 타이포그래피, 키보드로 접근할 수 있는 네이티브 탭을 살펴보는 전체 워크숍 가이드입니다.


- [구현 레퍼런스](https://aksel.nav.no/komponenter/core/table)
- [출처](https://aksel.nav.no/grunnleggende/styling/design-tokens)
- [출처](https://aksel.nav.no/komponenter/core/table)
- [지원 사양 읽기](https://aksel.nav.no/grunnleggende/migreringsguider/versjon-8)
- [지원 사양 읽기](https://aksel.nav.no/grunnleggende/styling/design-tokens)
- [지원 사양 읽기](https://aksel.nav.no/grunnleggende/kode/komponent-api)
- [지원 사양 읽기](https://aksel.nav.no/komponenter/core/table)
- [지원 사양 읽기](https://aksel.nav.no/grunnleggende/kode/css-import)
- [코드 참조](https://aksel.nav.no/komponenter/core/table)
- [코드 참조](https://aksel.nav.no/grunnleggende/kode/komponent-api)
- [Aksel 디자인 시스템 공식 컴포넌트, 프리미티브, 패턴 및 구현 시작점.](https://aksel.nav.no/designsystemet)
- [디자인 토큰 공식 토큰 참조.](https://aksel.nav.no/grunnleggende/styling/design-tokens)
- [Aksel 소스 공식 소스 프로젝트 및 개발 이력.](https://github.com/navikt/aksel)
