Porsche
회색 구성기 무대의 낮고 긴 911, 실제 페인트 이름·가격·선택선과 4px 사각 PDS 버튼
Brand DNA
브랜드 DNA
- 브랜드명: Porsche (포르쉐, Porsche Design System).
- 한 줄 정체성: 정밀한 자동차의 형태를 큰 무대에 놓고, 구매에 필요한 선택과 비용을 차분한 무채색 인터페이스로 설명한다.
- 공식 디자인 철학: Porsche는 공개 디자인 시스템의 목적을 일관되고 직관적인 디지털 제품, 여러 접점에서 이어지는 경험, 읽기 쉬운 글자와 충분한 상호작용 크기로 설명한다. 이 문서는 그 설명을 구성기의 선택·확인 흐름에 적용한다. 근거는 공식 PDS와 2020년 Porsche Newsroom의 디자인 시스템 소개다.
- 시그니처 요소 1개: 낮게 흐르는 911의 패스트백을 넓은 회색 무대에 놓고, 그 아래 실제 도장 이름·추가 비용과 검정/흰색 PDS 버튼을 정렬한 구성기.
기준 범위는 PDS v3.35.0이다. 이 버전은 2026년 8월 28일 공개되었으며, p-button의 theme 속성과 Light/Dark 토큰을 함께 확인할 수 있다. 별도 메이저인 v4.0.0은 2026년 4월 29일 공개되었다. v3 계열의 후속 릴리스가 더 늦게 나왔으므로 날짜만 보고 최신 메이저와 같은 API라고 판단하지 않는다. 앞머리의 마지막 메이저 연도는 v4.0.0의 공개일을 근거로 2026으로 쓴다. 최초 공개 연도 2020은 당시 공식 소개글에서 공개 시스템의 존재를 확인한 연도이며, 첫 출시일과 일치하는지는 확인하지 못했으므로 (추정)이다.
토큰의 출처 유형은 official_docs, 공개 여부는 is_official: true다. 색·서체·간격·모서리·그림자·모션·버튼 속성은 공식 문서와 같은 버전의 소스를 기준으로 한다. 화면 내용은 미국 2027 911 Carrera 구성기를 2026-10-12에 관찰했다. 따라서 미국 가격과 hp·mph를 사용한다. 국제 페이지의 PS·km/h와 미국 달러 가격을 한 표에서 아무 설명 없이 섞지 않는다. 제품 화면의 열 배치와 단계 흐름을 룩북 창에 맞게 압축한 치수는 (추정)이며, 공개 PDS의 규격으로 소개하지 않는다.
카드의 대표 이미지는 공식 992 측면 렌더에서 지붕·앞뒤 바퀴 중심·한 장짜리 도어·후면 유리의 좌표를 따서 SVG로 다시 그렸다. 앞 펜더 위의 비스듬한 헤드램프, 길게 뒤로 내려오는 지붕, 뒷바퀴 위의 넓은 어깨, 얇은 후미등, 작은 매립형 손잡이를 따로 그렸다. 바닥 그림자·타이어·디스크·살·차체·유리·반사·램프·흡입구가 서로 다른 겹이다. 정측면에서 잘 보이지 않는 둥근 헤드램프와 가로 라이트바는 작은 정면·후면 그림에서 보완한다. 도장에 준 반사광과 붉은 hex는 사진을 보고 정한 (추정)이며 공식 페인트 배합값이 아니다.
Tone & Mood
톤 & 무드
- 핵심 키워드 3개: 정밀한 · 절제된 · 역동적인.
- 무드 설명: 큰 이미지가 먼저 차의 자세를 보여 주고, 가는 선과 규칙적인 간격이 선택지를 정리한다. UI에서 가장 강한 대비는 다음 행동과 선택된 항목에 쓴다. 도장 색은 차체와 페인트 선택에만 넓게 나타난다.
- 비주얼 스타일: 모던 미니멀 (
modern-minimal). - 밀도(Density): Comfortable. 선택지 안은 이름·규격·가격을 충분히 담고, 서로 다른 선택 묶음 사이에 여유를 둔다.
- 모서리 성향: Soft. 상호작용 기본은 4px, 보조 컨테이너는 8px, 큰 영역은 12px다. 작은 사각 버튼의 긴 수평선이 먼저 보이게 한다.
- 평면성: Subtle. 대부분은 면과 얇은 경계로 구분하고, 떠 있는 레이어에만 그림자를 준다.
이 판의 기본은 Light다. 흰 Base와 옅은 Surface가 차의 윤곽을 분명히 보여 준다. 공식 Dark 토큰과 명시적 테마 선택도 확인했으므로 theme_modes는 [light, dark]다. PDS 문서의 전환 기능과 두 토큰 세트가 근거이며, 단순히 어두운 자동차 사진이 있다는 이유로 다크를 추가한 것이 아니다.
절제는 내용을 덜 쓰는 방식으로 만들지 않는다. 실제 구성기는 차종·연식·기술 정보·저장·요약·가격·선택 상태를 한 화면에 놓는다. 위계는 글자 크기, 열의 정렬, 배경의 작은 차이로 만든다. 카드에서는 자동차가 화면 폭의 대부분을 차지하고 견본 아래에 추가 비용이 이어진다. 상세에서는 왼쪽 자동차와 오른쪽 선택 목록이 같은 수평선에서 시작한다. 이 관계가 유지되어야 축소해도 전시장 광고와 구별된다.
제품 그림에는 부드러운 반사와 깊은 유리를 쓰고, UI에는 모호한 광택을 얹지 않는다. 표의 숫자는 같은 기준선에 놓으며 통화 기호와 천 단위 쉼표를 생략하지 않는다. 제목의 좁은 폭과 일정한 획은 Porsche Next의 특징을 따르지만, 시스템 대체 글꼴에서 잘리는 폭을 고정하지 않는다. 모델명은 가볍게, 현재 단계와 선택 상태는 600 정도로 구분한다. 모든 제목을 700으로 채우면 기술 사양 표와 차량 이름의 위계가 사라진다.
Color System
컬러 시스템 (CSS 변수)
PDS는 일반적인 브랜드색 50–900 스케일보다 역할 이름을 중심으로 색을 배포한다. 다음 표가 공식 값이고, 아래 CSS의 --color-primary-* 번호는 룩북 공통 형식을 위한 (추정) 별칭이다. 번호 사이를 보간해 새로운 색을 공식 색처럼 만들지 않았다. 동일한 역할 값이 여러 번호에 대응할 수 있다. 실제 화면은 --text-primary, --bg-base, --border-default처럼 의미가 분명한 이름을 쓴다.
| PDS v3.35.0 역할 | Light | Dark | 적용 위치 | |---|---|---|---| | Primary | #010205 | #FBFCFF | 본문, 모델명, 주요 버튼 면 | | Background Base | #FFFFFF | #0E0E12 | 페이지와 선택 영역 | | Background Surface | #EEEFF2 | #212225 | 차량 무대, 선택 보조 면 | | Background Shading | rgba(1,2,5,.67) | rgba(38,38,41,.67) | 모달 뒤 차광 | | Background Frosted | hsl(240 4% 85% / 35%) | hsl(240 3% 26% / 35%) | 반투명 도구 배경 | | Contrast Low | #D8D8DB | #404044 | 구획선과 일반 경계 | | Contrast Medium | #6B6D70 | #88898C | 보조 상태와 중간 대비 | | Contrast High | #535457 | #AFB0B3 | 설명과 가격 보조 글 | | State Hover | rgba(148,149,152,.18) | 같은 값 | 항목 위에 포인터를 올린 상태 | | State Active | rgba(148,149,152,.20) | rgba(126,127,130,.20) | 누르는 순간의 면 | | State Focus | #1A44EA | 같은 값 | 키보드 포커스 | | State Disabled | #949598 | #7E7F82 | 사용 불가 컨트롤 |
| 알림 역할 | Light 전경 / 부드러운 배경 | Dark 전경 / 부드러운 배경 | |---|---|---| | Success | #197E10 / #E4FFEC | #09D087 / #003320 | | Warning | #F3BE00 / #FFF4D2 | #F7CB47 / #362B0A | | Error | #CC1922 / #FFE2E4 | #FC4040 / #3A0F0F | | Info | #2762EC / #D3E1FF | #178BFF / #04294E |
:root {
/* 번호 스케일은 룩북 호환 별칭(추정); 공식 역할 값만 재사용 */
--color-primary-50: #FFFFFF;
--color-primary-100: #EEEFF2;
--color-primary-200: #D8D8DB;
--color-primary-300: #949598;
--color-primary-400: #6B6D70;
--color-primary-500: #010205;
--color-primary-600: #010205;
--color-primary-700: #010205;
--color-primary-800: #010205;
--color-primary-900: #010205;
--color-success-fg: #197E10;
--color-success-bg: #E4FFEC;
--color-warning-fg: #F3BE00;
--color-warning-bg: #FFF4D2;
--color-error-fg: #CC1922;
--color-error-bg: #FFE2E4;
--color-info-fg: #2762EC;
--color-info-bg: #D3E1FF;
--bg-base: #FFFFFF; /* Background Base */
--bg-subtle: #EEEFF2; /* Background Surface */
--bg-elevated: #FFFFFF; /* 배경 역할 매핑(추정) */
--bg-overlay: #FFFFFF;
--bg-shading: rgba(1,2,5,.67);
--bg-frosted: hsl(240 4% 85% / 35%);
--text-primary: #010205;
--text-secondary: #535457;
--text-tertiary: #6B6D70;
--text-on-primary: #FBFCFF;
--text-disabled: #949598;
--border-default: #D8D8DB;
--border-subtle: #D8D8DB;
--border-strong: #010205;
--border-focus: #1A44EA;
--state-hover: rgba(148,149,152,.18);
--state-active: rgba(148,149,152,.20);
--state-disabled: #949598;
--font-family: 'Porsche Next', 'Arial Narrow', Arial, 'Heiti SC', SimHei, sans-serif;
--font-line-height: calc(6px + 2.125ex);
--font-weight-regular: 400;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--font-text-xx-small: .75rem;
--font-text-x-small: clamp(.81rem, .77rem + .23vw, .88rem);
--font-text-small: 1rem;
--font-text-medium: clamp(1.13rem, 1.08rem + .21vw, 1.33rem);
--font-text-large: clamp(1.27rem, 1.16rem + .51vw, 1.78rem);
--font-text-x-large: clamp(1.42rem, 1.23rem + .94vw, 2.37rem);
--font-heading-small: var(--font-text-small);
--font-heading-medium: var(--font-text-medium);
--font-heading-large: var(--font-text-large);
--font-heading-x-large: var(--font-text-x-large);
--font-heading-xx-large: clamp(1.6rem, 1.29rem + 1.56vw, 3.16rem);
--font-display-small: clamp(1.8rem, 1.32rem + 2.41vw, 4.21rem);
--font-display-medium: clamp(2.03rem, 1.31rem + 3.58vw, 5.61rem);
--font-display-large: clamp(2.28rem, 1.24rem + 5.2vw, 7.48rem);
}
[data-theme="dark"] {
/* 번호 스케일은 룩북 호환 별칭(추정); 공식 역할 값만 재사용 */
--color-primary-50: #0E0E12;
--color-primary-100: #212225;
--color-primary-200: #404044;
--color-primary-300: #7E7F82;
--color-primary-400: #88898C;
--color-primary-500: #FBFCFF;
--color-primary-600: #FBFCFF;
--color-primary-700: #FBFCFF;
--color-primary-800: #FBFCFF;
--color-primary-900: #FBFCFF;
--color-success-fg: #09D087;
--color-success-bg: #003320;
--color-warning-fg: #F7CB47;
--color-warning-bg: #362B0A;
--color-error-fg: #FC4040;
--color-error-bg: #3A0F0F;
--color-info-fg: #178BFF;
--color-info-bg: #04294E;
--bg-base: #0E0E12; /* Background Base */
--bg-subtle: #212225; /* Background Surface */
--bg-elevated: #0E0E12; /* 배경 역할 매핑(추정) */
--bg-overlay: #0E0E12;
--bg-shading: rgba(38,38,41,.67);
--bg-frosted: hsl(240 3% 26% / 35%);
--text-primary: #FBFCFF;
--text-secondary: #AFB0B3;
--text-tertiary: #88898C;
--text-on-primary: #010205;
--text-disabled: #7E7F82;
--border-default: #404044;
--border-subtle: #404044;
--border-strong: #FBFCFF;
--border-focus: #1A44EA;
--state-hover: rgba(148,149,152,.18);
--state-active: rgba(126,127,130,.20);
--state-disabled: #7E7F82;
}
[data-theme="light"] {
/* 번호 스케일은 룩북 호환 별칭(추정); 공식 역할 값만 재사용 */
--color-primary-50: #FFFFFF;
--color-primary-100: #EEEFF2;
--color-primary-200: #D8D8DB;
--color-primary-300: #949598;
--color-primary-400: #6B6D70;
--color-primary-500: #010205;
--color-primary-600: #010205;
--color-primary-700: #010205;
--color-primary-800: #010205;
--color-primary-900: #010205;
--color-success-fg: #197E10;
--color-success-bg: #E4FFEC;
--color-warning-fg: #F3BE00;
--color-warning-bg: #FFF4D2;
--color-error-fg: #CC1922;
--color-error-bg: #FFE2E4;
--color-info-fg: #2762EC;
--color-info-bg: #D3E1FF;
--bg-base: #FFFFFF; /* Background Base */
--bg-subtle: #EEEFF2; /* Background Surface */
--bg-elevated: #FFFFFF; /* 배경 역할 매핑(추정) */
--bg-overlay: #FFFFFF;
--bg-shading: rgba(1,2,5,.67);
--bg-frosted: hsl(240 4% 85% / 35%);
--text-primary: #010205;
--text-secondary: #535457;
--text-tertiary: #6B6D70;
--text-on-primary: #FBFCFF;
--text-disabled: #949598;
--border-default: #D8D8DB;
--border-subtle: #D8D8DB;
--border-strong: #010205;
--border-focus: #1A44EA;
--state-hover: rgba(148,149,152,.18);
--state-active: rgba(148,149,152,.20);
--state-disabled: #949598;
}
Primary라는 이름은 항상 검정을 뜻하지 않는다. Light의 Primary는 거의 검정이고 Dark에서는 거의 흰색이다. 버튼 안의 글자는 반대 테마의 Primary에 대응한다. 페이지 배경만 검게 바꾸고 검정 버튼을 그대로 남기면 행동 위계가 사라진다. 카드의 배경·면·선·주 글자·보조 글자·강조는 card_tokens의 여섯 값으로 모두 연결했다. 차량의 도장과 유리, 타이어는 상품 이미지의 재질이므로 테마에 따라 반전하지 않는다.
가격과 페인트는 다음 관찰값을 쓴다. Guards Red와 Gentian Blue Metallic은 Dreams에서 각각 $1,580, GT Silver Metallic은 Shades에서 $880, Chalk는 Legends에서 $3,160이다. 해당 연식의 미국 구성기에서는 Shark Blue를 확인하지 못했으므로 넣지 않았다. 스와치에 쓰인 붉은색·파란색·은색·회백색의 CSS 그라디언트는 화면 관찰을 바탕으로 한 (추정)이다. PDS의 의미 색 목록이나 자동차 실물 색의 정확한 색도값에 포함하지 않는다.
Typography
타이포그래피
- 영문 기본: Porsche Next. 공식 스택은
'Porsche Next', 'Arial Narrow', Arial, 'Heiti SC', SimHei, sans-serif다. 이 문서의 자체 렌더에서는 외부 글꼴을 불러오지 않으므로 설치된 글꼴에 따라 Arial Narrow 또는 Arial로 보인다. - 한글 대체:
'Malgun Gothic', sans-serif를 추가하는 방법은 (추정)이다. 확인한 공식 스택에 공인 한국어 가족이 없으므로font_korean_supported: false로 기록한다. 한글 안내 화면을 제작할 때는 숫자 폭과 혼합 문장의 줄 높이를 따로 확인한다. - 굵기: 공식 Regular 400, Semi-bold 600, Bold 700. Thin과 Italic은 공식 Typography 사용 지침에서 피하도록 안내한다.
- 줄 높이: 공식 기본
calc(6px + 2.125ex). 모든 단계에 고정 1.2를 덮지 않는다. 자간은 기본값을 유지한다. 예시의 큰 모델명-.5px는 제한된 창에서 시각 크기를 맞춘 (추정)이다.
| 위계 | PDS 이름과 크기 | 굵기 / 줄 높이 / 자간 | 쓰임 | |---|---|---|---| | Display | Display Small clamp(1.8rem, 1.32rem + 2.41vw, 4.21rem) | 400 / 공식 줄 높이 / normal | 큰 모델 소개와 수치 | | H1 | Heading XX Large clamp(1.6rem, 1.29rem + 1.56vw, 3.16rem) | 600 / 공식 줄 높이 / normal | 독립 구획 제목 | | H2 | Heading X Large clamp(1.42rem, 1.23rem + .94vw, 2.37rem) | 600 / 공식 줄 높이 / normal | 주요 섹션 제목 | | H3 | Heading Large clamp(1.27rem, 1.16rem + .51vw, 1.78rem) | 600 / 공식 줄 높이 / normal | 선택 묶음과 패키지 | | Body Large | Text Medium clamp(1.13rem, 1.08rem + .21vw, 1.33rem) | 400 / 공식 줄 높이 / normal | 짧은 소개 | | Body | Text Small 1rem | 400 / 공식 줄 높이 / normal | 기본 문장과 버튼 | | Body Small | Text X Small clamp(.81rem, .77rem + .23vw, .88rem) | 400 / 공식 줄 높이 / normal | 보조 문장 | | Caption | Text XX Small .75rem | 400 / 공식 줄 높이 / normal | 조건·소비 정보 |
더 큰 공식 Display Medium은 clamp(2.03rem, 1.31rem + 3.58vw, 5.61rem), Display Large는 clamp(2.28rem, 1.24rem + 5.2vw, 7.48rem)이다. 본문용 Text Large와 X Large는 각각 Heading Large와 X Large의 크기 식을 공유한다. Heading Small은 1rem, Heading Medium은 Text Medium과 같은 식을 사용한다. 위계의 차이는 크기만으로 생기지 않으며 굵기와 주변 간격을 함께 적용한다.
PDS의 기본 본문은 16px이며 반응형 크기는 최소·최대 사이에서 움직인다. 미리보기 카드의 7–12px 글자와 상세 예시의 10–14px 보조 정보는 화면 전체를 좁은 룩북 창에 담기 위한 축약 모형의 추정 치수다. 실제 서비스의 읽기 규격으로 복사하지 않는다. 실서비스 구현에서는 공식 Text Small을 기본으로 복원하고 선택 컨트롤의 터치 영역도 충분히 확보해야 한다. 특히 옵션명은 두 줄로 허용하고 비용은 다른 줄에 놓아 긴 단어와 통화가 충돌하지 않게 한다.
Spacing
스페이싱
기본 단위는 4px다. PDS v3.35.0의 Static 단계는 X Small 4, Small 8, Medium 16, Large 32, X Large 48, XX Large 80px다. 룩북에서 흔히 쓰는 24·64px를 공식 단계로 끼워 넣지 않는다. 같은 large라는 말이라도 Static과 Fluid는 범위가 다르므로 별도 이름을 붙인다. 아래 --space-*는 Static에 대응하며 --space-fluid-*는 공식 Fluid 식을 그대로 옮겼다.
:root {
--space-xs: 4px; /* Static X Small */
--space-sm: 8px; /* Static Small */
--space-md: 16px; /* Static Medium */
--space-lg: 32px; /* Static Large */
--space-xl: 48px; /* Static X Large */
--space-2xl: 80px; /* Static XX Large */
--space-3xl: 80px; /* 룩북 호환 별칭(추정) */
--space-fluid-xs: clamp(4px, .25vw + 3px, 8px);
--space-fluid-sm: clamp(8px, .5vw + 6px, 16px);
--space-fluid-md: clamp(16px, 1.25vw + 12px, 36px);
--space-fluid-lg: clamp(32px, 2.75vw + 23px, 76px);
--space-fluid-xl: clamp(48px, 3vw + 38px, 96px);
--space-fluid-2xl: clamp(80px, 7.5vw + 56px, 200px);
--container-max: 1440px; /* 예시용 추정 */
--container-gutter: var(--space-fluid-md);
}
| 관계 | 선택할 간격 | 구성기에서의 이유 | |---|---|---| | 아이콘과 짧은 라벨 | Static Small 8px | 하나의 행동으로 읽히게 묶는다 | | 필드명과 입력, 가격과 설명 | X Small 4px 또는 Small 8px | 가까운 정보임을 유지한다 | | 선택 타일의 내부 | Medium 16px | 그림과 문장이 테두리에 붙지 않는다 | | 같은 구획의 선택 목록 | Medium 16px | 이름·가격의 줄을 읽을 수 있게 한다 | | 서로 다른 옵션 묶음 | Large 32px | Wheels와 Wheel Colors의 경계를 만든다 | | 별도 소개 구획 | X Large 48px 이상 | 기술 표와 패키지 목록을 나눈다 |
공식 Fluid는 화면 폭에 반응한다. 예를 들어 Medium은 clamp(16px, 1.25vw + 12px, 36px)다. 휴대폰에서는 16px 아래로 내려가지 않고 큰 화면에서도 36px를 넘지 않는다. 제목 여백만 커지고 선택 타일은 붙어 있는 식의 불균형을 막으려면, 넓은 구획에는 Fluid를 쓰고 작은 컨트롤에는 Static을 유지하는 편이 좋다. 이 적용 판단은 (추정)이며 값 자체는 공식 소스에서 확인했다.
⑫의 컨테이너는 미리보기 폭 안에서 100%를 쓰고 데스크톱 좌우 24px, 모바일 16px로 압축했다. 왼쪽 무대와 오른쪽 목록의 20px 틈, 600px 전환점도 (추정)이다. 공식 Porsche 구성기의 1280px 화면은 큰 이미지 옆에 옵션 아코디언을 놓고, 모바일은 이미지 아래에 선택 묶음을 쌓는다. 그 구조를 900px와 375px에 맞추되, 너무 작은 두 열을 모바일에 억지로 남기지 않는다. 가로로 긴 단계 메뉴는 자기 영역 안에서만 스크롤하며 페이지 전체 폭은 늘리지 않는다.
Border Radius
Border Radius
공식 Border 토큰은 Small 4px, Medium 8px, Large 12px다. 선 두께는 Base 2px, Thin 1px다. 이 숫자는 별개의 축이므로 12px 모서리의 큰 무대에 2px의 강한 선을 자동으로 붙이지 않는다. 기본 컨트롤은 작은 모서리와 분명한 선을 갖고, 큰 이미지 영역은 선을 생략하거나 얇게 둔다.
:root {
--radius-none: 0; /* 룩북 별칭(추정) */
--radius-sm: 4px; /* borderRadiusSmall */
--radius-md: 8px; /* borderRadiusMedium */
--radius-lg: 12px; /* borderRadiusLarge */
--radius-xl: 12px; /* large 재사용(추정) */
--radius-full: 9999px; /* 원형 상태 표시용(추정) */
--border-width-base: 2px;
--border-width-thin: 1px;
}
Primary와 Secondary 버튼은 4px로 맞춘다. 옆에 놓인 입력과 선택 타일도 작은 반경을 공유하면 작업 화면의 수평선이 정돈된다. 패키지 카드에는 8px, 차량 무대에는 12px를 썼다. 이는 공식 크기를 문맥에 대응한 (추정)이며 PDS가 구성기의 모든 영역에 이 배치를 강제한다는 뜻은 아니다. --radius-xl은 별도 16px를 만들지 않고 12px를 재사용한다. none과 full은 룩북 호환용 별칭이다.
선택된 타일은 기본 1px 경계 위에 1px의 외곽선을 더해 2px처럼 보이게 한다. 내용을 안으로 밀지 않으므로 휠 그림과 가격의 위치가 선택 전후에 움직이지 않는다. 외곽선은 자식 그림자를 넘어 보이되 주변 항목을 덮지 않도록 틈을 확보한다. 체크 표시와 라디오 상태를 함께 넣어 테두리만으로 선택 여부를 설명하지 않는다.
Shadow / Elevation
Shadow / Elevation
PDS의 공식 Drop Shadow는 Low 0 3px 8px rgba(0,0,0,.16), Medium 0 4px 16px rgba(0,0,0,.16), High 0 8px 40px rgba(0,0,0,.16)다. 세 단계 모두 검정 16%를 사용한다. 아래 sm/md/lg는 이 단계와 직접 대응한다. xl은 High를 재사용한 (추정) 별칭이고, 추가로 더 진한 그림자 단계를 발명하지 않았다.
:root {
--shadow-none: none;
--shadow-sm: 0 3px 8px rgba(0,0,0,.16); /* 공식 low: 작은 부유 요소 */
--shadow-md: 0 4px 16px rgba(0,0,0,.16); /* 공식 medium: 팝오버 */
--shadow-lg: 0 8px 40px rgba(0,0,0,.16); /* 공식 high: 상위 레이어 */
--shadow-xl: var(--shadow-lg); /* 별칭(추정), 추가 공식 단계 아님 */
}
기본 선택 타일과 기술 사양 표는 그림자 없이 경계선으로 나눈다. 선택된 타일의 표시는 떠오르는 카드 효과보다 선·체크·배경 변화가 먼저다. Dropdown처럼 다른 내용 위에 놓이는 영역에서 Low 또는 Medium을 쓰고, 모달의 분리에는 High와 Shading을 함께 고려한다. 이 용도 배치는 화면 위계를 설명하기 위한 (추정)이며 각 컴포넌트의 실제 내장 스타일은 설치한 PDS 버전을 따른다.
다크에서 검정 그림자는 눈에 잘 보이지 않는다. 이를 해결하려고 흰 glow를 추가하면 금속 제품 화면이 네온 UI처럼 변한다. Dark Surface #212225와 Contrast Low #404044를 써서 층을 먼저 구분하고 공식 그림자는 보조로 남긴다. 차광 면은 Light와 Dark의 Shading 값을 각각 사용한다. 반투명 Frosted는 내용이 복잡한 사진 위에서 글자를 충분히 가려 주는지 별도로 확인해야 한다.
Iconography
Iconography
- 스타일: Outline 중심. 실제 구성기의 Menu, Save, Share, Back, User, Compare와 확대 아이콘을 기준으로 삼는다.
- 획 두께: 이 문서의 24×24 SVG에서 1.6px는 화면 관찰에 따른 (추정)이다. 공식 아이콘의 모든 원본이 같은 stroke 속성으로 작성된 것은 아니므로 공통 공식 수치로 단정하지 않는다.
- 모서리 처리: 곧은 선과 간결한 꺾임을 기본으로 하고 사용자·정보 아이콘의 원은 자연스럽게 유지한다. 작은 화면에서도 번지는 과도한 round cap을 피한다.
- 우선 라이브러리: 공식
p-icon및 PDS 자산. 외부 의존이 없는 이 예시에서는 단순 조작 아이콘을 자체 인라인 SVG로 그렸다. 일반 라이브러리로 치환할 때는 Lucide의 가는 선이 후보지만 (추정) 대체안이다.
Porsche 워드마크는 공식 저장소의 Wordmark SVG 경로를 사용했다. 영문 텍스트에 자간을 벌려 로고처럼 보이게 만들지 않았다. 브랜드 이름은 모델 제목보다 작게 헤더 중앙에 놓고, 긴 수평 형태가 잘 보이도록 좌우를 비웠다. 다크에서는 currentColor가 Dark Primary로 바뀌므로 별도 흰색 경로를 복제할 필요가 없다. 워드마크의 가로세로 비율을 CSS로 찌그러뜨리지 않는다.
작은 그림은 모두 같은 자동차를 축소 복사하지 않았다. 정면은 두 램프와 네 점 LED, 후면은 유리와 가로 라이트바, 실내는 스티어링 휠·계기판·센터 콘솔, 시트는 등받이와 쿠션으로 구분한다. 상세의 휠은 기본 이중 살, Classic의 넓은 다섯 살, S의 갈라지는 살, Exclusive Design의 큰 면, Turbo S Design의 벌어진 살, RS Spyder의 여러 갈래로 구분한 (추정) 축약 그림이다. 부품 주문용 도면과 같은 정밀도를 주장하지 않는다.
Component Guide
컴포넌트 가이드 (상태별 CSS)
공식 p-button은 v3.35.0에서 primary, secondary, tertiary, ghost 변형을 받는다. theme는 light, dark, auto이고 기본은 light다. loading과 disabled, compact도 공식 속성이다. 이 문서는 대표적인 Primary·Secondary·Ghost를 일반 HTML/CSS로 옮긴다. Danger는 확인한 공식 Button variant에 없으며, 이 문서의 확장 예시 (추정)다. 실제 PDS를 도입할 때 variant="danger"를 넘겨도 동작한다고 가정하지 않는다.
기본 버튼의 공식 작은 서체는 16px, 내부 간격은 8px, 일반 padding은 세로 13px·가로 26px, 경계는 2px, 반경은 4px다. 줄 높이를 포함하면 일반 높이는 대략 54px이며 글꼴에 따라 달라진다. ⑫의 도구 막대와 타일 옆 버튼은 축약 화면이라 30–36px로 줄인 (추정) 예시다. 운영 화면에 적용할 때는 공식 컴포넌트의 크기와 접근성 동작을 사용한다.
| 종류 | 기본 | Hover / Active | Disabled / Loading | |---|---|---|---| | Primary | Primary 면, 반대 테마 글자 | Contrast High 면 / 눌림 보조 변화 | Disabled 면 / 대비 면에서 spinner | | Secondary | 투명 면, Primary 경계 | Hover 면·중간 선 / Active 면 | Disabled 선과 글자 / 라벨 숨기고 spinner | | Ghost | Frosted 면, 약한 경계 | Hover 보조 면 / Active 면 | Frosted 유지·Disabled 글자 / spinner | | Danger (추정) | Error 면, 반대 글자 | 명도 보조 변화 / 눌림 보조 변화 | 다른 버튼과 같은 사용 불가·로딩 규칙 |
.porsche-btn {
position: relative; display: inline-flex; align-items: center; justify-content: center;
gap: var(--space-sm); padding: 13px 26px; min-height: 54px;
border: var(--border-width-base) solid transparent; border-radius: var(--radius-sm);
font: 400 var(--font-text-small)/var(--font-line-height) var(--font-family);
text-decoration: none; cursor: pointer;
transition: background-color var(--duration-fast) var(--ease-base), border-color var(--duration-fast) var(--ease-base);
}
.porsche-btn-primary { background: var(--text-primary); color: var(--text-on-primary); border-color: var(--text-primary); }
.porsche-btn-primary:hover:not(:disabled):not([aria-busy="true"]) { background: var(--text-secondary); border-color: var(--text-secondary); }
.porsche-btn-primary:active:not(:disabled):not([aria-busy="true"]) { background: var(--text-secondary); filter: brightness(.92); } /* 눌림 보완(추정) */
.porsche-btn-secondary { background: transparent; border-color: var(--text-primary); color: var(--text-primary); }
.porsche-btn-secondary:hover:not(:disabled):not([aria-busy="true"]) { background: var(--state-hover); border-color: var(--text-tertiary); }
.porsche-btn-secondary:active:not(:disabled):not([aria-busy="true"]) { background: var(--state-active); }
.porsche-btn-ghost { background: var(--bg-frosted); color: var(--text-primary); border-color: var(--bg-frosted); }
.porsche-btn-ghost:hover:not(:disabled):not([aria-busy="true"]) { background: var(--state-hover); }
.porsche-btn-ghost:active:not(:disabled):not([aria-busy="true"]) { background: var(--state-active); }
/* Danger는 PDS의 공식 variant가 아닌 확장 예시(추정) */
.porsche-btn-danger { background: var(--color-error-fg); border-color: var(--color-error-fg); color: var(--text-on-primary); }
.porsche-btn-danger:hover:not(:disabled):not([aria-busy="true"]) { filter: brightness(.9); }
.porsche-btn-danger:active:not(:disabled):not([aria-busy="true"]) { filter: brightness(.8); }
.porsche-btn:focus-visible, .porsche-plain:focus-visible, .porsche-d-wheel:focus-within { outline: 2px solid var(--border-focus); outline-offset: 3px; }
.porsche-btn:disabled { cursor: not-allowed; filter: none; }
.porsche-btn-primary:disabled,.porsche-btn-danger:disabled { background: var(--state-disabled); border-color: var(--state-disabled); color: var(--text-secondary); }
.porsche-btn-secondary:disabled { background: transparent; border-color: var(--state-disabled); color: var(--state-disabled); }
.porsche-btn-ghost:disabled { background: var(--bg-frosted); border-color: var(--bg-frosted); color: var(--state-disabled); }
.porsche-btn[aria-busy="true"] { cursor: progress; pointer-events: none; }
.porsche-btn-primary[aria-busy="true"] { background: var(--text-secondary); border-color: var(--text-secondary); }
.porsche-btn-secondary[aria-busy="true"] { background: var(--state-hover); border-color: var(--text-tertiary); }
.porsche-btn-ghost[aria-busy="true"] { background: var(--bg-frosted); }
.porsche-btn-danger[aria-busy="true"] { background: var(--color-error-fg); filter: none; }
.porsche-btn[aria-busy="true"] .porsche-btn-label { opacity: 0; }
.porsche-btn[aria-busy="true"]::after { content: ''; position: absolute; width: 20px; height: 20px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: porsche-spin .8s linear infinite; }
.porsche-field { display: grid; gap: var(--space-xs); font: 400 var(--font-text-small)/var(--font-line-height) var(--font-family); }
.porsche-input { box-sizing: border-box; width: 100%; padding: 12px 16px; min-height: 54px; background: var(--bg-base); color: var(--text-primary); border: 1px solid var(--border-default); border-radius: var(--radius-sm); font: inherit; }
.porsche-input:focus-visible { border-color: var(--text-primary); outline: 2px solid var(--border-focus); outline-offset: 3px; }
.porsche-input[aria-invalid="true"] { border-color: var(--color-error-fg); }
.porsche-field-error { color: var(--color-error-fg); font-size: var(--font-text-x-small); }
.porsche-input:disabled { background: var(--bg-subtle); border-color: var(--state-disabled); color: var(--text-disabled); cursor: not-allowed; }
.porsche-panel { padding: var(--space-md); border-radius: var(--radius-md); background: var(--bg-base); box-shadow: var(--shadow-none); }
.porsche-panel-emphasis { background: var(--bg-subtle); border: 2px solid var(--text-primary); }
.porsche-panel-outlined { border: 1px solid var(--border-default); }
.porsche-tag { display: inline-flex; padding: 2px 8px; border: 1px solid transparent; border-radius: var(--radius-sm); background: var(--bg-subtle); color: var(--text-primary); font-size: var(--font-text-x-small); }
.porsche-tag-solid { background: var(--text-primary); color: var(--text-on-primary); }
.porsche-tag-subtle { background: var(--bg-subtle); }
.porsche-tag-outline { background: transparent; border-color: var(--border-default); }
.porsche-nav { display: flex; gap: var(--space-lg); border-bottom: 1px solid var(--border-default); }
.porsche-nav-item { color: var(--text-secondary); padding: var(--space-md) 0; border-bottom: 2px solid transparent; }
.porsche-nav-item[aria-current="step"] { color: var(--text-primary); border-bottom-color: var(--text-primary); font-weight: 600; }
.porsche-notice { display: flex; gap: var(--space-sm); padding: var(--space-md); background: var(--color-info-bg); border-left: 2px solid var(--color-info-fg); color: var(--text-primary); border-radius: var(--radius-sm); }
공식 컴포넌트를 불러오는 실제 앱에서는 아래처럼 모드를 명시한다. 이 짧은 예는 PDS v3.35.0 API를 설명한다. ⑫는 외부 로더 없이 보이는 정적 HTML/CSS 모형이다.
<p-button theme="light" variant="primary">Save configuration</p-button>
<p-button theme="dark" variant="secondary">Summary</p-button>
<p-button theme="dark" variant="primary" loading="true">Saving</p-button>
입력은 라벨·입력·도움말을 한 묶음으로 둔다. 기본 1px 경계, Focus의 파란 외곽선, Error의 의미색과 설명, Disabled의 채도 낮은 글자를 구별한다. 기본·오류·사용 불가는 CSS 예시이며 공식 PDS 입력 컴포넌트의 내부 Shadow DOM을 흉내 내는 선택자는 쓰지 않는다. 에러를 aria-invalid="true"로 알려 주고 설명 id를 aria-describedby에 연결하는 방식이 필요하다. 색만 달라지는 상태는 충분하지 않다.
버튼 상태에서 Loading은 문구를 opacity:0으로 숨겨 기존 폭을 유지한다. 가운데 spinner를 놓고 실제 구현에서는 aria-busy="true"와 중복 실행 방지를 함께 적용한다. CSS만으로 중복 요청을 막을 수는 없다. Disabled는 선택 후 금지된 상태이며 Loading은 진행 중이므로 메시지도 구분한다. 키보드 포커스는 hover와 독립적으로 남긴다. 모든 hover 선택자는 사용 불가·로딩 상태를 제외한다.
Card와 선택 타일은 역할이 다르다. 패키지 소개는 기본 Card, 현재 선택은 강조형, 목록 속 단순 묶음은 Outlined를 쓴다. 강조는 작은 음영과 2px 경계로 표현하고 그림자를 더 높이지 않는다. 검색 입력은 공식 화면의 Search equipment options 라벨을 썼다. 라디오 타일에는 네이티브 입력을 남겨 이름과 선택 여부가 읽히게 한다. 이 정적 데모의 라디오와 버튼은 배치·상태를 보여 주는 모형이다. 선택만 바꿔 가격까지 계산하는 기능은 포함하지 않으므로 실제 구성기 로직으로 오해하지 않는다.
Badge / Tag는 Solid·Subtle·Outline 세 가지 매핑을 제공한다. 연식 2027은 Subtle로 두고 중요한 비용보다 먼저 튀지 않게 한다. 성공 태그는 단순히 초록인 모든 가격에 붙이지 않는다. 저장 완료처럼 확인된 결과에만 쓴다. 색을 선택했다는 의미와 작업이 성공했다는 의미를 같은 체크 배지 하나로 합치지 않는다. 단위를 가진 숫자는 배지보다 일반 문장으로 표현하는 편이 비교하기 쉽다.
Navigation은 단계의 순서를 보존한다. 실제 구성기는 Exterior Colors, Wheels, Interior Colors & Material, Seats, Packages 등의 아코디언으로 이어진다. 이 예시에서는 주요 단계를 탭처럼 압축한 (추정) 구성을 사용한다. 카드의 Interior는 긴 실제 라벨을 줄인 표기다. 선택된 Wheels에는 아래 선과 굵기를 함께 사용한다. 전체 단계 목록에는 Exterior·Interior·Technology·Vehicle accessories·Delivery Experience를 실제 순서로 이어 넣었다. 상세의 2 / 10은 Summary를 제외한 큰 선택 묶음 중 Wheels의 위치다.
가격 요약은 장식 카드가 아닌 검산 가능한 정보다. 카드의 기본가 $135,500 + Guards Red $1,580 + 배송·처리 $2,350 = $139,430이다. 상세에서는 Carrera Classic Wheels $2,590을 추가해 장비 $4,170, 총액 $142,020이 된다. 아래 추천 패키지는 선택되지 않았으므로 합계에 넣지 않는다. Standard와 Optional, Selected를 서로 구별하고 가격을 생략한 선택이 무료인지 확인되지 않았는지 모호하게 남기지 않는다. 실제 판매 조건을 의미하는 문구는 작은 주석으로 합계 근처에 붙인다.
Motion
Motion
공식 Motion 토큰은 Short .25s, Moderate .4s, Long .6s, Very Long 1.2s다. Ease Base는 cubic-bezier(.25,.1,.25,1), Ease In은 cubic-bezier(0,0,.2,1), Ease Out은 cubic-bezier(.4,0,.5,1)이다. 일반적인 이름만 보고 다른 라이브러리의 곡선을 넣지 않는다. 아래 fast/base/slow는 Short·Moderate·Long에 대응한다.
:root {
--duration-fast: .25s; /* motionDurationShort */
--duration-base: .4s; /* motionDurationModerate */
--duration-slow: .6s; /* motionDurationLong */
--duration-very-slow: 1.2s; /* motionDurationVeryLong */
--ease-base: cubic-bezier(.25,.1,.25,1);
--ease-in: cubic-bezier(0,0,.2,1);
--ease-out: cubic-bezier(.4,0,.5,1);
--ease-in-out: var(--ease-base); /* 룩북 호환 별칭(추정) */
}
@keyframes porsche-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
.porsche-btn,.porsche-input { transition: none; }
.porsche-btn[aria-busy="true"]::after { animation: none; }
}
색 선택 후 차체가 바뀌는 순간과 버튼 hover의 전환은 다른 일이다. 제어 요소의 색·선은 짧게 전환하고 이미지 준비가 필요한 작업은 진행 상태를 보여 준다. 준비되기 전에 새로운 총액만 바꾸거나 예전 차량 이미지를 최신 선택처럼 보여 주지 않는다. 실제 서비스에서는 선택된 옵션의 상태, 준비 중인 렌더, 완료된 이미지가 같은 요청을 가리키도록 관리해야 한다. 이 정적 예시에는 자동 회전이나 차체 전환 애니메이션을 넣지 않았다.
prefers-reduced-motion: reduce에서는 spinner 회전을 정지하고 비필수 전환을 없앤다. 진행 중이라는 문장과 aria-busy 의미는 유지해야 한다. 코드의 회전 시간 .8s와 누르는 순간의 밝기 변화는 공식 Motion 토큰의 추가 단계가 아니라 (추정) 구현 예시다. 실제 PDS 컴포넌트를 쓸 때는 그 버전의 내장 Loading 동작을 우선하고 중복된 전환을 밖에서 덧씌우지 않는다.
Anti-patterns
Anti-patterns
1. 자동차의 빨강을 UI Primary로 확장하기. Guards Red는 구성한 차량의 색이다. 버튼·탭·모든 제목을 빨강으로 채우면 제품과 상태가 같은 신호를 낸다. PDS의 무채색 Primary와 별도 Error 역할을 유지하고, 페인트 선택은 이름·가격·체크로 설명한다. 사진이 파란 차로 바뀌어도 주변 UI의 의미는 변하지 않아야 한다. 2. 911을 네모난 차체와 두 바퀴로 요약하기. 낮은 앞부분, 솟은 펜더, 객실 뒤로 이어지는 긴 지붕, 넓은 뒤 어깨가 빠지면 일반 스포츠카가 된다. 공식 렌더에서 비율을 먼저 따고 유리·도어·손잡이·램프·휠·반사광을 따로 겹친다. 카드에서는 그 세부가 뭉개지지 않는 크기로 차를 남긴다. 정면과 후면의 특징은 다른 시점의 작은 그림으로 보완한다. 3. 미국·국제판 사양과 서로 다른 연식의 가격을 섞기. 388 hp와 394 PS는 단위 체계와 시장 표기의 차이가 있다. 0–60 mph, 0–100 km/h와 Sport Chrono 조건도 분리해야 한다. 이 문서의 2027 미국 기본가와 옵션가는 같은 구성기에서 확인했다. 국내 가격이나 과거 Shark Blue 옵션을 현재 선택지처럼 넣지 않는다. 추천 패키지와 이미 선택한 장비의 합계도 구별한다. 4. 공식 PDS 토큰과 관찰한 화면 치수를 한 종류의 규칙으로 쓰기. v3.35.0의 4/8/12px와 16px 기본 본문은 공식 값이다. 카드의 7px 글자, 900px 안의 두 열, 수동 SVG 도장의 hex는 축약 모형의 추정값이다. 이를 분명히 나누어야 예시를 실서비스로 옮길 때 작은 컨트롤을 그대로 배포하지 않는다. PDS v4의 색 체계도 v3의 theme 속성 설명과 섞지 않는다. 5. 다크를 사진 보정 필터나 검정 배경 한 장으로 처리하기. 공식 Dark는 Primary·Surface·Contrast·Feedback·Disabled에 각각 값이 있다. 밝은 버튼의 글자, 선택선, 표의 구획선까지 바뀌어야 한다. 차체의 도장과 워드마크는 서로 다른 방식으로 처리한다. 제품 이미지의 색을 반전하지 않으며, 워드마크는 텍스트색을 따른다. 낮은 대비를 흰 그림자로 해결하지 않고 공식 면과 선을 먼저 조절한다.
Sources
출처
- https://designsystem.porsche.com/v3/
- https://designsystem.porsche.com/v3/styles/theme/
- https://designsystem.porsche.com/v3/styles/typography/
- https://designsystem.porsche.com/v3/styles/spacing/
- https://designsystem.porsche.com/v3/styles/border/
- https://designsystem.porsche.com/v3/styles/drop-shadow/
- https://designsystem.porsche.com/v3/styles/motion/
- https://designsystem.porsche.com/v3/components/button/examples/
- https://designsystem.porsche.com/v4/must-know/theme/
- https://github.com/porsche-design-system/porsche-design-system/releases/tag/v3.35.0
- https://api.github.com/repos/porsche-design-system/porsche-design-system/releases/tags/v4.0.0
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/components/src/utils/theme/theme.ts
- https://configurator.porsche.com/en-US/model/9921B2
- https://www.porsche.com/usa/models/911/
- https://www.porsche.com/international/models/911/
- https://newsroom.porsche.com/en_AU/company/porsche-digital-design-system-19975.html
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/components/src/components/button/button-styles.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/components/src/components/wordmark/assets/wordmark-optimized.svg
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/border/border.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/dropShadow/dropShadowHighStyle.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/dropShadow/dropShadowLowStyle.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/dropShadow/dropShadowMediumStyle.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/font/fontFamily.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/font/fontLineHeight.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/font/fontSize.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/font/fontWeight.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/motion/motionDurationShort.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/motion/motionEasingBase.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/spacing/spacingFluid.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/spacing/spacingStatic.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/theme/themeDark.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/theme/themeLight.ts
- https://raw.githubusercontent.com/porsche-design-system/porsche-design-system/v3.35.0/packages/utilities/projects/utilities/src/js/theme/themeShared.ts
Porsche 이름과 로고는 각 권리자의 상표입니다.