금융 기술 · 새 리소스

SumUp Circuit 디자인 시스템.

정확한 시맨틱 토큰, 네이티브 유효성 검사 props, 완성된 판매자 상품 편집기, 고객 측 미리보기 그림을 제공하는 Circuit 가이드입니다.

OpenDesign 가이드8개 챕터참조 항목 39개독자적 적용 가이드
01

SumUp Circuit 디자인 시스템 인터페이스 미리보기

형식이 잘못된 금액을 입력하고, 상품명을 바꾸고, 메모 입력란을 전환한 다음 로컬 스냅샷을 확인하세요.

상품을 수정하고 고객에게 표시되는 미리보기를 확인하세요전체 예시 열기
@sumup/circuit-ui 8.15.0 및 @sumup/design-tokens 7.3.1의 라이트 CSS를 기본으로 사용한 독립적인 로컬 상품 편집기. · 구현 레퍼런스
02

SumUp Circuit 디자인 시스템 디자인 참고 자료

@sumup/circuit-ui 8.15.0 및 @sumup/design-tokens 7.3.1의 라이트 CSS를 기본으로 사용한 독립적인 로컬 상품 편집기.

판매자용 라이트 테마의 배경과 텍스트

출처
이름 / 규칙값 / 구성용도
--cui-bg-normal#fff판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-bg-subtle#f0f1f5 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-bg-strong#000판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-bg-accent-strong#0f131a 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-fg-normal#0f131a 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-fg-subtle#6a737c 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-fg-on-strong#fff판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-fg-success#018850 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-fg-danger#de331d 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.
--cui-border-normal#aeb6be 판매자용 라이트 테마의 시맨틱 참고 자료입니다. 배경색을 전경색으로 사용하기 전에 의도된 색상 조합인지 확인하세요.

간격 단위

출처
이름 / 규칙값 / 구성용도
--cui-spacings-bit4px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-byte8px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-kilo12px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-mega16px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-giga24px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-tera32px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-peta40px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-exa48px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.
--cui-spacings-zetta56px고정된 CSS 내보내기 파일에서 가져온 명명된 간격 단계입니다.

모서리 반경

출처
이름 / 규칙값 / 구성용도
--cui-border-radius-bit4px컨트롤이나 배경의 역할에 맞춰 모양을 사용하세요.
--cui-border-radius-byte8px컨트롤이나 배경의 역할에 맞춰 모양을 사용하세요.
--cui-border-radius-kilo12px컨트롤이나 배경의 역할에 맞춰 모양을 사용하세요.
--cui-border-radius-mega16px컨트롤이나 배경의 역할에 맞춰 모양을 사용하세요.
--cui-border-radius-circle100%컨트롤이나 배경의 역할에 맞춰 모양을 사용하세요.
--cui-border-radius-pill999999px컨트롤이나 배경의 역할에 맞춰 모양을 사용하세요.

글꼴 모음 및 굵기

출처
이름 / 규칙값 / 구성용도
--cui-font-stack-defaultaktiv-grotesk, Helvetica, Arial, system-ui, sans-serif, "Segoe UI", Roboto, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"이 예제는 사용 가능한 대체 글꼴을 사용하며 Aktiv Grotesk를 가져오지 않습니다.
--cui-font-stack-monoMenlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace이 예제는 사용 가능한 대체 글꼴을 사용하며 Aktiv Grotesk를 가져오지 않습니다.
--cui-font-weight-regular400이 예제는 사용 가능한 대체 글꼴을 사용하며 Aktiv Grotesk를 가져오지 않습니다.
--cui-font-weight-bold700이 예제는 사용 가능한 대체 글꼴을 사용하며 Aktiv Grotesk를 가져오지 않습니다.

기본 동작 상태

출처
이름 / 규칙값 / 구성용도
--cui-bg-accent-strong#0f131a 기본, 호버, 눌림, 비활성화 상태를 각각 유지하세요.
--cui-bg-accent-strong-hovered#3b3f46 기본, 호버, 눌림, 비활성화 상태를 각각 유지하세요.
--cui-bg-accent-strong-pressed#6a737c 기본, 호버, 눌림, 비활성화 상태를 각각 유지하세요.
--cui-bg-accent-strong-disabledrgba(15, 19, 26, .4)기본, 호버, 눌림, 비활성화 상태를 각각 유지하세요.

입력 및 버튼의 공개 props

출처
이름 / 규칙값 / 구성용도
Input.labelrequired string필드의 용도를 표시합니다.
Input.invalidboolean기본 제공되는 잘못된 입력 스타일과 접근성 상태입니다.
Input.validationHintstring컨트롤 아래에 구체적인 안내를 표시합니다.
Button.variantprimary / secondary / tertiary이 고정 버전의 동작 우선순위입니다.
Button.sizes / m버전 8.15.0의 현재 크기 값입니다.
Button.stretchboolean로컬 검토 동작에 부모 너비를 적용합니다.
03

SumUp Circuit 디자인 시스템 전체 가이드

실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.

DESIGN-sumup-circuit.md

완전한 안내와 구현 시작점, 소스 링크.

가이드 다운로드

