01 Semi Design 디자인 시스템 인터페이스 미리 보기 이름을 검증하고, 요약 메일 설정을 선택하고, 이전 단계로 돌아가 최종 로컬 구성을 확인하세요.
Semi 테마 스케일과 Steps/Input/Switch 동작을 오프라인에서 HTML 방식으로 해석한 예시입니다. 기본 React 예제는 별개입니다. ·
구현 레퍼런스 02
Semi Design 디자인 시스템 디자인 참조 Semi 공식 문서 및 기본 테마 SCSS 스냅샷. $ 이름은 컴파일 시점의 Sass 상수이고 --semi-* 이름은 런타임 CSS 변수입니다. 애플리케이션 워크플로 데이터는 자체 제작한 것입니다.
이름 / 규칙 값 / 구성 용도 $height-control-small / default / large24 / 32 / 40px공개된 컨트롤 높이. $spacing-super-tight2px가장 좁은 간격. $spacing-extra-tight4px매우 좁은 간격. $spacing-tight8px좁은 간격. $spacing-base-tight12px그룹 사이의 촘촘한 간격. $spacing-base16px기본 간격. $spacing-base-loose20px그룹 간격을 넓힘. $spacing-loose24px섹션 간격. $spacing-extra-loose32px넓은 간격. $spacing-super-loose40px이 세트에서 이름이 지정된 간격 중 가장 넓은 값.
이름 / 규칙 값 / 구성 용도 font-size-small mixin12 / 16px크기는 variables.scss에서, 줄 높이는 믹스인에서 가져옵니다. font-size-regular mixin14 / 20px본문 텍스트. font-size-header-6 mixin16 / 22px작은 제목입니다. font-size-header-4 mixin20 / 28px섹션 제목. font-size-header-3 mixin24 / 32px페이지 제목 옵션. font-size-header-1 mixin32 / 44px이름이 지정된 제목 중 가장 큰 크기.
이름 / 규칙 값 / 구성 용도 --semi-color-primaryrgba(var(--semi-blue-5),1)밝은 팔레트는 rgb(0,100,250)로 표시됩니다. --semi-color-primary-hoverrgba(var(--semi-blue-6),1)밝은 팔레트는 rgb(0,98,214)로 표시됩니다. --semi-color-text-0rgba(var(--semi-grey-9),1)밝은 테마의 기본 텍스트는 rgb(28,31,35)로 표시됩니다. --semi-color-text-2Grey 9 at .62 opacity in light mode보조 텍스트. 어두운 테마에서는 불투명도가 다릅니다. --semi-color-fill-0Grey 8 at .05 opacity in light mode은은한 채우기 색상은 배경 표면에 맞춰 조정됩니다. --semi-border-radius-small3px일반적인 컨트롤. --semi-border-radius-medium6px메뉴 및 유사한 표면. --semi-border-radius-large12px큰 컨테이너 역할. --semi-border-radius-full9999px알약형 스타일.
이름 / 규칙 값 / 구성 용도 type="basic"Recommended simple step bar이전 기본 스타일은 문서에서 사용 중단 예정으로 표시됩니다. currentZero-based number0부터 시작합니다. statuswait / process / finish / error / warning현재 단계의 상태. type="nav"Non-interactive navigation appearance클릭 가능한 마법사를 대신하는 지름길이 아닙니다. onChange(index)Index includes initial offset이동을 허용할지는 애플리케이션에서 결정합니다.
이름 / 규칙 값 / 구성 용도 Input onChange(value,event)첫 번째 인수는 새 값입니다. Input validateStatusdefault / error / warning시각적 스타일만 적용하며 비즈니스 데이터를 검증하지 않습니다. Input compositionBoolean, false by default활성화하면 IME 입력 확정 후에 onChange를 호출합니다. Input aria-describedbyDescription ID도움말 및 오류 텍스트를 연결하세요.
이름 / 규칙 값 / 구성 용도 Switch checkedControlled Boolean설정 상태는 상위 컴포넌트에서 관리하세요. Switch onChange(checked,event)Boolean 값을 그대로 사용하세요. Switch aria-labelMeaningful state label시각적 토글이 아니라 설정의 의미를 설명하세요. Switch size="small"No checkedText / uncheckedText treatment긴 레이블은 스위치 바깥에 배치하세요.
03 Semi Design 디자인 시스템 종합 가이드 실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.
DESIGN-semi-design.md 완전한 안내와 구현 시작점, 소스 링크.
가이드 다운로드 Semi Design 디자인 시스템: 실제 React 메이저 버전에 맞는 패키지 선택 접미사에 따라 연동 방식이 달라집니다. Semi의 최신 Quick Start에서는 React 19 패키지와 이전 React 버전에서 사용하던 패키지를 구분합니다. 이 예제에서는 React 18과 @douyinfe/semi-ui를 명시적으로 선택합니다. 이를 React 19로 바꾸려면 문서에 안내된 @douyinfe/semi-ui-19 import와 종속성 선택을 적용해야 합니다.
지원되는 번들러는 컴포넌트 JavaScript에서 관련 CSS을 불러옵니다. 사용자 지정 접두사, 테마 컴파일 또는 CSS 레이어처럼 컴파일 시점에 적용되는 변경에는 별도의 도구 고려 사항이 있습니다. 기본 import 예제를 모든 테마 사용자 지정이 설정 없이 작동한다는 주장으로 확대 해석하지 마세요.
지원 사양 읽기
Semi Design 디자인 시스템의 이름 있는 Sass 스케일로 밀도 구체화하기 공개된 24, 32, 40px 컨트롤 높이 사용 Semi의 컨트롤 높이 상수는 24, 32, 40px입니다. 간격 이름은 2~40px 범위를 다루며, 값이 일정한 간격으로 증가하지는 않습니다. 마법사의 기본 필드에는 12px의 도움말 간격과 다음 섹션까지 24px의 간격을 적용해도 새로운 간격 체계를 도입할 필요가 없습니다.
이 값들은 Sass 상수이며 런타임 변수로 자동 제공되지 않습니다. 이 견본은 자체 제작한 페이지 CSS에서 이에 해당하는 크기를 사용합니다. 개발자가 스타일시트를 다시 빌드하지 않고 런타임에 레이아웃 테마를 지정하려 할 때 이 차이가 중요합니다.
지원 사양 읽기
Semi Design 디자인 시스템에서 실제 크기와 줄 높이 조합 사용 본문 텍스트와 제목은 서로 다른 리듬을 가집니다. 일반 믹스인은 14px 텍스트와 20px 줄 높이를, 작은 크기 믹스인은 12px 텍스트와 16px 줄 높이를 조합합니다. Header 3은 24/32이고 Header 1은 32/44입니다. 짧은 마법사 제목에는 전자를 사용하고, 후자는 더 강한 페이지 위계가 필요할 때 활용할 수 있습니다.
소스 글꼴군은 Inter를 먼저 사용하고 플랫폼 및 CJK 대체 글꼴을 뒤따라 지정합니다. 오프라인 미리보기는 사용 가능한 시스템 글꼴 스택을 사용하며, 특정 글꼴을 다운로드했다고 주장하지 않습니다. 좁은 뷰포트에서 단계 표시줄이 줄바꿈되어도 의미가 유지되도록 단계 이름을 간결하게 작성하세요.
지원 사양 읽기
Semi Design 디자인 시스템의 테마 역할과 팔레트 채널은 별개입니다 애플리케이션에서 확인된 역할을 사용하세요 CSS 기본 역할은 팔레트 채널 변수를 rgba로 감쌉니다. 일반적인 색상 속성에는 --semi-color-primary를 사용할 수 있지만, 원시 --semi-blue-5 채널 목록만으로는 완전한 CSS 색상이 되지 않습니다. 라이트 및 다크 팔레트에 따라 채널 값이 달라집니다.
텍스트 역할에도 불투명도가 적용됩니다. 보조 텍스트는 임의로 더 밝은 16진수 색상 코드가 아니며, 비활성 텍스트를 중요한 도움말에 재사용해서는 안 됩니다. 구성 준비만으로 실제 계정이 생성되는 것은 아니므로 마법사의 완료 메시지는 중립적으로 유지합니다.
지원 사양 읽기
Semi Design 디자인 시스템의 기본 단계는 진행 상태를 나타내며, 검증을 건너뛸 수 있다는 뜻이 아닙니다 전환 규칙은 애플리케이션에서 관리합니다 Semi는 간단한 단계 표시줄에 type="basic"을 권장합니다. current는 0부터 시작하며, 현재 단계에는 process, error 또는 지원되는 다른 상태를 지정할 수 있습니다. 기존 기본 모양은 문서에서 사용 중단 예정으로 표시되어 있습니다.
이 예제에서는 의도적으로 계속 및 이전 컨트롤을 통해 단계가 진행됩니다. 모든 단계 클릭을 setCurrent에 연결하지 않습니다. 그렇게 하면 이름을 입력하지 않은 채 검토 단계에 도달할 수 있기 때문입니다. 별도로 문서화된 nav 모양은 상호작용하지 않으므로 마법사 탐색 기능으로 오해하지 마세요.
첫 번째 단계에서 벗어나기 전에 이름을 검증하세요. 뒤로 이동해도 선택한 주간 요약 불리언 값을 유지하세요. 검토 단계에 전체 설정을 표시하세요. 계정이나 구독이 생성되었다고 주장하지 말고 로컬 구성만 준비하세요. 지원 사양 읽기
Semi Design 디자인 시스템에서는 스위치 옆의 설명만으로도 설정을 이해할 수 있어야 합니다 상위 컴포넌트에서 상태를 관리하세요 Switch는 checked와 불리언 값이 먼저 전달되는 onChange 콜백을 사용합니다. Weekly digest와 같이 라벨에 설정을 표시하고, 주변 텍스트로 설정의 의미를 설명하세요. 긴 켜짐/꺼짐 문구는 작은 컨트롤 바깥에 배치해야 합니다. 작은 스위치는 내부에 해당 문구를 표시하는 방식을 지원하지 않습니다.
어떤 설정인지 알 수 있도록 명확한 접근성 이름을 지정하세요. 마법사 단계를 이동해도 설정 값을 유지하세요. 검토 페이지에 최종 값을 일반 텍스트로 표시하세요. 지원 사양 읽기
Semi Design 디자인 시스템에서 Button의 type과 theme은 서로 다른 질문에 답합니다 의미상 역할과 시각적 표현 Semi Button의 type은 primary 또는 danger와 같은 역할을 선택합니다. theme은 light, solid, borderless 또는 outline과 같은 시각적 표현을 선택합니다. 이 예제에서는 버튼을 더 눈에 띄게 하려고 danger를 잘못 사용하는 대신, 기본 동작인 계속에는 solid primary를, 이전 동작에는 더 차분한 표현을 사용합니다.
오프라인 예제에서는 단계가 바뀌면 새 섹션 제목으로 포커스를 옮기고, 검증에 실패하면 잘못된 입력 필드로 포커스를 돌립니다. 모바일 레이아웃과 키보드 탐색 순서는 소스에서 확인한 기본 React 예제와 별도로 테스트합니다.
지원 사양 읽기
Semi Design 디자인 시스템 컴포넌트 예제 완전한 독립형 인터랙티브 예제 문서 전체를 index.html로 저장한 뒤 브라우저에서 여세요. Semi 테마 배율과 Steps/Input/Switch 동작을 오프라인에서 HTML 방식으로 해석합니다. 기본 React 예제는 별도입니다.
html 코드 복사
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Semi workspace setup interpretation</title><style>
*{box-sizing:border-box}body{margin:0;background:#f5f6f8;color:#1c1f23;font:14px/20px Inter,system-ui,sans-serif}button,input{font:inherit}button{cursor:pointer;min-height:32px;border:0;border-radius:3px;padding:6px 16px;background:rgba(46,50,56,.05);color:inherit}button.primary{background:#0064fa;color:white}button.primary:hover{background:#0062d6}button:focus-visible,input:focus-visible{outline:2px solid #0064fa;outline-offset:3px}header{padding:20px 32px;border-bottom:1px solid rgba(28,31,35,.08);background:white;display:flex;justify-content:space-between;gap:16px}header strong{font-size:16px}header span,.muted{color:#63656a}main{max-width:950px;margin:32px auto;padding:0 24px}h1{font-size:24px;line-height:32px;font-weight:600;margin:0 0 8px}h2{font-size:20px;line-height:28px;font-weight:600;margin:0 0 12px}p{margin:0 0 16px}.card{background:white;border:1px solid rgba(28,31,35,.08);border-radius:12px;overflow:hidden;margin-top:24px}.steps{padding:24px;display:flex;list-style:none;margin:0;border-bottom:1px solid rgba(28,31,35,.08);gap:12px}.steps li{flex:1;display:flex;align-items:center;gap:8px;color:#63656a;font-size:12px}.steps b{height:24px;width:24px;border-radius:50%;display:grid;place-items:center;background:#eee;flex-shrink:0}.steps [aria-current]{color:#0064fa}.steps [aria-current] b{background:#0064fa;color:white}.steps .done b{background:#eaf5ff;color:#0064fa}.workspace{display:grid;grid-template-columns:1fr 240px;min-height:300px}.panel{padding:32px}.illustration{background:#eaf5ff;display:flex;flex-direction:column;justify-content:center;padding:24px;gap:12px}.mini{background:white;box-shadow:0 6px 20px #0064fa12;border-radius:6px;padding:16px;transform:rotate(-3deg)}.mini i{display:block;height:8px;background:#eaf5ff;width:80%;margin:8px 0;border-radius:3px}.mini i:first-child{background:#0064fa;width:36%}.mini i:nth-child(3){width:55%}.mini:last-child{transform:rotate(4deg);margin-left:20px}.mini span{font-size:12px;color:#63656a}.form-label{display:block;font-weight:600;margin:20px 0 8px}input[type=text]{height:32px;background:rgba(46,50,56,.05);border:1px solid transparent;border-radius:3px;padding:5px 12px;width:100%}input[aria-invalid=true]{border-color:#d52515}.error{color:#b21b13;min-height:20px;font-size:12px;margin:8px 0}.preference{border:1px solid #eee;border-radius:6px;padding:16px;display:flex;align-items:center;justify-content:space-between;gap:20px}.preference p{margin:4px 0 0;font-size:12px}.toggle{appearance:none;width:40px;height:24px;border-radius:999px;background:#bbb;position:relative;cursor:pointer;flex-shrink:0}.toggle:checked{background:#0064fa}.toggle:before{content:'';position:absolute;left:3px;top:3px;background:white;border-radius:50%;width:18px;height:18px}.toggle:checked:before{left:19px}footer{display:flex;justify-content:space-between;padding:20px 32px;border-top:1px solid rgba(28,31,35,.08)}dl{margin:20px 0}dt{color:#63656a;font-size:12px}dd{margin:4px 0 20px;font-size:16px;font-weight:600;overflow-wrap:anywhere}#result{margin-top:16px;border-radius:6px;background:#eaf5ff;padding:16px}#result:empty{display:none}.boundary{font-size:12px;margin-top:20px;color:#63656a}h2:focus{outline:none}@media(max-width:600px){header{padding:16px}header span{display:none}main{margin:24px auto;padding:0 16px}.workspace{grid-template-columns:1fr}.illustration{display:none}.steps{padding:16px;gap:8px}.steps li{flex-direction:column;align-items:flex-start;gap:4px}.panel{padding:24px 20px}footer{padding:16px 20px;gap:12px}footer button{padding:6px 12px}}
</style><header><strong>◒ Workspace</strong><span>Configuration studio</span></header><main><h1>Make room for your team</h1><p class="muted">Three steps to prepare a workspace configuration.</p><div class="card"><ol class="steps" aria-label="Setup progress"><li><b>1</b>Name workspace</li><li><b>2</b>Choose updates</li><li><b>3</b>Review settings</li></ol><div class="workspace"><section class="panel" id="panel"></section><aside class="illustration" aria-hidden="true"><div class="mini"><i></i><i></i><i></i><span>A place for shared ideas</span></div><div class="mini"><i></i><i></i><i></i><span>Updates on your terms</span></div></aside></div><footer><button id="previous">Previous</button><button class="primary" id="next">Continue</button></footer></div><div id="result" role="status"></div><p class="boundary">Independent HTML interpretation of Semi’s theme and components. This example stores a draft only in memory; it does not create an account.</p></main><script>
let step=0,name='',digest=true;const panel=document.querySelector('#panel'),next=document.querySelector('#next'),previous=document.querySelector('#previous'),result=document.querySelector('#result');function render(focus=false){document.querySelectorAll('.steps li').forEach((el,i)=>{el.className=i<step?'done':'';el.removeAttribute('aria-current');if(i===step)el.setAttribute('aria-current','step')});previous.style.visibility=step?'visible':'hidden';next.textContent=step===2?'Prepare configuration':'Continue';if(step===0){panel.innerHTML='<h2 tabindex="-1">Name your workspace</h2><p class="muted">Choose a name your team will recognize.</p><label class="form-label" for="name">Workspace name</label><input id="name" type="text" placeholder="e.g. Studio North" autocomplete="organization" aria-describedby="help error"><p id="error" class="error" role="alert"></p><p id="help" class="muted">You can revisit this step before preparing the configuration.</p>';let input=document.querySelector('#name');input.value=name;input.oninput=()=>{name=input.value;input.removeAttribute('aria-invalid');document.querySelector('#error').textContent='';result.textContent=''};input.onkeydown=e=>{if(e.key==='Enter')next.click()}}else if(step===1){panel.innerHTML='<h2 tabindex="-1">Choose your updates</h2><p class="muted">Keep the weekly digest in your configuration, or switch it off.</p><label class="preference"><span><strong>Weekly digest</strong><p class="muted">A weekly summary of workspace activity.</p></span><input class="toggle" type="checkbox" role="switch" aria-label="Weekly digest" id="digest"></label>';let input=document.querySelector('#digest');input.checked=digest;input.onchange=()=>{digest=input.checked;result.textContent=''}}else{panel.innerHTML='<h2 tabindex="-1">Review settings</h2><p class="muted">Check the draft before preparing it.</p><dl><dt>Workspace name</dt><dd id="review-name"></dd><dt>Weekly digest</dt><dd id="review-digest"></dd></dl>';document.querySelector('#review-name').textContent=name.trim();document.querySelector('#review-digest').textContent=digest?'Enabled':'Disabled'}if(focus)panel.querySelector('h2').focus()}
next.onclick=()=>{if(step===0&&!name.trim()){document.querySelector('#error').textContent='Enter a workspace name.';let input=document.querySelector('#name');input.setAttribute('aria-invalid','true');input.focus();return}if(step<2){step++;render(true)}else result.textContent='Configuration prepared locally: '+name.trim()+' · Weekly digest '+(digest?'enabled':'disabled')+'. No account created.'};previous.onclick=()=>{step=Math.max(0,step-1);result.textContent='';render(true)};render();
</script></html>
코드 참조
계속을 누르면 다음 단계로 진행하기 전에 작업 공간 이름을 검증합니다. 이 문서는 단계 동작을 해석합니다. 패키지 경계를 설명하는 별도의 React 항목은 React 18과 19를 구분합니다. 검증을 포함한 3단계 구성 마법사 기본 Steps는 현재 진행 상황을 추적하고, Input과 Switch는 페이지를 이동해도 값을 유지합니다. 계속을 누르면 이름을 검증하며, 마지막 동작은 로컬 구성만 준비합니다.
jsx 코드 복사
// React 18 example. React 19 uses @douyinfe/semi-ui-19 instead.
// npm install react@18 react-dom@18 @douyinfe/semi-ui
import React,{useState} from 'react';
import {createRoot} from 'react-dom/client';
import {Steps,Input,Switch,Button} from '@douyinfe/semi-ui';
function WorkspaceSetup(){
const [current,setCurrent]=useState(0),[name,setName]=useState('');
const [digest,setDigest]=useState(true),[error,setError]=useState('');
const [prepared,setPrepared]=useState(false);
function next(){
if(current===0&&!name.trim()){setError('Enter a workspace name.');return;}
setError('');setCurrent(n=>Math.min(2,n+1));
}
return <main style={{maxWidth:760,margin:'auto',padding:24,color:'var(--semi-color-text-0)'}}>
<h1>Workspace setup</h1>
<Steps type="basic" current={current} status={error?'error':'process'}>
<Steps.Step title="Name workspace"/>
<Steps.Step title="Choose updates"/>
<Steps.Step title="Review settings"/>
</Steps>
<section style={{padding:'24px 0'}}>
{current===0&&<><label htmlFor="workspace-name">Workspace name</label>
<Input id="workspace-name" value={name} onChange={setName}
validateStatus={error?'error':'default'} aria-invalid={!!error} aria-describedby="error" />
<p id="error" role="alert">{error}</p></>}
{current===1&&<><h2>Weekly digest</h2><p>Include a weekly activity summary in the local configuration.</p>
<Switch checked={digest} onChange={setDigest} aria-label="Weekly digest"/></>}
{current===2&&<><h2>Review your draft</h2><dl><dt>Workspace</dt><dd>{name}</dd>
<dt>Weekly digest</dt><dd>{digest?'Enabled':'Disabled'}</dd></dl>
<p>No workspace or notification subscription is created.</p></>}
</section>
{current>0&&<Button onClick={()=>{setCurrent(n=>n-1);setPrepared(false);}}>Previous</Button>}
{current<2 ? <Button theme="solid" type="primary" onClick={next}>Continue</Button> :
<Button theme="solid" type="primary" onClick={()=>setPrepared(true)}>Prepare configuration</Button>}
<p role="status">{prepared?'Configuration prepared locally. No account created.':''}</p>
</main>;
}
createRoot(document.getElementById('root')).render(<WorkspaceSetup />); 코드 참조
React 18 예제는 의도적으로 @douyinfe/semi-ui를 설치합니다. React 19에는 Quick Start에 설명된 -19 패키지가 필요합니다. 지원되는 번들러에서는 Semi 컴포넌트 JavaScript가 관련 CSS을 가져옵니다. 기본 설정에는 별도로 꾸며 낸 전역 스타일시트 단계가 필요하지 않습니다. 포함된 HTML 예제에는 명시적인 포커스 이동이 구현되어 있습니다. 제품에서 기본 컴포넌트 주변에 같은 동작을 적용하세요. 04
Semi Design 디자인 시스템 AI 에이전트 설정 구현 시작점 종속성 분기 하나를 선택하세요. 이 예제는 React 18을 사용합니다. 현재 Quick Start에 따르면 Vite/Webpack/Rspack에서는 컴포넌트 JavaScript가 관련 CSS을 가져옵니다. 테마 컴파일에는 추가 도구가 필요합니다.
bash 예제 복사
npm install react@18 react-dom@18 @douyinfe/semi-ui
# For a React 19 application instead:
# npm install react@19 react-dom@19 @douyinfe/semi-ui-19 프로젝트를 위한 프롬프트 에이전트 프롬프트 프롬프트 복사
Semi 기본 Steps와 제어되는 Input 및 Switch를 사용하세요. 설치한 React의 메이저 버전에 맞는 React 패키지를 선택하세요. 다음 단계로 이동하기 전에 검증하고, 이전 단계로 돌아가도 데이터를 유지하며, 존재하지 않는 계정 생성 결과를 꾸며 내지 말고 최종 로컬 구성을 제시하세요. 05
Semi Design 디자인 시스템의 출처와 범위 독립적인 OpenDesign 참고 자료입니다. 원본 작업 공간 예제이며 계정이나 알림 구독은 생성되지 않습니다.