01 Nord 디자인 시스템 인터페이스 미리보기 방 용량 다섯 가지 중 하나를 선택하고, 제목을 검증한 다음, 로컬 요청 요약을 작성하세요.
Nord Therapy 토큰을 오프라인에서 HTML/CSS로 구현한 예시입니다. 네이티브 Web Component 통합 예시는 별도로 제공됩니다. ·
구현 레퍼런스 Nord 토큰 9.0.4 및 최신 구성 요소 문서입니다. 아래 값은 기본 Therapy 테마를 설명하며 Nordhealth의 모든 브랜드에 적용되는 것은 아닙니다. 공개 문서가 제공되더라도 Nordhealth가 정한 용도 외에 Nord를 사용할 권한이 부여되는 것은 아닙니다.
이름 / 규칙 값 / 구성 용도 --n-color-accent#3559c7 주요 동작입니다. --n-color-text#0c1a3d 주요 콘텐츠입니다. --n-color-text-weak#36434a 보조 텍스트. --n-color-background#fafbfb 페이지입니다. --n-color-surface#ffffff 패널입니다. --n-color-border#d8dee4 구분선입니다. --n-color-border-strong#bcc5cc 컨트롤 테두리입니다. --n-color-text-error#d24023 오류 메시지입니다.
이름 / 규칙 값 / 구성 용도 --n-space-xs4px좁은 간격. --n-space-s8px관련 항목입니다. --n-space-m16px그룹입니다. --n-space-l24px섹션. --n-space-xl36px큼입니다. --n-space-xxl72px주요 항목입니다.
이름 / 규칙 값 / 구성 용도 --n-font-size-m0.875rem본문입니다. --n-font-size-l1rem큰 텍스트입니다. --n-font-size-xl1.25rem섹션 제목. --n-font-size-xxl1.5rem제목입니다. --n-line-height1.5본문 배율입니다. --n-line-height-form20px컨트롤 줄 상자입니다. --n-font-weight-heading600제목입니다. --n-border-radius-s3px컨트롤입니다. --n-border-radius5px표면입니다.
이름 / 규칙 값 / 구성 용도 label / hint / errorBuilt-in field text독립형 입력란에는 레이블을 지정하세요. expandBoolean, default false부모 너비에 맞게 늘립니다. sizes / m / l기본값은 중간 크기입니다. readonly versus disabledSubmitted versus excluded읽기 전용 상태에서도 포커스할 수 있습니다. --n-input-inline-size240px기본 너비는 고정입니다. 반응형 폼에는 expand를 사용하세요.
이름 / 규칙 값 / 구성 용도 Default slotNative option elementsnord-option을 임의로 만들지 마세요. valueString선택 상태를 제어합니다. requiredBooleannovalidate와 애플리케이션 오류 처리를 사용하세요. changeUser selection eventcomponent.value에서 값을 읽으세요. focus()Component method호출하기 전에 정의가 완료될 때까지 기다리세요.
이름 / 규칙 값 / 구성 용도 typesubmit by default제출 이외의 동작에는 button을 지정하세요. variantdefault / primary / dashed / plain / danger섹션마다 기본 동작 버튼은 하나만 사용하세요. hrefCreates anchor semantics탐색에 사용합니다. sizes / m / l기본값은 중간 크기입니다. loadingBusy presentation알림되는 상태 메시지와 함께 사용하세요.
03 Nord 디자인 시스템 전체 가이드 실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.
DESIGN-nordhealth.md 완전한 안내와 구현 시작점, 소스 링크.
가이드 다운로드 Nord 디자인 시스템 Nord는 공개 참고 자료가 있는 내부 제품 디자인 시스템입니다 정해진 사용 범위를 명확히 하세요 Nord 문서는 Nordhealth 경험을 위해 설계된 시스템을 설명합니다. 공개적으로 살펴볼 수 있는 구성 요소는 유용한 참고 자료지만, 브랜드나 구성 요소를 임의의 상업적 용도로 재사용해도 된다는 뜻은 아닙니다. 이 예시에 나오는 방 이름과 요청 흐름은 독자적으로 만든 데모 데이터입니다.
기본 토큰 표는 Therapy를 나타냅니다. 동물병원이나 의료 애플리케이션은 파란색 강조색이 모든 Nordhealth 제품에 적용된다고 가정하지 말고, 사용 목적에 맞는 테마를 선택해야 합니다. 테마 선택은 애플리케이션 수준에서 관리하세요.
지원 사양 읽기
Nord 디자인 시스템 Therapy 역할은 작업 공간을 차분하게 유지합니다 텍스트, 테두리, 표면의 역할을 구분하세요 이 예시에서는 요청 세부 정보에 기본 텍스트 역할을, 설명에는 덜 강조된 역할을 사용합니다. 흰색 패널은 미색 페이지 위에 놓이고, 더 뚜렷한 테두리로 편집 가능한 필드를 나타냅니다. 오류 텍스트는 인터페이스 전체를 빨갛게 물들이는 대신 제목 입력란 옆에 표시됩니다. 미리보기에는 임상 정보나 환자 정보가 포함되어 있지 않습니다.
지원 사양 읽기
Nord 디자인 시스템 작은 글씨에도 충분한 줄 간격을 확보하세요 문서에 명시된 글자 크기와 줄 간격을 함께 사용하세요 토큰은 본문 글자 크기 0.875rem과 본문 줄 높이 1.5를 짝으로 지정하며, 폼 텍스트에는 별도의 20px 줄 상자를 사용합니다. 두 규칙은 서로 다릅니다. 폼 값을 긴 문단에 적용하면 불필요하게 줄 간격이 좁아집니다. 실시간 참고 자료에서는 Nordhealth Sans 글꼴 패밀리 토큰을 사용하지만, 이 오프라인 구현 예시는 사용 가능한 시스템 글꼴을 사용하므로 라이선스가 있는 글꼴을 제공한다고 주장하지 않습니다.
지원 사양 읽기
Nord 디자인 시스템 애플리케이션 그리드 안에서 컨트롤을 확장하세요 페이지의 중단점은 구성 요소에서 정하지 않습니다 Input의 기본 인라인 크기는 240px입니다. 사용 가능한 필드 열 전체를 채우려면 문서에 명시된 expand를 사용하세요. 이 예시에서는 데스크톱에서 방 목록과 편집기를 나란히 배치하고 모바일에서는 세로로 쌓습니다. 이 중단점은 애플리케이션의 결정이지 Nord 토큰이 아닙니다. 행을 선택해도 방 이름, 용량, 이용 가능 여부 레이블은 계속 표시됩니다.
오프라인 구현 예시에서 선택하는 방 목록은 네이티브 라디오 그룹입니다. 별도로 제공되는 라이브러리 예시에서는 옵션이 다섯 개인 Select를 사용합니다. 두 예시 모두 방 하나를 선택하지만 레이아웃은 다르며, 동일한 런타임 구성 요소 구현인 것처럼 제시하지 않습니다.
지원 사양 읽기
Nord 디자인 시스템 레이블과 오류 메시지를 한 곳에서 관리하세요 이 폼에는 독립형 필드만으로 충분합니다 Input이나 Select 자체에 레이블, 힌트, 오류를 지정할 수 있습니다. 새 Field 조합을 사용하면 이 역할을 Field가 맡으므로 두 방식의 설정을 모두 중복하면 안내가 되풀이됩니다. 이 예시에서는 독립형 방식을 사용하고, 공백을 제거한 제목이 비어 있을 때 간단한 오류 하나를 표시합니다.
비활성화된 필드는 제출에서 제외되지만, 읽기 전용 값은 포커스와 제출이 가능합니다. 방 식별자를 요청에 포함해야 한다면 편집을 막기 위해 비활성화하지 마세요.
요청 제목 레이블을 계속 표시하세요. 힌트에는 입력해야 할 내용을 안내하고, 레이블을 대신하게 하지 마세요. 검증 메시지를 유효하지 않은 컨트롤과 연결하세요. 지원 사양 읽기
Nord 디자인 시스템 Select에는 일반 option 요소를 사용하세요 호스트 구성 요소에서 값을 읽으세요 기본 슬롯에는 네이티브 option 요소를 넣을 수 있습니다. 각 방에는 고정된 값과 용량을 포함하는 설명형 표시 레이블을 지정하세요. change 이벤트가 발생하면 애플리케이션은 호스트 값에서 요약 정보를 다시 계산합니다. 이 구성에는 사용자 정의 nord-option 태그가 없습니다.
Nord는 선택지가 많을 때는 Select를, 몇 가지 선택지를 바로 보여주는 것이 유용할 때는 라디오 버튼을 권장합니다. 이 예시에는 방이 다섯 개 있습니다. 오프라인 라디오 방식에서는 용량별 시각적 차이를 쉽게 살펴볼 수 있습니다.
지원 사양 읽기
Nord 디자인 시스템 Button 기본값은 폼 구성에 영향을 줍니다 동작, 링크, 로딩의 의미를 명시적으로 선택하세요 Nord Button의 기본값은 type="submit"입니다. 따라서 폼 안에서 미리보기나 초기화와 같은 보조 작업을 수행할 때 제출되지 않게 하려면 type을 명시해야 합니다. 컴포넌트에 href를 지정하면 노출되는 의미가 링크로 바뀝니다. 클릭 핸들러로 앵커를 흉내 내기보다 탐색에 이 방식을 사용하세요.
로딩 상태에서는 버튼에 포커스를 유지하면서 반복 활성화를 방지합니다. 스피너는 보조 기술에 노출되지 않으므로 진행 상황을 글로 전달해야 합니다. disabled를 무조건 대신 사용하지 마세요. 사용할 수 없는 작업과 이미 진행 중인 작업은 포커스와 피드백에 필요한 방식이 다릅니다.
회의실 요청 예시는 초안 계산을 동기적으로 처리하므로 로딩 시간이 필요하지 않습니다. 기본 버튼은 제목을 검증하고 선택한 회의실을 읽으며, 둘 중 하나를 수정하면 더 이상 유효하지 않은 초안 문장을 삭제합니다. 입력란과 Select 섹션에서는 해당 입력을 처리하는 Nord API를 설명합니다.
지원 사양 읽기
Nord 디자인 시스템 컴포넌트 메서드를 호출하기 전에 필요한 CSS을 불러오세요 프로토타입과 프로덕션 번들링은 다릅니다 공식 빠른 시작에서는 컴포넌트 모듈과 CSS 프레임워크를 함께 사용합니다. 프레임워크는 공유 토큰과 기본 스타일을 제공합니다. 번들 애플리케이션에서는 @nordhealth/css와 @nordhealth/components를 설치하고, CSS은 한 번만 가져온 뒤 사용하는 컴포넌트 모듈만 가져오세요. 패키지 모듈은 부수 효과로 요소를 등록합니다.
React 19에서는 이러한 사용자 지정 요소를 직접 사용할 수 있습니다. 이전 @nordhealth/react 래퍼는 현재 가이드에서 사용 중단되었습니다. 서버 렌더링에는 컴포넌트 shadow DOM이 포함되지 않으며, Next.js에서 가져오려면 클라이언트 경계가 필요합니다. 이러한 통합 제약은 라이브러리 없이도 상호작용하는 오프라인 HTML 미리보기와 별도로 고려하세요.
컴포넌트 모듈보다 먼저 프레임워크 CSS을 불러오세요. 초기화 중 focus를 호출하기 전에 customElements.whenDefined가 완료될 때까지 기다리세요. 유효성 검사 및 로컬 상태 핸들러를 연결하세요. 여러 CDN 모듈 요청에 의존하지 말고 프로덕션 종속성을 번들링하세요. 지원 사양 읽기
Nord 디자인 시스템 컴포넌트 예시 완전한 독립형 인터랙티브 예제 전체 문서를 index.html로 저장한 다음 브라우저에서 여세요. Nord Therapy 토큰을 오프라인에서 HTML/CSS 방식으로 해석하며, 네이티브 Web Component 통합은 별도로 제공됩니다.
html 코드 복사
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Nord room request interpretation</title><style>*{box-sizing:border-box}body{margin:0;background:#fafbfb;color:#0c1a3d;font:14px/1.5 system-ui,sans-serif}button,input{font:inherit}header{height:52px;background:white;border-bottom:1px solid #d8dee4;padding:0 24px;display:flex;align-items:center;justify-content:space-between}header small{color:#36434a}main{max-width:960px;margin:36px auto;padding:0 24px}h1{font-size:24px;line-height:1.2;margin:0 0 8px}h2{font-size:20px;line-height:1.2;margin:0 0 16px}p{margin:0 0 24px}.muted{color:#36434a}.layout{display:grid;grid-template-columns:310px 1fr;gap:24px}.panel{background:white;border:1px solid #d8dee4;border-radius:5px;padding:24px}fieldset{margin:0;padding:0;border:0;min-width:0}legend{font-weight:600;margin-bottom:16px}.room{display:flex;gap:12px;padding:12px;border:1px solid #d8dee4;border-radius:3px;margin-bottom:8px;cursor:pointer;align-items:center}.room:has(:checked){border-color:#3559c7;background:#f0f4ff}.room input{accent-color:#3559c7}.room span{flex:1}.room small{display:block;color:#36434a}.room b{font-size:12px;font-weight:500}.diagram{height:120px;background:#f6f8f8;display:grid;place-items:center;margin:-24px -24px 24px;border-radius:5px 5px 0 0;border-bottom:1px solid #d8dee4}.table{height:50px;border:2px solid #bcc5cc;border-radius:5px;background:#fff;position:relative;transition:width .2s ease}.chair{position:absolute;width:12px;height:10px;border:1px solid #bcc5cc;background:white;border-radius:3px;top:-16px}.chair.bottom{top:auto;bottom:-16px}label.field{display:block;font-weight:600;margin:16px 0 8px}#title{width:100%;border:1px solid #bcc5cc;border-radius:3px;height:36px;padding:7px 12px;color:inherit;background:white}#title[aria-invalid=true]{border-color:#d24023}.error{color:#d24023;min-height:20px;font-size:12px;margin:4px 0 12px}button{background:#3559c7;color:white;border:1px solid transparent;box-shadow:0 1px 3px #0c0c0c17;border-radius:3px;padding:7px 16px;cursor:pointer}button:focus-visible,input:focus-visible{outline:2px solid #3559c7;outline-offset:3px}.summary{margin-top:24px;background:#f0f4ff;border:1px solid #c6d4f9;padding:16px;border-radius:5px;overflow-wrap:anywhere}.summary:empty{display:none}.boundary{font-size:12px;color:#36434a;margin-top:24px}#selected{font-weight:600}.facts{display:flex;gap:24px;margin-bottom:24px}.facts strong{font-size:20px;display:block}.facts span{font-size:12px;color:#36434a}@media(max-width:650px){main{margin:24px auto;padding:0 16px}.layout{grid-template-columns:1fr;gap:16px}.panel{padding:16px}.diagram{margin:-16px -16px 16px}.room{padding:8px 12px}header{padding:0 16px}header small{display:none}}</style><header><strong>◈ Workplace</strong><small>Room request workspace</small></header><main><h1>A room for your next conversation</h1><p class="muted">Choose a room and prepare a request draft.</p><div class="layout"><section class="panel"><fieldset><legend>Choose a room</legend><div id="rooms"></div></fieldset></section><section class="panel"><div class="diagram" aria-hidden="true"><div class="table" id="table"></div></div><h2 id="selected">Birch</h2><div class="facts"><div><strong id="capacity">4</strong><span>Seats</span></div><div><strong>Draft</strong><span>Request status</span></div></div><form novalidate><label class="field" for="title">Request title</label><input id="title" type="text" aria-describedby="hint error" placeholder="e.g. Design review"><div id="error" class="error" role="alert"></div><p id="hint" class="muted">Use a non-sensitive meeting title. Availability is not checked in this example.</p><button type="submit">Prepare request</button></form><div class="summary" id="result" role="status"></div></section></div><p class="boundary">Independent HTML interpretation of Nord Therapy tokens. Nord is intended for Nordhealth products. This example creates a local draft only; it does not reserve a room.</p></main><script>const rooms=[['Birch',4],['Cedar',6],['Elm',8],['Maple',10],['Pine',12]],field=document.querySelector('#title'),result=document.querySelector('#result');let selected=0;document.querySelector('#rooms').innerHTML=rooms.map(([name,n],i)=>`<label class="room"><input type="radio" name="room" value="${i}" ${i===0?'checked':''}><span>${name}<small>Meeting room</small></span><b>${n} seats</b></label>`).join('');function update(){let [name,n]=rooms[selected];document.querySelector('#selected').textContent=name;document.querySelector('#capacity').textContent=n;let table=document.querySelector('#table');table.style.width=(n*12+44)+'px';table.innerHTML=Array.from({length:n},(_,i)=>`<i class="chair ${i>=n/2?'bottom':''}" style="left:${12+(i%(n/2))*24}px"></i>`).join('');result.textContent=''}document.querySelectorAll('[name=room]').forEach(input=>input.onchange=()=>{selected=Number(input.value);update()});document.querySelector('form').onsubmit=e=>{e.preventDefault();if(!field.value.trim()){document.querySelector('#error').textContent='Enter a request title.';field.setAttribute('aria-invalid','true');field.focus();return}result.textContent='Draft prepared: '+field.value.trim()+' · '+rooms[selected][0]+' · '+rooms[selected][1]+' seats. No room is reserved.'};field.oninput=()=>{field.removeAttribute('aria-invalid');document.querySelector('#error').textContent='';result.textContent=''};update();</script></html>
코드 참조
이 예시에서는 회의실 선택지를 라디오 버튼으로 표시합니다. 네이티브 Nord 예시에서는 일반 option 요소를 사용하는 Select를 사용합니다. 어느 쪽도 실제 회의실을 예약하지 않습니다. 명시적 유효성 검사를 적용한 라벨 있는 회의실 요청 독립형 nord-input과 nord-select는 선택적 Field 패밀리 없이 라벨을 제공합니다. 제출 시 컴포넌트 값을 읽고 입력 오류 속성을 설정합니다.
html 코드 복사
<!doctype html>
<html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Room request draft</title>
<link rel="stylesheet" href="https://nordcdn.net/ds/css/5.2.4/nord.min.css">
<script type="module" src="https://nordcdn.net/ds/components/5.3.0/index.js"></script>
<style>main{max-width:560px;margin:auto;padding:var(--n-space-l)}form{display:grid;gap:var(--n-space-l)}</style>
<main><h1>Prepare a room request</h1><p>For an authorized Nordhealth product. Local demonstration only.</p>
<form novalidate>
<nord-input id="request" name="request" label="Request title" hint="Use a non-sensitive meeting title." required expand></nord-input>
<nord-select id="room" name="room" label="Room" value="Birch" expand>
<option value="Birch">Birch · 4 seats</option><option value="Cedar">Cedar · 6 seats</option>
<option value="Elm">Elm · 8 seats</option><option value="Maple">Maple · 10 seats</option><option value="Pine">Pine · 12 seats</option>
</nord-select>
<nord-button type="submit" variant="primary">Prepare request</nord-button>
</form><p id="result" role="status"></p></main>
<script type="module">
await Promise.all(['nord-input','nord-select','nord-button'].map(name=>customElements.whenDefined(name)));
const form=document.querySelector('form'), title=document.querySelector('#request'),room=document.querySelector('#room'),result=document.querySelector('#result');
form.addEventListener('submit',event=>{
event.preventDefault();title.error=title.value.trim()?'':'Enter a request title.';
if(title.error){title.focus();return;}
result.textContent=`Draft: ${title.value.trim()} in ${room.value}. No room is reserved.`;
});
form.addEventListener('input',()=>{result.textContent='';title.error='';});
form.addEventListener('change',()=>{result.textContent='';});
</script></html> 코드 참조
회의실 선택지가 다섯 개라 Select를 간결한 선택 컨트롤로 활용할 수 있습니다. Button의 기본값은 submit이지만, 이 예시에서는 type을 명시합니다. 메서드를 사용하기 전에 사용자 지정 요소가 정의될 때까지 기다립니다. 예약 서비스는 호출하지 않습니다. 구현 시작점 승인된 Nordhealth 용도를 위한 전체 공개 CDN 프로토타입입니다. 문서에서는 현재 CSS 5.2.4 및 components 5.3.0을 안내합니다. 프로덕션에서는 npm 패키지를 번들링해야 합니다. 아래 오프라인 시각적 해석은 이러한 원격 패키지를 불러오지 않습니다.
html 예제 복사
<!doctype html>
<html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Room request draft</title>
<link rel="stylesheet" href="https://nordcdn.net/ds/css/5.2.4/nord.min.css">
<script type="module" src="https://nordcdn.net/ds/components/5.3.0/index.js"></script>
<style>main{max-width:560px;margin:auto;padding:var(--n-space-l)}form{display:grid;gap:var(--n-space-l)}</style>
<main><h1>Prepare a room request</h1><p>For an authorized Nordhealth product. Local demonstration only.</p>
<form novalidate>
<nord-input id="request" name="request" label="Request title" hint="Use a non-sensitive meeting title." required expand></nord-input>
<nord-select id="room" name="room" label="Room" value="Birch" expand>
<option value="Birch">Birch · 4 seats</option><option value="Cedar">Cedar · 6 seats</option>
<option value="Elm">Elm · 8 seats</option><option value="Maple">Maple · 10 seats</option><option value="Pine">Pine · 12 seats</option>
</nord-select>
<nord-button type="submit" variant="primary">Prepare request</nord-button>
</form><p id="result" role="status"></p></main>
<script type="module">
await Promise.all(['nord-input','nord-select','nord-button'].map(name=>customElements.whenDefined(name)));
const form=document.querySelector('form'), title=document.querySelector('#request'),room=document.querySelector('#room'),result=document.querySelector('#result');
form.addEventListener('submit',event=>{
event.preventDefault();title.error=title.value.trim()?'':'Enter a request title.';
if(title.error){title.focus();return;}
result.textContent=`Draft: ${title.value.trim()} in ${room.value}. No room is reserved.`;
});
form.addEventListener('input',()=>{result.textContent='';title.error='';});
form.addEventListener('change',()=>{result.textContent='';});
</script></html> 프로젝트를 위한 프롬프트 에이전트 프롬프트 프롬프트 복사
라벨이 있는 컨트롤에 Nord Therapy 의미 역할을 적용하세요. 반응형 애플리케이션 레이아웃 안에 필드를 배치하고 확장하세요. 요청 제목의 앞뒤 공백을 제거해 검증하고, 회의실은 하나만 선택되도록 유지하며, 로컬 초안 결과만 표시하세요. 실제 Nordhealth 구현에는 문서에 명시된 패키지 및 테마 사용 권한을 따르세요. 독립적으로 작성한 OpenDesign 참고 자료입니다. Nord는 Nordhealth 제품에서의 사용을 목적으로 한다고 명시합니다. 이 독창적인 HTML 해석은 회의실을 예약하지 않으며 브랜드 또는 컴포넌트 사용 권한을 부여하지 않습니다.