상품 편집기와 영수증 형태의 미리보기는 동일한 상태를 두 가지 방식으로 보여줍니다. 간단한 양식에서 상품명을 입력하고 예시 금액을 설정한 뒤 고객용 메모 입력란의 표시 여부를 선택합니다. 미리보기에서 변경 사항을 확인할 수 있지만, 결제 화면을 만들거나 결제 정보를 요청하지는 않습니다.
독창적인 상품 일러스트를 사용하세요
기하학적 프린트 이미지는 직접 제작한 CSS 그래픽이며 접근성 설명을 포함합니다. 가짜 판매자 사진이나 복사한 SumUp 상품 에셋 대신, 빈 이미지 영역이 아닌 알아보기 쉬운 사물을 고객 미리보기에 표시합니다.
SumUp Circuit 디자인 시스템 시맨틱 테마 및 패키지 범위
고정된 테마를 정확히 사용하세요
이 예제는 @sumup/circuit-ui 8.15.0과 @sumup/design-tokens 7.3.1을 사용합니다. 참고 표는 해당 패키지의 light.css에서 가져옵니다. 최신 업스트림 문서는 @sumup-oss 네임스페이스로 옮겨갔습니다. 이는 재현 가능한 고정 버전 통합 예제이며, 이전 네임스페이스가 최신 릴리스라는 의미는 아닙니다.
컴포넌트 스타일과 토큰 스타일을 불러오세요
React 항목은 컴포넌트 스타일시트와 라이트 토큰 파일을 모두 가져옵니다. CSS 사용자 지정 속성이 정의되지 않은 경우 컴포넌트 클래스 이름만으로는 충분하지 않습니다. 범위를 지정한 다크 팔레트를 사용하려면 공유 색상 외 값도 제공하는 완전한 기본 테마가 필요합니다.
SumUp Circuit 디자인 시스템 중립 배경 및 동작 대비
시각적 초점은 상품에 두세요
편집기에는 흰색 배경과 어두운 전경을 사용하고, 고객 미리보기에는 은은한 중립 배경을 적용합니다. 상품 이미지에 담긴 독창적인 그래픽은 색상을 절제해 사용하므로, 기본 제공되는 주요 동작 버튼을 쉽게 읽고 찾을 수 있습니다.
미리보기 동작이 실제로 작동하지 않음을 분명히 표시하세요
고객 화면 하단에는 결제가 곧 진행될 것처럼 보이는 비활성화된 결제 버튼 대신 ‘미리보기 전용’이라는 텍스트 블록이 표시됩니다. 실제 제출 동작은 편집기에만 있으며, 로컬 상품을 검토하는 데 사용됩니다. 이를 통해 예제의 실제 상호작용 범위를 명확히 알 수 있습니다.
SumUp Circuit 디자인 시스템 타이포그래피 및 대체 글꼴
테마의 글꼴 스택을 있는 그대로 안내하세요
공개된 글꼴 스택은 Aktiv Grotesk로 시작해 Helvetica, Arial 및 시스템 대체 글꼴을 포함합니다. 이 오프라인 예제는 첫 번째 글꼴을 내려받지 않습니다. 기본 제공되는 Headline 및 Body 컴포넌트는 의도한 위계를 표현하지만, 최종 글자 모양은 사용 가능한 글꼴에 따라 달라집니다.
금액과 통화를 함께 표시하세요
SumUp Circuit 디자인 시스템 간격 및 둥근 배경
명명된 단계 순서를 사용하세요
토큰 크기에는 bit, byte, kilo, mega 등의 이름이 사용됩니다. 이 이름은 디자인 라벨이며 2의 거듭제곱을 계산하는 방식이 아닙니다. 표에는 정확한 픽셀 값이 나와 있으므로 이름의 비유를 바탕으로 임의의 크기 체계를 만들지 않아도 됩니다.
위계를 유지하면서 컨트롤의 가장자리를 정렬하세요
양식에는 일정한 세로 간격을 적용하고 주요 동작 버튼은 전체 너비로 표시합니다. 미리보기에는 크게 둥근 바깥 배경과 그보다 작은 영수증 영역을 사용합니다. 휴대전화에서는 양식 다음에 미리보기가 오며, 컨트롤을 좁히기 전에 패딩을 줄입니다.
SumUp Circuit 디자인 시스템 상품 검증 및 초안 상태
서식을 적용하기 전에 입력 문자열 전체를 검증하세요
애플리케이션은 1~5자리 정수와 최대 소수점 이하 두 자리로 이루어진 양수만 허용합니다. 이는 이 예제에서 정한 규칙입니다. 부분 문자열을 허용하는 parseFloat 때문에 24abc와 같은 값이 입력되는 일을 방지하며, 제출 후 처음으로 유효하지 않은 기본 Input에 포커스를 둡니다.
입력이 변경되면 이전 검토 결과를 모두 지우세요
상품명, 금액, 메모 표시 여부가 바뀌면 이전 스냅샷은 더 이상 유효하지 않습니다. 검토가 완료된 상태에는 상품명과 금액이 포함되므로 구체적인 초안에 연결됩니다. 이 코드는 결과를 백엔드에 저장하거나 결제 요청을 만들지 않습니다.
SumUp Circuit 디자인 시스템 입력 복구 및 미리보기 동작
두 필드의 오류를 모두 확인하세요
상품명과 가격 필드에는 기본 제공되는 필수 입력 라벨, 잘못된 입력 상태 및 validationHint가 적용됩니다. 소스에는 입력 참조가 유지되어 처음 실패한 필드로 포커스를 되돌립니다. 실제 고객 정보나 카드 정보를 입력하지 않고도 오류 복구를 테스트할 수 있습니다.
상품명을 지운 뒤 제출해 첫 번째 필드의 오류를 확인하세요.
24abc 또는 0을 입력해 보고, 금액을 24.50으로 수정하세요.
로컬에서 검토한 다음 필드를 수정해 오래된 스냅샷을 지우세요.
일러스트와 정적 미리보기를 정확하게 설명하세요
이미지에는 짧은 역할 설명이 제공됩니다. 고객 메모 영역은 명확한 라벨이 있는 미리보기 안의 설명용 자리표시자이며, 편집 가능한 입력란처럼 꾸민 요소가 아닙니다. 실제 메모 설정 체크박스는 판매자 양식에 있으며, 미리보기 영역의 표시 여부를 제어합니다.
SumUp Circuit 디자인 시스템 React 및 CSS 통합
공개 피어 의존성과 두 스타일시트를 모두 포함하세요
이 예제는 React 18 및 고정된 Circuit 컴포넌트를 사용하며, 토큰·아이콘·국제화·Emotion 피어 의존성이 패키지 요구사항과 일치합니다. 코드에서 light.css와 styles.css를 명시적으로 가져옵니다. 문서화되지 않은 프로바이더나 프로젝트 수준의 숨겨진 테마 설정에 의존하지 않습니다.
@sumup/circuit-ui 8.15.0 컴포넌트 스타일입니다.
@sumup/design-tokens 7.3.1 라이트 테마 전체입니다.
React 18 및 컴포넌트 패키지에 선언된 피어 의존성입니다.
실제 애플리케이션에서만 결제 서비스를 추가하세요
SumUp Circuit 디자인 시스템 컴포넌트 예제
main.jsx — 완전히 작동하는 예제
항목을 수정하고 고객에게 표시되는 미리보기를 확인하세요. 아래 소스는 모든 상태와 유효성 검사를 포함한 React 전체 예제입니다.
jsx
import React, { useState, useRef } from "react";
import { createRoot } from "react-dom/client";
import { Input, Checkbox, Button, Headline, Body } from "@sumup/circuit-ui";
import "@sumup/design-tokens/light.css";
import "@sumup/circuit-ui/styles.css";
import "./circuit.css";
function App() {
const [name, setName] = useState("Studio print"),
[price, setPrice] = useState("24.00"),
[note, setNote] = useState(true),
[errors, setErrors] = useState({}),
[review, setReview] = useState(null);
const nameRef = useRef(),
priceRef = useRef();
const valid = /^\d{1,5}(\.\d{1,2})?$/.test(price) && Number(price) > 0;
const amount = valid
? new Intl.NumberFormat("en-IE", {
style: "currency",
currency: "EUR",
}).format(Number(price))
: "—";
function change(fn) {
fn();
setReview(null);
setErrors({});
}
function submit(e) {
e.preventDefault();
const next = {};
if (!name.trim()) next.name = "Enter an item name.";
if (!valid)
next.price = "Use a positive amount with up to two decimal places.";
setErrors(next);
if (next.name) {
nameRef.current.focus();
return;
}
if (next.price) {
priceRef.current.focus();
return;
}
setReview({ name: name.trim(), amount, note });
}
return (
<main className="circuit-example">
<header>
<p className="eyebrow">MERCHANT TOOLS / LOCAL SPECIMEN</p>
<Headline as="h1">Prepare a simple item</Headline>
<Body>
Review how an item could appear to a customer. This example never
creates a payment link.
</Body>
</header>
<div className="circuit-grid">
<form onSubmit={submit} noValidate>
<h2>Item details</h2>
<Input
ref={nameRef}
label="Item name"
required
value={name}
maxLength={80}
invalid={!!errors.name}
validationHint={
errors.name || "Use a short name the customer can recognize."
}
onChange={(e) => change(() => setName(e.target.value))}
/>
<Input
ref={priceRef}
label="Price in EUR"
required
inputMode="decimal"
value={price}
invalid={!!errors.price}
validationHint={
errors.price || "Example amount only; no charge will be made."
}
onChange={(e) => change(() => setPrice(e.target.value))}
/>
<Checkbox
label="Show a customer note field"
checked={note}
onChange={(e) => change(() => setNote(e.target.checked))}
/>
<Button variant="primary" type="submit" stretch>
Review item locally
</Button>
{review && (
<div className="review" role="status">
<strong>Item reviewed</strong>
<p>
{review.name} · {review.amount}
</p>
<small>
Local snapshot only. No payment link or charge created.
</small>
</div>
)}
</form>
<section className="preview-surface" aria-labelledby="preview-heading">
<h2 id="preview-heading">Customer-side preview</h2>
<div className="receipt">
<div className="shop-mark" aria-hidden="true">
N
</div>
<p className="shop-name">Northstar Studio</p>
<div
className="print-art"
role="img"
aria-label="Original geometric print illustration"
>
<i></i>
<b></b>
<span></span>
</div>
<h3>{name.trim() || "Your item name"}</h3>
<p className="receipt-price">{amount}</p>
{note && (
<div className="note-placeholder">
<span>Customer note</span>
<p>A note field would appear here.</p>
</div>
)}
<div className="preview-action">
Preview only · checkout unavailable
</div>
</div>
</section>
</div>
<footer>
Native Circuit UI 8.15.0 components and design tokens 7.3.1. Original
item editor and illustration by OpenDesign.
</footer>
</main>
);
}
createRoot(document.getElementById("root")).render(<App />);
main.jsx와 같은 위치에 저장하세요. 이 사용자 지정 레이아웃 규칙은 라이브러리 토큰 참조와 구분됩니다.
04
SumUp Circuit 디자인 시스템 AI 에이전트 설정
구현 시작점
고정된 기본 예제를 번들링한 뒤 로컬 브라우저에서 확인했습니다. 이 예제는 로컬 애플리케이션 상태만 사용합니다.
sh
npm create vite@latest circuit-item -- --template react
cd circuit-item
npm install
npm install [email protected][email protected] @sumup/[email protected] @sumup/[email protected] @sumup/icons @sumup/intl@1 @emotion/react @emotion/styled @emotion/is-prop-valid
# Replace src/main.jsx and add src/circuit.css.
npm run dev
프로젝트를 위한 프롬프트
에이전트 프롬프트
고정된 기본 컨트롤과 필수 스타일시트 두 개를 사용해 Circuit 항목 편집기를 만드세요. 금액 문자열 전체를 검증하고 통화 형식을 유지하며, 수정 후에는 이전 로컬 검토 내용을 지우고 고객용 미리보기를 실제 결제 화면과 분명히 구분하세요. 기존 일러스트와 의미에 맞는 토큰 역할을 정확히 사용하세요.
05
SumUp Circuit 디자인 시스템의 출처와 범위
OpenDesign 디자인 시스템 애플리케이션 가이드는 고정된 Circuit 패키지 세대를 기준으로 합니다. 일러스트, 금액, 항목은 예시입니다. 이 로컬 편집기는 결제 링크를 만들거나 결제를 진행하지 않으며 SumUp 계정에 어떤 작업도 수행하지 않습니다. 현재 업스트림 패키지는 새 @sumup-oss 네임스페이스를 사용합니다.