이 예시는 nsw-design-system 3.27.0을 실행합니다. 마크업을 만든 다음 패키지 CSS와 Tabs 클래스를 가져오고, 단일 탭 그룹을 초기화합니다. 이렇게 필요한 부분만 초기화하면 사용하지 않는 컴포넌트가 등록되지 않습니다. 라이브 문서에서는 더 최신 버전을 안내할 수 있지만, 여기서 다운로드할 수 있는 코드와 토큰 값은 검증된 패키지 버전을 기준으로 합니다.
컴포넌트와 애플리케이션 상태 분리
기본 Tabs 클래스가 탭 선택, 패널 표시 여부, 키보드 탐색을 관리합니다. 애플리케이션은 저장된 프롬프트를 Set에 보관합니다. 따라서 단계 사이를 이동해도 읽기 목록은 그대로 유지됩니다. 소스 코드에서 이러한 역할 분담을 명확히 확인할 수 있습니다. 숨겨진 전역 저장소나 백엔드 요청, 정부 계정을 흉내 내는 기능은 없습니다.
NSW 디자인 시스템 브랜드 역할과 가독성 높은 표면
어두운 역할과 밝은 역할을 함께 사용하세요
기본 어두운 브랜드 색상은 #002664이고, 밝은 표면 색상은 #CBEDFD입니다. 프롬프트 패널에는 밝은 역할을, 동작 버튼에는 어두운 색상을 사용합니다. 활성 탭에는 패키지의 강조 스타일이 적용됩니다. 이는 공공 부문 사이트를 연상시키려고 임의로 선택한 파란색 팔레트가 아니라 실제 테마 역할입니다. 이 예제에서는 공식 정부 로고를 사용하지 않습니다.
토큰 이름을 정확히 해석하세요
text-light 토큰은 흰색입니다. 어두운 배경에 사용해야 하며, 채도가 낮은 텍스트를 뜻하는 일반적인 표현으로 사용해서는 안 됩니다. 보조 단계 텍스트에는 더 어두운 중성 색상 역할을 사용합니다. 참고 자료에는 상태별 전경색과 배경색 쌍이 포함되어 있지만, 워크숍에서는 사용 가능한 모든 색상을 보여주기 위해 오류나 성공 알림을 임의로 추가하지 않습니다.
NSW 디자인 시스템 Public Sans와 반응형 크기 체계
레이아웃을 살펴보기 전에 글꼴을 불러오세요
이 예제에서는 Public Sans의 400 및 700 굵기 글꼴을 로컬에서 불러옵니다. 패키지는 모바일과 데스크톱의 크기를 각각 정의합니다. 중간 크기 텍스트는 1.125rem에서 1.25rem으로, 가장 큰 제목 참고 크기는 2.25rem에서 3rem으로 커집니다. 이러한 크기 쌍은 사용 가능한 너비가 달라져도 읽기 순위를 유지하는 데 도움이 됩니다.
콘텐츠의 위계를 절제하세요
짧은 단계 레이블 다음에 설명형 제목, 소개, 안내 문단, 저장된 프롬프트 하나가 이어집니다. 각 문장을 카드로 만들 필요는 없습니다. 좁은 화면에서는 읽기 목록이 단계 패널 뒤에 배치되며, 짧은 세 개의 레이블로 이루어진 탭 목록은 텍스트를 여러 줄로 억지로 줄이지 않고도 사용할 수 있습니다.
NSW 디자인 시스템 탭 마크업과 키보드 동작
실제 링크를 컴포넌트가 보강하도록 하세요
초기 탭 목록에는 고유한 콘텐츠 ID를 가리키는 링크가 포함됩니다. 초기화하면 탭 목록, 탭, 탭 패널 의미가 추가되고 선택 상태를 관리하며 포커스 가능한 탭을 설정합니다. 컴포넌트가 패널을 찾으려면 href 대상이 올바르게 지정되어 있어야 합니다. 한 페이지에 탭 그룹을 두 개 이상 배치할 때는 ID를 중복하지 마세요.
각 탭 링크가 하나의 패널 ID와 일치하도록 하세요.
마크업을 추가한 뒤 그룹을 초기화하세요.
선택 상태와 키보드 포커스는 기본 컴포넌트가 관리하도록 하세요.
클릭뿐 아니라 키보드로 선택되는지도 확인하세요
NSW 디자인 시스템 저장된 프롬프트와 정확한 피드백
표시 중인 탭과 저장 상태를 분리하세요
각 단계의 동작 버튼은 Set에서 해당 프롬프트를 추가하거나 제거하고, aria-pressed를 업데이트하며, 레이블을 Save 또는 Remove로 변경합니다. 읽기 목록의 개수와 항목은 이 Set을 기준으로 계산됩니다. 저장된 단계로 돌아오면 선택 상태가 올바르게 표시됩니다. Clear reading list를 누르면 모든 선택이 해제되며, 해제할 항목이 없을 때는 버튼이 비활성화됩니다.
저장 범위를 명확히 안내하세요
읽기 목록은 페이지의 로컬 상태이며 새로고침하면 사라집니다. 인터페이스에서 이를 직접 안내합니다. 실제로 목록을 유지하려면 명시적인 저장 모델과 복원 동작이 필요하지만, 여기서는 어느 쪽도 암시하지 않습니다. 이 콘텐츠는 독자적으로 작성한 디자인 토론용 자료이며, 서비스 자격 안내서가 아니고 공식 NSW 절차를 재현했다고 주장하지도 않습니다.
NSW 디자인 시스템 전체 구현 및 검토
필요한 의존성을 포함해 소스 코드를 재현하세요
Vite 바닐라 프로젝트를 만들고 nsw-design-system 3.27.0 및 Public Sans를 설치한 다음, 제공된 엔트리 파일과 nsw.css를 저장하세요. 루트 마운트 요소를 유지하세요. 세 단계 전체 콘텐츠와 독창적인 프롬프트, 기본 Tabs 초기화, 읽기 목록 핸들러가 모두 포함되어 있습니다. 저장 및 초기화 동작을 의사 코드로 대체하지 않습니다.
버전을 고정한 NSW 패키지와 Public Sans 글꼴 파일을 설치하세요.
루트 마운트 요소를 포함해 전체 엔트리 파일과 nsw.css를 저장하세요.
서로 다른 두 탭에서 프롬프트를 저장하고 상태가 유지되는지 확인하세요.
ArrowRight를 사용하고 목록을 비운 뒤 빈 상태를 확인하세요.
탭 탐색과 저장된 콘텐츠를 분리하세요
링크 대상과 패널이 존재한 뒤에만 기본 Tabs 클래스를 초기화하세요. 프래그먼트 ID가 일치해야 보강 기능이 올바르게 동작합니다. 탭 레이블이 여전히 정상적으로 보여도 패널 ID를 변경하면서 href를 바꾸지 않으면 연결이 끊어집니다. 한 페이지에서 여러 그룹을 사용하는 경우 각 그룹에 고유한 ID를 지정하세요.
읽기 목록은 탭 인스턴스와 별개인 애플리케이션 상태로 관리하세요. 패널을 전환해도 프롬프트의 저장 상태가 유지되어야 하며, 해당 패널로 돌아왔을 때 aria-pressed가 그 상태를 반영해야 합니다. 독자가 다시 방문할 수 있는 동등한 콘텐츠에는 탭을 사용하세요. 완료된 단계를 요구하는 순차적 양식에는 다른 탐색 모델이 필요합니다. 이 예제는 페이지 내에서만 상태를 유지하므로, 저장 기능을 추가하려면 명시적인 저장 및 복원 정책이 필요합니다.
NSW 디자인 시스템 컴포넌트 예제
main.js — 기본 탭 및 읽기 목록 전체 예제
기존 단계 콘텐츠 전체, 탭 초기화, 저장·삭제·초기화 로직을 포함합니다.
자바스크립트
import Tabs from 'nsw-design-system/src/components/tabs/tabs.js';
import 'nsw-design-system/css';
import '@fontsource/public-sans/latin-400.css';
import '@fontsource/public-sans/latin-700.css';
import './nsw.css';
const sessions=[['Prepare','Choose one question to explore','Start with a clear outcome rather than a long list of activities.','Write a one-sentence purpose. Identify the people who can answer the question and the evidence you already have.'],['Discuss','Make room for different views','Use a short, structured discussion to compare observations.','Ask participants to describe what they noticed before proposing solutions. Keep a separate record of assumptions that need evidence.'],['Review','Turn observations into a next step','End with an action that has an owner and a clear reason.','Choose one improvement to investigate. Record what would count as success and when the group will review the result.']];
document.getElementById('root').innerHTML=`<main><p class="eyebrow">NSW DESIGN SYSTEM / ORIGINAL WORKSHOP STUDY</p><h1>Plan a focused discussion</h1><p class="nsw-intro">Move between three stages and save useful prompts to a local reading list.</p><div class="layout"><section class="nsw-tabs js-tabs"><ul class="nsw-tabs__list">${sessions.map(([name],i)=>`<li><a href="#session-${i}">${name}</a></li>`).join('')}</ul>${sessions.map(([name,title,lead,body],i)=>`<section id="session-${i}" class="nsw-tabs__content"><p class="step">STAGE ${i+1} / 3</p><h2>${title}</h2><p class="nsw-intro">${lead}</p><p>${body}</p><div class="prompt"><h3>Prompt to keep</h3><blockquote>${['What do we need to understand before choosing a solution?','Which observations are shared, and where do they differ?','What is the smallest next step that would reduce uncertainty?'][i]}</blockquote><button class="nsw-button nsw-button--dark save" data-index="${i}" aria-pressed="false">Save this prompt</button></div></section>`).join('')}</section><aside><h2>Your reading list</h2><p id="count" role="status">0 prompts saved</p><ul id="saved"></ul><p id="empty">Save a prompt from any stage. Changing tabs keeps your selection.</p><button class="nsw-button nsw-button--white" id="clear" disabled>Clear reading list</button><p class="note">This is an original local study using NSW 3.27.0 tabs and CSS. Nothing is stored after reloading.</p></aside></div></main>`;
new Tabs(document.querySelector('.js-tabs')).init();const saved=new Set();const $=id=>document.getElementById(id);function render(){$('count').textContent=saved.size+' prompt'+(saved.size===1?'':'s')+' saved';$('saved').replaceChildren(...[...saved].sort().map(i=>{const li=document.createElement('li');li.textContent=sessions[i][0]+': '+sessions[i][1];return li}));$('empty').hidden=saved.size>0;$('clear').disabled=!saved.size;document.querySelectorAll('.save').forEach(b=>{const yes=saved.has(Number(b.dataset.index));b.setAttribute('aria-pressed',String(yes));b.textContent=yes?'Remove saved prompt':'Save this prompt'})}document.querySelectorAll('.save').forEach(b=>b.addEventListener('click',()=>{const i=Number(b.dataset.index);saved.has(i)?saved.delete(i):saved.add(i);render()}));$('clear').addEventListener('click',()=>{saved.clear();render()});
보조 단계 레이블에는 어두운 중성 색상을 사용하며, --nsw-text-light는 흰색입니다.
04
NSW 디자인 시스템 에이전트 설정
구현 시작점
기본 탭의 클릭과 화살표 키 동작, 저장 상태 유지, 목록 비우기, 반응형 레이아웃을 로컬에서 테스트했습니다.
sh
npm create vite@latest nsw-workshop -- --template vanilla
cd nsw-workshop
npm install
npm install [email protected] @fontsource/public-sans
# Replace src/main.js and add src/nsw.css. Keep <div id="root"></div>.
npm run dev
프로젝트를 위한 프롬프트
에이전트 프롬프트
3.27.0의 기본 Tabs, Public Sans, 실제 의미 기반 역할을 사용해 NSW 워크숍 안내서를 구현하세요. 고유한 패널 ID, 키보드 선택, 독립적인 프롬프트 저장 상태, 유용한 빈 읽기 목록을 유지하세요. 저장 범위가 로컬로 한정됨을 명확히 안내하고 공식 서비스에 대한 주장을 피하세요.
05
NSW 디자인 시스템 출처 및 범위
OpenDesign가 NSW Design System 3.27.0을 사용해 만든 워크숍 연구입니다. 기본 탭 동작은 실제 기능이며, 콘텐츠와 저장된 프롬프트 흐름은 로컬 애플리케이션 로직으로 직접 구현했습니다.