SumUp Circuit 디자인 시스템 판매자 편집기 구성

판매자 입력과 고객에게 표시되는 화면을 분리하세요

상품 편집기와 영수증 형태의 미리보기는 동일한 상태를 두 가지 방식으로 보여줍니다. 간단한 양식에서 상품명을 입력하고 예시 금액을 설정한 뒤 고객용 메모 입력란의 표시 여부를 선택합니다. 미리보기에서 변경 사항을 확인할 수 있지만, 결제 화면을 만들거나 결제 정보를 요청하지는 않습니다.

이 OpenDesign 가이드에서

독창적인 상품 일러스트를 사용하세요

기하학적 프린트 이미지는 직접 제작한 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가 적용됩니다. 소스에는 입력 참조가 유지되어 처음 실패한 필드로 포커스를 되돌립니다. 실제 고객 정보나 카드 정보를 입력하지 않고도 오류 복구를 테스트할 수 있습니다.

  1. 상품명을 지운 뒤 제출해 첫 번째 필드의 오류를 확인하세요.
  2. 24abc 또는 0을 입력해 보고, 금액을 24.50으로 수정하세요.
  3. 로컬에서 검토한 다음 필드를 수정해 오래된 스냅샷을 지우세요.

일러스트와 정적 미리보기를 정확하게 설명하세요

이미지에는 짧은 역할 설명이 제공됩니다. 고객 메모 영역은 명확한 라벨이 있는 미리보기 안의 설명용 자리표시자이며, 편집 가능한 입력란처럼 꾸민 요소가 아닙니다. 실제 메모 설정 체크박스는 판매자 양식에 있으며, 미리보기 영역의 표시 여부를 제어합니다.

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 />);

코드 참조

  • Vite React 프로젝트를 만들고 <div id="root"></div>를 유지한 다음, 이 파일을 src/main.jsx로 불러오세요.

circuit.css — 기존 반응형 구성

기본 구성 요소를 중심으로 구성한 애플리케이션 레이아웃입니다.

CSS
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  background: var(--cui-bg-normal);
  color: var(--cui-fg-normal);
  font: 16px/1.5 var(--cui-font-stack-default);
}
.circuit-example {
  padding: 32px;
}
.circuit-example header {
  max-width: 720px;
  margin-bottom: 32px;
}
.eyebrow {
  font-size: 12px;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
  color: var(--cui-fg-subtle);
}
.circuit-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(300px, 1fr);
  gap: 48px;
}
.circuit-example h2 {
  font-size: 20px;
  font-weight: 700;
  margin: 0 0 24px;
}
.circuit-example form {
  max-width: 540px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.circuit-example form h2 {
  margin: 0;
}
.preview-surface {
  background: var(--cui-bg-subtle);
  padding: 28px;
  border-radius: 16px;
}
.preview-surface > h2 {
  font-size: 14px;
  color: var(--cui-fg-subtle);
  text-align: center;
}
.receipt {
  max-width: 340px;
  margin: auto;
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 20px #0000000d;
  padding: 24px;
}
.shop-mark {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #0f131a;
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  margin: auto;
}
.shop-name {
  text-align: center;
  font-size: 14px;
  margin: 12px 0 20px;
}
.print-art {
  height: 150px;
  background: #f5dfbb;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
}
.print-art i {
  position: absolute;
  left: 24px;
  bottom: 0;
  width: 100px;
  height: 130px;
  border-radius: 60px 60px 0 0;
  background: #ce663d;
}
.print-art b {
  position: absolute;
  right: 20px;
  top: 20px;
  width: 90px;
  height: 90px;
  border-radius: 50%;
  background: #385d50;
}
.print-art span {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 24px;
  background: #202e2a;
}
.receipt h3 {
  font-size: 20px;
  line-height: 1.3;
  margin: 20px 0 8px;
  overflow-wrap: anywhere;
}
.receipt-price {
  font-size: 28px;
  font-weight: 700;
  margin: 0 0 24px;
}
.note-placeholder {
  padding: 12px;
  border: 1px solid #bfc6cf;
  border-radius: 8px;
  margin-bottom: 16px;
  font-size: 12px;
}
.note-placeholder span {
  font-weight: 700;
}
.note-placeholder p {
  margin: 4px 0 0;
  color: #4f5a65;
}
.preview-action {
  background: #e9edf2;
  text-align: center;
  border-radius: 999px;
  padding: 12px;
  font-size: 12px;
  color: #4f5a65;
}
.review {
  padding: 20px;
  background: #e7f5ef;
  border-radius: 8px;
}
.review p {
  margin: 8px 0;
}
.review small {
  font-size: 12px;
}
.circuit-example footer {
  font-size: 12px;
  color: var(--cui-fg-subtle);
  margin-top: 32px;
}
@media (max-width: 850px) {
  .circuit-grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .circuit-example form {
    max-width: none;
  }
}
@media (max-width: 550px) {
  .circuit-example {
    padding: 20px 16px;
  }
  .preview-surface {
    padding: 20px;
  }
  .receipt {
    padding: 20px;
  }
}

코드 참조

  • 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 네임스페이스를 사용합니다.