Twilio Paste 디자인 시스템: 문서화 포크와 혼동하지 않고 업스트림 시스템 사용하기
Twilio 소스와 독립적인 후속 프로젝트
Paste는 twilio-labs 저장소에서 공개됩니다. 확인 과정에서 기존 paste.twilio.design 문서 경로는 해당 저장소로 리디렉션되었습니다. 별도로 호스팅되는 Paste DSys 사이트는 Twilio와 관계없는 독립 포크라고 설명합니다. 따라서 이 가이드의 토큰 값과 컴포넌트 동작은 업스트림 소스 파일을 기준으로 합니다.
알림 작성 도구는 정적인 버튼 모음으로는 담아낼 수 없는 여러 상태를 보여 주는 유용한 예시입니다. 편집 가능한 콘텐츠, 검토 확인, 준비된 스냅샷, 전송 전에 명확히 구분된 경계가 이에 해당합니다. 이 미리보기에서는 Twilio API를 호출하지 않습니다.
space30은 0.5rem이고 space70은 1.5rem입니다. 30과 70은 척도에서의 위치를 나타내는 접미사이지 30px와 70px를 뜻하지 않습니다. 루트 크기가 16px일 때 작성 도구는 레이블과 필드 사이에 8px, 컨트롤 내부에 12px, 영역 사이에 24px를 사용할 수 있습니다.
YAML 소스에서는 하이픈이 포함된 이름을 사용합니다. 레퍼런스 표에는 Paste 사용자가 쓰는 JavaScript 방식의 이름과 해당 이름에 대응하는 해석값이 함께 표시되어 있습니다. rem 단위 값은 루트 글꼴 크기에 따라 달라지므로, 이에 대응하는 픽셀 값을 브라우저에서 항상 동일하게 측정되는 값으로 간주해서는 안 됩니다.
글꼴 크기와 줄 높이 별칭은 서로 별개입니다. fontSize30은 기본 루트에서 14px이고 lineHeight30은 20px입니다. fontSize70은 24px이며 줄 높이 옵션은 32px입니다. 이러한 조합은 레이블과 여러 줄 콘텐츠를 읽기 쉽게 하면서 모든 섹션이 커다란 마케팅용 제목처럼 보이지 않도록 합니다.
내장된 예시에서는 시스템 산세리프 글꼴 스택과 애플리케이션 자체의 휴대폰 일러스트를 사용합니다. 두 요소 모두 설명을 위한 예시입니다. 독점 글꼴 파일은 재배포하지 않으며, 휴대폰 프레임 크기를 Paste 토큰으로 제시하지 않습니다.
업스트림 색상 소스에는 역할별 대비 조합이 기록되어 있습니다. 기본 텍스트, 보조 텍스트, 오류 메시지, 성공 메시지는 각각 의도된 전경색 역할이 다릅니다. 약한 텍스트 역할에는 일반 활성 컨트롤에 사용하지 말라는 경고가 있습니다. 흐린 글자 수 표시라고 해서 사용 가능한 회색 중 가장 옅은 색을 적용해서는 안 됩니다.
예시에서는 파란색으로 동작을 강조하고 어두운 중성 텍스트로 메시지를 전달합니다. 사용자가 버튼을 눌렀다고 준비된 초안이 녹색으로 바뀌지는 않습니다. 상태 메시지는 로컬 스냅샷이 생성되었음을 설명합니다. 예시의 값은 연결된 팔레트에 따른 것이며, 다른 테마 변형에서는 다르게 표시될 수 있습니다.
Theme은 Provider와 Consumer, 명명된 테마 객체와 유틸리티를 내보냅니다. 현재 변형 상수에는 default, dark, twilio, twilio-dark, sendgrid, evergreen이 포함됩니다. 이 예제는 의도적으로 default와 dark 사이에서만 전환합니다.
애플리케이션에서 관리하는 기본 컨트롤은 Provider가 변경될 때 이에 맞는 표면 스타일이 필요합니다. Provider는 Paste 컴포넌트에 테마를 적용할 수 있지만, 모든 외부 위젯의 스타일을 자동으로 바꾸지는 않습니다. 제공된 코드는 주변의 전경색과 배경색을 명시적으로 설정하고, textarea가 애플리케이션에서 관리하는 컨트롤임을 밝힙니다.
실시간 미리보기에는 현재 textarea 값이 반영됩니다. 준비된 문구는 별도로 저장하며, 유효성 검사를 마친 뒤에만 변경됩니다. 다시 편집하더라도 이전에 준비한 스냅샷이 조용히 덮어써져서는 안 됩니다. 검토 확인란은 로컬에서 동작을 보여 주기 위한 것이며, 수신자의 동의나 법적 준수를 입증하지 않습니다.
Twilio Paste 디자인 시스템 휴대폰 모형을 해석하지 않아도 이해할 수 있는 피드백 제공
일러스트 외부에 라벨과 텍스트 피드백 표시
textarea에는 눈에 보이는 라벨이 있으며, 글자 수 및 오류 설명과 연결되어 있습니다. 글자 수는 유니코드 코드 포인트를 기준으로 하며, SMS 분할 방식이나 인코딩, 비용을 측정한다고 주장하지 않습니다. 준비된 결과도 예시용 기기 외부에 일반 텍스트로 표시됩니다.
유효성 검사에서 메시지가 비어 있거나 검토 확인이 누락된 경우 이를 알려야 합니다. 상태 영역은 메시지가 전달된 것처럼 가장하지 않고 로컬 처리 결과를 알립니다. 좁은 뷰포트에서도 모든 기본 컨트롤과 버튼의 키보드 포커스가 보입니다.
설정에는 실제 Paste Theme 및 Button 패키지를 불러오며, 완전한 React 구성을 제공합니다. 기본 폼 컨트롤은 검증되지 않은 컴포넌트 API의 기능이라고 잘못 설명하지 않고 애플리케이션에서 관리한다고 명시합니다. 포함된 버전은 외부 CDN에 의존하지 않는 오프라인 HTML 해석입니다.
서비스에 사용하기 전에 peer dependencies를 해결하고 기본 예제를 빌드한 다음, 메시지를 전송할 실제 백엔드 경계를 추가하세요. 로컬 미리보기 테스트가 성공해도 편집기 동작만 확인된 것이며, 프로덕션 메시징 연동이나 Twilio 전송을 입증하는 것은 아닙니다.
휴대폰 패널에는 초안 스냅샷이 표시됩니다. SMS는 전송되지 않습니다. 기본 Paste Theme 및 Button 동작은 별도의 React 예제가 필요합니다.
실제 Paste 테마와 버튼 상태를 적용한 로컬 초안
Theme.Provider가 작성기 전체를 감쌉니다. secondary의 pressed 상태는 미리보기 테마를 바꾸고, primary 제출 버튼은 애플리케이션 유효성 검사를 마친 뒤 스냅샷을 준비합니다. 라벨, textarea, 확인란은 기본 애플리케이션 컨트롤임을 명시합니다.
jsx
// npm install @twilio-paste/button @twilio-paste/theme react react-dom
import React, {useState} from 'react';
import {createRoot} from 'react-dom/client';
import {Theme} from '@twilio-paste/theme';
import {Button} from '@twilio-paste/button';
// Native textarea and labels are application-owned; this is not Paste TextArea.
function Composer() {
const [message,setMessage] = useState('Your appointment is confirmed for Thursday at 10:00.');
const [snapshot,setSnapshot] = useState('');
const [error,setError] = useState('');
const [confirmed,setConfirmed] = useState(false);
const [mode,setMode] = useState('default');
const length = Array.from(message).length;
const background = mode === 'dark' ? '#121c2d' : '#ffffff';
const foreground = mode === 'dark' ? '#ffffff' : '#121c2d';
function prepare(event) {
event.preventDefault();
if (!message.trim()) return setError('Write a message before preparing a draft.');
if (!confirmed) return setError('Confirm that you reviewed the message.');
setError(''); setSnapshot(message.trim());
}
return <Theme.Provider theme={mode}>
<main style={{padding:24,background,color:foreground,maxWidth:760,margin:'auto'}}>
<h1>Notification draft</h1>
<Button variant="secondary" pressed={mode==='dark'} onClick={() => setMode(mode==='dark'?'default':'dark')}>Dark preview</Button>
<form onSubmit={prepare}>
<label htmlFor="message" style={{display:'block',marginTop:24}}>Message</label>
<textarea id="message" rows={5} value={message} onChange={e=>{setMessage(e.target.value);setConfirmed(false);}}
aria-describedby="count error" aria-invalid={!!error}
style={{width:'100%',padding:12,margin:'8px 0',font:'inherit',borderRadius:4}} />
<p id="count">{length} Unicode code points. This is not an SMS segment estimate.</p>
<label><input type="checkbox" checked={confirmed} onChange={e=>setConfirmed(e.target.checked)} /> I reviewed this draft</label>
<p id="error" role="alert">{error}</p>
<Button variant="primary" type="submit">Prepare local draft</Button>
</form>
<section aria-label="Prepared draft" style={{marginTop:24}}>
<h2>Prepared copy</h2>
<p style={{whiteSpace:'pre-wrap'}}>{snapshot || 'No draft prepared yet.'}</p>
<p role="status">{snapshot ? 'Draft prepared locally. Nothing was sent.' : ''}</p>
</section>
</main>
</Theme.Provider>;
}
createRoot(document.getElementById('root')).render(<Composer />);
Paste Theme.Provider와 Button을 사용해 알림 초안 편집기를 만드세요. secondary pressed 토글 동작, rem 간격, 출처가 확인된 텍스트 역할, 분리된 초안 및 스냅샷 상태를 유지하세요. SMS 분할 수나 전송 결과를 임의로 만들어 내지 마세요.
05
Twilio Paste 디자인 시스템 출처와 범위
상위 Paste를 독립적으로 참조하는 OpenDesign입니다. Paste DSys는 별도의 비제휴 포크입니다. 이 예제에서는 메시지를 전송하지 않습니다.