모든 도구 브랜드 룩북

HarmonyOS NEXT

푸른 빛의 곡선 위 18·22vp 서비스 카드, 큰 온도·걸음 수와 꽃잎·렌즈 앱 아이콘

아시아디자인 시스템소비자차가운modern-minimalhumanism고딕comfortableroundlayered라이트다크공식출시 2024개정 2024

갤러리에서 열기 — 적용 예시 · 가이드 다운로드

Brand DNA

브랜드 DNA

  • 브랜드명: HarmonyOS NEXT · 鸿蒙. 중국 본토용 휴대폰과 태블릿의 홈, 서비스 카드, 설정, 제어 센터를 다룬다.
  • 한 줄 정체성: 앱을 열기 전에 필요한 정보와 짧은 행동을 꺼내 놓는, 기기 사이에 이어지는 생활 운영체제.
  • 공식 디자인 철학: 영문 Design Philosophy의 One·Harmonious·Universe를 기준으로, 같은 원리가 여러 기기에서 일관되게 작동하고 빛과 움직임이 화면의 깊이를 만든다고 해석한다.
  • 시그니처 요소 1개: 서로 다른 크기의 서비스 카드가 홈 아이콘 격자에 들어가고, 그 안에서 큰 숫자와 한 번의 행동을 함께 보여 주는 구조.

이 시스템을 구별하는 단서는 파란 버튼 하나가 아니다. 날씨는 도시와 현재 온도를 크게 보여 주고, 음악은 앨범과 재생 버튼을 가까이 놓으며, 운동 카드는 걸음 수를 한눈에 읽게 한다. 앱 이름은 카드 아래에 작게 붙는다. 카드 안에 앱 이름을 또 크게 넣으면 정보가 밀려난다. 아이콘 아래의 작은 밑줄은 위로 밀어 카드를 꺼낼 수 있다는 단서다. 정사각 카드와 가로로 긴 카드가 같은 홈 격자를 나눠 쓰므로 화면을 임의의 통계 대시보드로 바꾸지 않는다.

공식 서비스 카드 문서는 1×2, 2×2, 2×4, 4×4 구성을 구분한다. 카드 안의 정보와 행동은 해당 공간에 맞춰 줄어들거나 늘어난다. 작은 카드에 큰 카드의 모든 내용을 축소해 넣는 방식은 맞지 않는다. 날씨 카드의 현재 온도는 남기되, 시간별 예보는 넓은 카드나 앱 화면에서 보여 주는 식이다. 카드의 바깥 모양은 시스템이 관리하고, 내용은 제공 서비스의 성격을 드러낸다. 날씨의 파랑과 건강의 주황이 함께 있어도 외곽 크기와 글자 위계가 맞으면 같은 시스템으로 읽힌다.

이 문서는 NEXT 제품 화면과 공개 가이드의 확인 시점을 구분한다. 2026년 10월 12일 중문 디자인 대문은 HarmonyOS 7을 소개하고 있지만 영문 대문에는 HarmonyOS NEXT Design이 남아 있다. 제품 소개 주소의 제목은 HarmonyOS 5다. 따라서 최신 대문에 새로 생긴 표현을 전부 NEXT 초기 화면의 규칙으로 소급하지 않는다. 문서의 색·배치·카드 수치는 현재 공개된 관련 가이드에서 읽은 값이고, 기기 그림은 NEXT 소개 화면에서 확인한 형태를 재구성했다. 첫 공개 연도 2024는 NEXT 계열을 구분하기 위한 값으로, 전체 HarmonyOS 디자인 체계의 최초 연도를 뜻하지 않는다.

Tone & Mood

톤 & 무드

  • 핵심 키워드 3개: 조화로운 · 즉각적인 · 유연한
  • 무드 설명: 눈처럼 밝은 회색 바탕 위에 파랑을 필요한 행동에만 쓴다. 둥근 카드와 부드러운 빛은 편안하지만, 큰 숫자와 짧은 문구는 읽는 순서를 분명하게 만든다. 어두운 판은 회색 면의 높낮이를 남겨 정보가 검은 바탕에 묻히지 않게 한다.
  • 비주얼 스타일: 모던 미니멀, 휴머니즘.
  • 밀도(Density): Comfortable. 개별 카드에는 안전 여백을 주고, 홈 전체는 카드·앱 폴더·독을 함께 배치해 생활 정보가 모이게 한다.
  • 모서리 성향: Round. 필터의 분류는 round이며, 실제 서비스 카드 수치는 작은 카드 18vp, 큰 카드 22vp다.
  • 평면성: Layered. 홈 배경, 카드 내용, 펼친 패널이 서로 다른 깊이를 갖지만 본문 목록에는 입체 효과를 남발하지 않는다.

편안한 밀도는 빈 화면을 뜻하지 않는다. 공식 홈 예시는 위쪽 시계, 중간 날씨와 걸음 수, 큰 앱 폴더, 하단 독이 한 장면에 공존한다. 카드 안은 핵심 숫자와 짧은 설명만 남겨 빠르게 읽히게 하고, 다른 서비스는 옆 카드로 분리한다. 따라서 긴 소개 문단을 카드에 넣거나, 모든 내용을 같은 크기의 사각형 여섯 개로 나누면 실제 홈의 리듬이 사라진다. 2×2의 집중된 정보와 1×2의 짧은 상태가 번갈아 나타나야 한다.

밝은 판은 흰 카드와 회색 배경의 차이를 이용해 영역을 나눈다. 경계선이 카드의 모든 가장자리에 두껍게 보일 필요는 없다. 어두운 판은 그림자만으로 높이를 표현하기 어렵기 때문에 배경보다 조금 밝은 회색 면을 쓴다. 이때 모든 면을 같은 검정으로 만들면 목록과 패널이 붙고, 반대로 모든 카드를 푸른색으로 채우면 행동과 정보의 구분이 사라진다. 파랑은 연결된 상태, 선택된 항목, 주 행동에 집중하고 서비스 고유 색은 해당 콘텐츠 안에 둔다.

중국어 화면 문구는 명사와 행동을 짧게 쓴다. 设置, 卡片, 控制中心처럼 화면 이름을 먼저 놓고, 添加至桌面, 查看物流, 加入会议처럼 결과를 알 수 있는 행동을 쓴다. 영문을 장식으로 섞지 않으며 High Five 같은 실제 앨범명이나 HarmonyOS NEXT 같은 고유 이름만 유지한다. 숫자는 08:08처럼 시각 형식을 지키고, 걸음 수와 온도에는 단위를 가까이 붙인다. 보조 설명은 회색으로 낮추되 필요한 값까지 흐리게 지우지 않는다.

Color System

컬러 시스템 (CSS 변수)

공식 Color 문서는 기본 팔레트, 의미 토큰, 컴포넌트 토큰의 순서로 색을 구분한다. 브랜드 행동색은 라이트 #0A59F7, 다크 #317AF7다. 두 값은 임의로 밝기를 올린 결과가 아니라 표에 따로 적힌 값이다. 같은 버튼에 밝은 판의 파랑을 고정하면 어두운 판의 표면과 대비가 달라진다. 화면 전체를 브랜드색으로 칠하기보다 강조 글자와 주요 행동, 활성 상태에 같은 의미 토큰을 연결한다.

| 역할 | 라이트 공식 값 | 다크 공식 값 | 적용 위치 | |---|---|---|---| | brand / emphasize | #0A59F7 | #317AF7 | 추가 버튼, 선택 탭, 활성 스위치 | | warning | #E84026 | #D94838 | 위험·오류를 알리는 빨강 | | alert | #ED6F21 | #DB6B42 | 주의가 필요한 주황 | | confirm | #64BB5C | #5BA854 | 완료·성공의 초록 | | background_secondary | #F1F3F5 | #191A1C | 화면 바탕 | | comp_background_primary | #FFFFFF | #202224 | 설정 목록 면 | | 서비스 카드 바탕 | #FFFFFF / #F1F3F5 | #2E3033 | 카드·일정·걸음 수 | | font_primary | #E5000000 | #E5FFFFFF | ARGB 표기, 핵심 글자 | | font_secondary | #99000000 | #99FFFFFF | ARGB 표기, 보조 글자 | | comp_divider | #33000000 | #33FFFFFF | ARGB 표기, 분리선 |

공식 표의 여덟 자리 색은 알파가 앞인 ARGB다. 웹 CSS의 여덟 자리 HEX는 알파가 뒤이므로 그대로 복사하면 다른 색이 된다. 예를 들어 #E5000000은 CSS에서 #000000E5이고, #99000000은 #00000099다. 아래 코드는 이 순서를 바꿔 사용한다. 배경과 섞인 결과색을 새 공식 토큰처럼 기록하지 않는다. 90%, 60%, 40%, 20%로 나뉜 글자 위계는 각각 중요한 본문, 보조 설명, 약한 장식 정보, 비활성 상태에 대응한다.

공개 표의 background_primary 다크 셀에는 #FFE5E5E5가 보이지만 주변 설명의 어두운 배경 원칙과 일치하지 않는다. 그 값을 검정으로 임의 정정하지 않았다. 이 재현은 명확한 background_secondary #191A1C를 기본 면으로, comp_background_primary #202224를 목록 면으로, 서비스 카드 문서의 #2E3033를 위젯 면으로 선택한다. 이 결정 덕분에 출처의 모순을 숨기지 않으면서 실제 다크 카드 예시와 일치하는 표면 위계를 유지한다.

Primary 50~900 단계는 문서 형식을 맞추기 위한 웹 재현용 보간이며 500을 제외하면 모두 (추정)이다. 공식 이름이 붙은 열 단계 팔레트라고 해석하지 않는다. 성공·주의·오류 배경은 각각의 의미색을 낮은 불투명도로 합성한 재현값(추정)이다. 전경의 의미색은 공식 수치를 유지한다. 파란 날씨 카드와 짙은 음악 카드는 콘텐츠에 따라 정한 예시 색(추정)이며 시스템 동작색과 별도다. 카드 가이드는 콘텐츠 중심의 컬러 카드가 테마 사이에서 같은 색을 유지하는 구성을 허용한다.

:root {
  /* 500은 공식 brand. 나머지 Primary 단계는 웹 보간 (추정). */
  --color-primary-50: #EDF3FF;
  --color-primary-100: #DDE8FF;
  --color-primary-200: #B7CFFF;
  --color-primary-300: #85AEFC;
  --color-primary-400: #528BFA;
  --color-primary-500: #0A59F7;
  --color-primary-600: #084ACF;
  --color-primary-700: #073FAE;
  --color-primary-800: #06338A;
  --color-primary-900: #062663;
  /* 중성색: 공개 surface의 원색을 순서만 붙여 정리. */
  --color-neutral-0: #FFFFFF;
  --color-neutral-50: #F1F3F5;
  --color-neutral-100: #E5E5EA;
  --color-neutral-200: #D1D1D6;
  --color-neutral-300: #B7BBC2; /* 보간 (추정) */
  --color-neutral-500: #81858D; /* 보간 (추정) */
  --color-neutral-700: #2E3033;
  --color-neutral-800: #202224;
  --color-neutral-900: #191A1C;
  --color-neutral-1000: #000000;
  /* 전경은 공식 confirm/alert/warning, 배경 합성은 (추정). */
  --color-success-fg: #64BB5C;
  --color-success-bg: #64BB5C1A;
  --color-warning-fg: #ED6F21;
  --color-warning-bg: #ED6F211A;
  --color-error-fg: #E84026;
  --color-error-bg: #E840261A;
  --color-info-fg: var(--color-primary-500);
  --color-info-bg: #0A59F719;
  --bg-base: #F1F3F5; /* background_secondary */
  --bg-subtle: #F1F3F5;
  --bg-elevated: #FFFFFF; /* comp_background_primary */
  --bg-widget: #FFFFFF; /* 서비스 카드 전용 공식 값 */
  --bg-overlay: #00000040; /* 웹 시트 뒤 딤 (추정) */
  --bg-hover: #0000000C;
  --bg-selected: #0A59F733; /* emphasize_secondary */
  --text-primary: #000000E5;
  --text-secondary: #00000099;
  --text-tertiary: #00000066;
  --text-disabled: #00000033;
  --text-on-primary: #FFFFFF;
  --border-default: #00000033;
  --border-subtle: #0000000C;
  --border-strong: #00000066; /* 웹 기기 외곽 매핑 (추정) */
  --border-focus: var(--color-primary-500);
  --state-hover: #0000000C;
  --state-pressed: #00000019;
  --font-sans: 'HarmonyOS Sans SC', 'HarmonyOS Sans', 'Noto Sans SC', 'Microsoft YaHei', 'PingFang SC', sans-serif;
}

Typography

타이포그래피

  • 기본 서체: HarmonyOS Sans. 간체 중국어 화면은 HarmonyOS Sans SC를 먼저 찾고, 그 다음 HarmonyOS Sans, Noto Sans SC, Microsoft YaHei, PingFang SC, sans-serif 순서로 대체한다.
  • 한글 페어링: 이 예시는 간체 중국어 화면이다. 공식 한글 전용 가족의 지원 범위를 이번 자료에서 확인하지 못해 메타데이터는 false로 기록했다. 한국어 본문을 별도 서비스에 옮길 경우 Malgun Gothic 또는 Noto Sans KR를 대체 서체로 쓰는 것은 구현 선택(추정)이다.
  • 영문·숫자: 같은 HarmonyOS Sans 계열을 유지하고 시간·온도·걸음 수에는 tabular-nums를 켠다. 외부 폰트를 내려받거나 문서에 포함하지 않는다.

현재 공개 Typography 문서는 폰의 전시 글자 56/48/38vp, 제목 30/24/20vp, 부제 18/16/14vp, 본문 16/14/12vp, 캡션 12/10vp를 구분한다. 표에 적힌 단위를 그대로 vp로 기록한다. 서비스 카드의 「卡片字号」 표는 숫자 40/32/20fp, 제목 18/16fp, 본문 16/14/12fp, 힌트 10fp를 제시한다. 카드별 세부 도해의 14fp 제목 예시는 이 전체 단계와 구분한다. 두 표를 합쳐 존재하지 않는 하나의 공식 단계라고 만들지 않는다. 홈의 온도는 서비스 카드의 숫자 규칙을, 설정의 제목과 목록은 일반 화면의 위계를 따른다.

| 웹 역할 | 공식 폰 크기·굵기 | 웹 행간·자간 (추정) | 읽는 대상 | |---|---|---|---| | Display L/M/S | 56 / 48 / 38vp, Light | 1.08 / -0.02em | 잠금 시계, 큰 상태 값 | | H1 / Title L | 30vp, Bold | 1.2 / -0.015em | 화면 제목 | | H2 / Title M | 24vp, Bold | 1.25 / -0.01em | 큰 구획 | | H3 / Title S | 20vp, Bold | 1.3 / 0 | 작은 구획 | | Subtitle L/M/S | 18 / 16 / 14vp, Medium | 1.35 / 0 | 카드·목록의 짧은 제목 | | Body Large | 16vp, Medium | 1.5 / 0 | 중요한 안내 | | Body | 14vp, Regular | 1.5 / 0 | 본문 설명 | | Body Small | 12vp, Regular | 1.45 / 0 | 보조 설명 | | Caption L/M | 12 / 10vp, Medium | 1.35 / 0 | 짧은 라벨 |

서체 문서는 가는 두께부터 매우 굵은 두께까지 아홉 단계를 설명한다. 모든 크기에 굵은 글자를 쓰는 대신 숫자의 크기와 글자 두께를 따로 조절한다. 온도는 크고 가벼워도 읽히지만, 좁은 카드의 제목은 중간 두께가 필요하다. 중국어 문장을 과도한 자간으로 벌리면 정보가 분리돼 보이므로 기본은 0이다. 영문 이름이 긴 경우에는 단어를 임의로 끊기보다 줄 수나 표시 내용을 조정한다. 숫자 사이의 콜론과 온도 기호는 가까이 두되 기준선이 흔들리지 않게 한다.

vp는 논리 배치 단위이며 fp는 사용자 글자 배율을 반영하는 단위다. 물리 픽셀과 같지 않다. 이 문서의 웹 CSS px는 룩북 안에서 비율을 옮긴 값(추정)이며, 280×210 카드에서는 장면 전체가 줄어든다. 실제 앱에 그 작은 크기를 복사해서는 안 된다. 네이티브 구현은 시스템 글자 배율을 따라야 하며, 카드 가이드가 허용한 숫자·짧은 라벨의 예외도 해당 조건에서만 적용한다. 정보가 길어졌다는 이유로 본문 전체의 배율을 강제로 고정하지 않는다.

Spacing

스페이싱

기본 단위는 8vp이고 작은 보정은 4vp다. 공식 배치 문서는 화면 폭에 따라 열과 바깥 여백을 바꾼다. 600vp 미만은 4열과 좌우 16vp, 600~839vp는 8열과 좌우 24vp, 840vp 이상은 12열과 좌우 32vp를 제시한다. 넓은 화면은 콘텐츠 폭을 무한히 늘리지 않고 최대 2220vp를 기준으로 관리한다. 같은 카드 수를 억지로 한 줄에 유지하기보다 열 수를 바꾸는 쪽이 이 시스템의 기기 대응 원칙에 가깝다.

| 영역 | 확인한 간격 | 적용 판단 | |---|---|---| | 기본 반복 간격 | 8vp | 아이콘과 글자, 작은 카드 사이 | | 세부 보정 | 4vp | 숫자와 단위, 짧은 라벨 | | 카드 내부 안전 구역 | 12vp | 카드 내용이 바깥 마스크에 닿지 않게 함 | | 좁은 화면 가장자리 | 16vp | 폰의 일반 콘텐츠 | | 중간 화면 가장자리 | 24vp | 태블릿·접힌 화면 중간 단계 | | 넓은 화면 가장자리 | 32vp | 큰 창의 콘텐츠 | | 나란한 두 버튼 사이 | 12vp | 취소와 확인 등 같은 그룹 | | 목록 오른쪽 액션 간격 | 12vp | 본문과 스위치·보조 행동 |

서비스 카드의 12vp는 글자만을 위한 여백이 아니다. 작은 로고나 재생 버튼도 이 안전 구역을 고려한다. 날씨 그림은 배경처럼 잘릴 수 있지만 현재 온도나 도시 이름은 모서리 밖으로 나가면 안 된다. 앱 이름을 카드 아래에 두는 경우에는 카드 내부 여백과 별도의 라벨 간격이 필요하다. 룩북의 작은 장면은 기기 비율로 줄였으며, 아래 CSS의 카드 패딩은 큰 예시에서 직접 사용한다. 실제 홈에서는 시스템이 주는 카드 슬롯의 크기가 우선이다.

가이드에 실린 휴대폰 카드 미리보기에는 2×2가 140×140vp, 2×4가 300×140vp인 예가 있다. 이를 모든 기기의 고정 크기로 해석하지 않는다. 글자 배율과 홈 격자, 화면 폭이 바뀌면 사용 가능한 공간도 달라진다. 스냅샷 이미지의 픽셀 크기를 논리 크기와 혼동하지 않고, 짧은 변과 긴 변의 비율을 먼저 따른다. 데스크톱·태블릿·휴대폰에서 같은 위젯을 보여 줄 때는 내용 우선순위를 유지하고 부가 정보를 늘리거나 줄인다.

:root {
  /* 공식 8vp 기본 / 4vp 보정의 비율을 CSS px로 옮긴 웹 재현 */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-card: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;
  --space-3xl: 64px;
  --container-max: 1200px; /* 룩북 폭 (추정), 네이티브 최대 2220vp와 별도 */
  --container-padding: 16px;
}
.hm-container { max-width:var(--container-max); padding-inline:var(--container-padding); margin-inline:auto; }
@media (min-width:600px) { .hm-container { --container-padding:24px; } }
@media (min-width:840px) { .hm-container { --container-padding:32px; } }

⑫의 900px 화면에는 기기 세 대를 한 줄로 놓되, 각 기기 안의 정보는 하나의 폰 화면으로 묶었다. 375px에서는 폰을 세로로 배치하고, 태블릿의 왼쪽 탐색을 위쪽 서비스 선택 줄로 바꾼다. 이는 웹 재현을 위한 대응점(추정)이며 공식 기기 구간을 그대로 대체하지 않는다. 가로로 넘치는 긴 장면을 축소해 읽을 수 없게 만드는 대신 실제 콘텐츠의 순서를 유지한다. 아래의 일정과 알림도 한 열로 바뀌므로 화면을 가로로 밀지 않아도 끝까지 읽을 수 있다.

Border Radius

Border Radius

공식 서비스 카드 규격에서 1×2와 2×2의 모서리는 18vp, 2×4와 4×4는 22vp다. 크기가 큰 카드가 더 큰 모서리를 갖지만 두 값의 차이는 과장되지 않는다. 위젯은 앱이 제출한 네모난 내용을 시스템 마스크가 잘라 보여 주는 구조다. 웹 재현에서는 이를 CSS border-radius로 옮겼다. 이런 CSS 값이 네이티브 시스템의 곡선 수학을 완전히 복제한다는 뜻은 아니다. 카드의 크기와 문맥을 먼저 맞추고 모서리 값을 선택한다.

아이콘의 곡선은 카드와 다른 문제다. 공식 앱 아이콘 문서는 1024×1024px 정사각형 전경·배경 자원을 요구하고, 시스템이 장면별 마스크를 적용한다고 설명한다. 문서 본문에서 단일 CSS 반지름을 확인하지 못했으므로 앱 아이콘의 연속 곡선은 관찰에 따른 SVG 재구성(추정)이다. 모든 앱을 원으로 만들거나, 카드의 18vp를 그대로 축소해 아이콘 마스크로 쓰지 않는다. 중앙 전경이 모서리에서 잘리지 않게 배치하는 원칙은 공식 규정에서 가져왔다.

| 요소 | 모서리 | 근거 | |---|---|---| | 1×2·2×2 서비스 카드 | 18vp | 공식 카드 규격 | | 2×4·4×4 서비스 카드 | 22vp | 공식 카드 규격 | | 카드 안 작은 서비스 로고 | 4vp | 20×20vp 로고 예시 | | 스켈레톤 면 | 높이 10vp 초과 4vp, 이하는 2vp | 공식 빈 상태 규칙 | | 원형 행동·스위치 트랙 | 완전한 원·캡슐 | 공식 형태를 웹에 옮김 | | 설정 목록 그룹 | 16px | 관찰 기반 재현 (추정) | | 기기 몸체·시트 외곽 | 장면별 별도 곡률 | 공식 화면 관찰에 따른 그림 (추정) |

:root {
  --radius-none: 0;
  --radius-xs: 2px; /* 작은 스켈레톤 */
  --radius-sm: 4px; /* 카드 로고와 큰 스켈레톤 */
  --radius-md: 12px; /* 웹 탐색 선택면 (추정) */
  --radius-list: 16px; /* 목록 그룹 (추정) */
  --radius-card: 18px; /* 공식 1×2 / 2×2의 18vp를 웹에 대응 */
  --radius-card-wide: 22px; /* 공식 2×4 / 4×4의 22vp를 웹에 대응 */
  --radius-lg: var(--radius-card);
  --radius-xl: var(--radius-card-wide);
  --radius-full: 9999px;
}

큰 카드 안에 작은 둥근 카드가 계속 중첩되면 바탕이 여러 겹 생기고 정보 영역이 줄어든다. 공식 카드 가이드는 불필요한 둥근 사각 틀의 반복을 피하도록 한다. 일정 카드의 한 줄은 별도 흰 상자보다 짧은 세로 색선으로 구분하고, 음악의 재생 버튼은 원형으로 두어 사각형 중첩을 줄인다. 태블릿의 출행 카드도 시간, 역 이름, 좌석을 하나의 면 안에서 정렬한다. 각 데이터에 별도의 배지를 붙여 조각내지 않는다.

Shadow / Elevation

Shadow / Elevation

깊이는 넓은 그림자보다 표면의 관계로 먼저 표현한다. 홈의 위젯은 배경화면 위에 놓이고, 카드 센터는 홈 위로 올라오는 패널이다. 카드 센터 안의 추천 카드가 다시 떠 있는 것처럼 모든 목록 행에 그림자를 넣으면 계층이 너무 많아진다. 공식 자료에서 이 웹 재현과 일치하는 blur·spread·offset 숫자는 확인하지 못했다. 아래 그림자 값은 전부 화면 관찰에 따른 (추정)이며, 공식 토큰으로 오해하지 않게 역할 이름을 따로 둔다.

| 단계 | 쓰는 곳 | 피하는 곳 | |---|---|---| | none | 기본 목록 행, 카드 안 정보, 날씨 그림 | 선택을 설명해야 하는 부유 패널 | | sm | 선택 탭, 태블릿 바깥 면의 약한 분리 | 목록의 모든 줄 | | md | 펼친 서비스 카드 미리보기 | 작은 상태 배지 | | lg | 홈 위 카드 센터 시트 | 본문 문장 뒤 | | xl | 장면을 설명하는 기기 그림 | 실제 앱 콘텐츠의 기본값 |

:root {
  /* 모두 관찰 기반 웹 재현 (추정), 네이티브 공식 수치 아님 */
  --shadow-none: none;
  --shadow-sm: 0 1px 3px #14264C0D;
  --shadow-md: 0 5px 16px #14264C14;
  --shadow-lg: 0 12px 32px #14264C21;
  --shadow-xl: 0 18px 42px #12264A33;
  --shadow-device: 0 7px 14px #14264C26, inset 0 0 0 1px #FFFFFF38;
}

밝은 판의 그림자는 검정이 바탕에 낮은 농도로 섞이는 정도로 제한한다. 경계가 흐려졌다는 이유로 검정 테두리를 함께 두껍게 넣으면 카드가 무거워진다. 다크 판에서는 검은 그림자의 효과가 작기 때문에 공식 다크 가이드가 설명하는 밝기 차이로 높이를 보완한다. 페이지 #191A1C, 목록 #202224, 위젯 #2E3033의 관계가 먼저 유지돼야 한다. 그림자를 더 진하게 하는 일만으로 밝은 판과 같은 분리를 얻으려 하지 않는다.

반투명 면은 공식 NEXT 제어 센터의 화면 관찰에서 가져왔다. 음악 재생과 Wi-Fi 영역 뒤로 배경색이 비치지만 글자와 아이콘은 또렷하다. 여기서 사용한 불투명도와 CSS 그라데이션은 관찰 기반 값(추정)이다. Apple HIG의 최신 유리 재질 규칙을 가져온 것이 아니며, 모든 표면에 같은 흐림 효과를 적용하지 않았다. 서비스 카드 센터와 설정 화면은 기본 회색 면을 유지한다. 각 화면의 실제 재질이 다른 점을 그대로 남기는 편이 브랜드를 더 정확하게 보여 준다.

Iconography

Iconography

  • 스타일: 앱은 색 면과 전경 그림을 겹친 Filled·Duotone, 시스템 행동은 단순한 Outline을 섞는다.
  • Stroke 굵기: 제어 아이콘의 웹 24px 상자에서 1.7px, 작은 보조 아이콘 1.2~1.6px는 관찰 기반 (추정)이다. 공식 Symbol의 모든 굵기를 하나로 대표하는 값이 아니다.
  • 모서리 처리: 시스템 선 아이콘은 둥근 끝, 앱 바탕은 시스템이 자르는 연속 곡선이다.
  • 추천 자원: 기본은 공식 HarmonyOS Symbol과 앱 아이콘 템플릿이다. 이 문서의 SVG는 외부 자원 없이 의미를 보여 주기 위한 재구성이며, 일반 웹 아이콘을 쓸 때도 공식 기호의 의미와 두께를 먼저 비교한다.

공식 앱 아이콘 가이드는 전경과 배경을 나누고 중앙의 주요 형태를 크게 유지하도록 한다. 휴대폰의 작은 아이콘은 자세히 들여다보지 않아도 기능을 알아야 한다. 전화는 초록 바탕의 흰 수화기, 메시지는 파란 바탕의 말풍선, 브라우저는 지구의 선, 카메라는 여러 겹의 렌즈로 그렸다. 설정은 톱니, 갤러리는 서로 겹친 꽃잎, 음악은 음표, 메모는 체크와 줄, 지갑은 겹친 카드다. 다른 색의 같은 사각형으로 앱 종류를 대신하지 않았다.

빛은 위에서 아래로 내린다. 공식 문서는 앱 바탕의 위가 밝고 아래가 어두운 방향을 권하며, 대각선이나 아래가 더 밝은 강한 그라데이션을 피한다. 따라서 앱 아이콘의 바탕은 한 방향의 약한 명도 차이를 갖고 상단에 짧은 하이라이트를 남겼다. 앞쪽 그림이 지나치게 작거나 모서리에 붙으면 시스템 마스크에서 잘릴 수 있다. 균형을 맞추기 위해 꽃잎처럼 퍼진 모양과 좁은 수화기는 각기 다른 면적 보정을 사용한다.

제어 센터의 원형 버튼은 앱 아이콘과 구별한다. 비행 모드는 비행기 선 그림, 손전등은 길쭉한 몸체, 화면 회전은 잠금 모양, 스캔은 네 모서리 표시로 표현한다. 선택 상태는 원형 바탕과 글자·기호가 함께 알려야 한다. 파란 원 안에 흰 기호가 있다는 이유만으로 모든 동작이 활성인 것은 아니다. 예시에서는 벨소리와 모바일 데이터만 활성색을 주고 나머지는 같은 배경 계열의 낮은 면으로 남겼다.

Component Guide

컴포넌트 가이드 (상태별 CSS)

서비스 카드, 목록, 버튼, 스위치는 같은 의미 토큰을 쓰되 역할에 맞게 크기를 다르게 잡는다. 공식 버튼 가이드는 강조 면, 옅은 면, 글자 버튼 순서로 행동의 무게를 구분한다. 중요한 추가 행동은 파란 캡슐, 이미 존재하는 정보의 자세히 보기는 옅은 파랑, 관리·닫기 같은 가벼운 행동은 글자 또는 원형 아이콘으로 표현한다. 파괴적 행동만 빨강을 사용한다. 화면 안에 빨간색을 더 넣기 위해 의미 없는 위험 버튼을 배치하지 않는다.

Button: .hm-btn-primary, .hm-btn-secondary, .hm-btn-ghost, .hm-btn-danger가 기본형이다. Hover는 공식 hover 알파, Active는 pressed 알파를 합성하며, Disabled는 낮은 농도와 실제 disabled 속성으로 처리한다. Loading은 aria-busy와 작은 회전 표시를 함께 사용한다. 웹의 투명도 0.4와 상태 전환 구현은 (추정)이다. 모바일 기본 장면에는 호버가 없으므로 호버를 유일한 피드백으로 삼지 않는다. 카드의 캡슐 버튼 높이 36vp와 일반 버튼 최대 폭 448vp는 공식 규격을 참고했다.

Input: 검색은 옅은 캡슐 면 안에 돋보기와 한 줄 입력을 넣는다. Default에서는 설명을 보조색으로, Focus에서는 명확한 외곽선을, Error에서는 의미색과 오류 문구를 함께 제공한다. Disabled는 편집할 수 없음을 속성과 외관에 모두 반영한다. 예시의 설정 검색은 화면 구조를 보여 주는 입력이며 실제 설정 목록을 검색하지 않는다. 폼을 실제 서비스에 붙일 때는 입력 라벨과 오류 설명을 연결해야 한다. Placeholder만으로 필드 이름을 대신하지 않는다.

Card: .hm-widget는 공식 12vp 안전 여백과 18vp 모서리를 사용하고, 넓은 세계 시계나 긴 서비스 카드에는 22vp를 연결한다. 강조형은 내용의 의미색 또는 선택면, Outlined는 필요한 경계만 둔다. 일반 카드와 색 있는 날씨·음악 카드를 구별하며, 테마 전환 때 콘텐츠 고유 색까지 뒤집지 않는다. 카드 안에 여러 동작을 넣어 앱 전체를 축소하지 않는다. 가이드가 설명하는 짧은 정보·간단한 조작의 범위를 지킨다.

List / Switch: 공식 효율형 목록 높이는 48/56/64/72/96vp, 콘텐츠형은 64/72/80/96/120vp다. 왼쪽에는 기능을 알리는 작은 아이콘, 가운데 제목과 설명, 오른쪽에는 값·이동 표시·스위치를 놓는다. 본문과 오른쪽 액션 사이는 12vp를 기준으로 잡는다. 웹 예시의 폰 내부 행은 기기 전체 비율에 맞춰 축소한 값(추정)이다. 스위치는 위치와 색을 함께 바꾸며, 연결된 필드가 있을 때 켜짐·꺼짐에 맞춰 편집 가능 여부를 바꿔야 한다.

Badge / Navigation: 상태 배지는 Solid, Subtle, Outline을 구분한다. 열차의 대기 상태처럼 짧은 상태에는 배지를 쓰지만 모든 날짜와 숫자를 캡슐로 만들지는 않는다. 태블릿의 서비스 탐색은 왼쪽 열을 기본으로 하고, 좁은 웹 화면에서는 위쪽으로 옮긴다. 선택 항목은 배경면과 글자색으로 함께 구분한다. 일·주·월·년 탭은 한 줄에서 배타적 선택을 보여 주며 현재 탭의 대비가 나머지보다 높다.

.hm-demo,.hm-demo *{box-sizing:border-box}.hm-demo{font-family:var(--font-sans);font-size:14px;line-height:1.4;font-variant-numeric:tabular-nums;background:var(--bg-base);color:var(--text-primary);padding:0 16px 20px;max-width:1200px;margin:auto}.hm-demo h2,.hm-demo h3,.hm-demo p{margin:0}.hm-demo button,.hm-demo input{font:inherit}.hm-demo button{cursor:pointer}.hm-demo button:focus-visible,.hm-demo input:focus-visible{outline:2px solid var(--border-focus);outline-offset:3px}.hm-demo svg{max-width:100%;flex-shrink:0}.hm-demo-header{height:48px;display:flex;align-items:center;gap:7px}.hm-logo{width:107px;color:var(--text-primary)}.hm-next{font-size:10px;letter-spacing:1px;margin-top:1px}.hm-header-path{margin-left:18px;color:var(--text-secondary);font-size:12px}.hm-header-state{margin-left:auto;font-size:12px;color:var(--text-secondary);display:flex;gap:6px;align-items:center}.hm-header-state i,.hm-dot{width:6px;height:6px;border-radius:50%;background:var(--color-success-fg);display:inline-block}
.hm-screen-flow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px;align-items:start}.hm-device{height:401px;border-radius:31px;padding:3px;background:linear-gradient(100deg,#A5AFBC,#333D4B 17%,#1C2531 85%,#A8B3C1);box-shadow:var(--shadow-device);min-width:0;border:1px solid #596778}.hm-screen{contain:paint;height:100%;border:2px solid #080D16;border-radius:27px;background:var(--bg-base);position:relative;overflow:hidden}.hm-status{display:flex;justify-content:space-between;height:26px;padding:7px 12px 0;position:relative;font-size:9px;font-weight:500;z-index:1}.hm-punch{position:absolute;width:5px;height:5px;background:#070C13;border-radius:50%;top:7px;left:calc(50% - 2.5px);box-shadow:-10px 0 #070C13,10px 0 #070C13}.hm-phone-body{padding:0 10px;position:relative;z-index:1}.hm-toolbar{height:34px;display:flex;align-items:center;gap:6px}.hm-toolbar h2{font-size:21px;line-height:1.1;margin-right:auto;letter-spacing:-.4px}.hm-icon-button{width:28px;height:28px;border-radius:50%;background:var(--bg-hover);border:0;display:inline-flex;align-items:center;justify-content:center;color:inherit;padding:6px}.hm-icon-button svg{width:16px;height:16px}.hm-gesture{position:absolute;bottom:5px;left:38%;width:24%;height:3px;background:var(--text-primary);opacity:.35;border-radius:3px;z-index:2}.hm-widget{contain:paint;border-radius:var(--radius-card);background:var(--bg-widget);padding:var(--space-card);min-width:0}.hm-worlds{display:grid;grid-template-columns:repeat(4,1fr);gap:3px;padding:8px 5px;border-radius:var(--radius-card-wide)}.hm-world{display:flex;flex-direction:column;text-align:center;gap:1px;min-width:0}.hm-world b{font-size:10px;font-weight:500}.hm-world span:not(.hm-dial){font-size:10px}.hm-world small{font-size:8px;color:var(--text-secondary)}.hm-dial{display:flex;width:36px;height:36px;margin:auto;border-radius:50%;background:var(--bg-base);color:var(--text-primary)}.hm-dial svg{width:36px;height:36px}.hm-dial.night{color:#F1F3F5;background:#272D36}.hm-under{font-size:10px;text-align:center;color:var(--text-secondary);padding:4px 0 6px}.hm-widget-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.hm-weather{position:relative;display:flex;flex-direction:column;height:112px;gap:3px;padding:10px;color:white}.hm-weather{background:linear-gradient(#177DF2,#58AEFA)}.hm-weather>span{font-size:10px;position:relative;z-index:1}.hm-weather strong{font-size:31px;line-height:1.1;font-weight:500;position:relative;z-index:1}.hm-weather small{font-size:10px}.hm-weather-art{position:absolute;right:3px;top:16px;width:47px}.hm-pair{display:grid;grid-template-columns:1fr 1fr}.hm-list{background:var(--bg-elevated);border-radius:var(--radius-list);overflow:hidden}.hm-list-row{display:flex;align-items:center;gap:8px;min-height:38px;padding:6px 8px;position:relative}.hm-list-row+.hm-list-row:before{content:'';position:absolute;top:0;left:43px;right:10px;border-top:1px solid var(--border-subtle)}.hm-list-row>svg:last-child{width:11px;height:11px;color:var(--text-tertiary)}.hm-row-copy{min-width:0;flex:1;display:flex;flex-direction:column;gap:1px}.hm-row-copy b{font-size:11px;font-weight:500;white-space:nowrap}.hm-row-copy small{font-size:9px;color:var(--text-secondary)}.hm-row-value{font-size:9px;color:var(--text-secondary);white-space:nowrap}.compact .hm-list-row{min-height:35px;padding:4px 8px}.compact .hm-list-row>svg:first-child{width:24px;height:24px}.hm-search{display:flex;gap:6px;align-items:center;border-radius:var(--radius-full);padding:5px 10px;background:var(--bg-hover);min-width:0}.hm-search>svg{width:14px;height:14px;color:var(--text-secondary)}.hm-demo .hm-input{width:100%;min-width:0;background:transparent;border:0;color:var(--text-primary);outline-offset:2px;padding:0;font-size:11px}.hm-input::placeholder{color:var(--text-secondary)}.hm-input[aria-invalid=true]{outline:1px solid var(--color-error-fg)}.hm-input:disabled{color:var(--text-disabled)}.hm-profile{display:flex;gap:9px;align-items:center;padding:10px 2px}.hm-profile>div:nth-child(2){display:flex;flex-direction:column;gap:3px;flex:1;font-size:13px}.hm-profile small{font-size:10px;color:var(--text-secondary)}.hm-profile>svg{width:12px;height:12px;color:var(--text-tertiary)}.hm-avatar{width:40px;height:40px;overflow:hidden;border-radius:50%;background:#DCE8FA}.hm-avatar svg{width:40px;height:40px}.hm-switch{width:38px;height:22px;background:var(--bg-hover);border:0;border-radius:99px;position:relative;padding:0}.hm-switch span{position:absolute;left:2px;top:2px;width:18px;height:18px;border-radius:50%;background:white;box-shadow:0 1px 3px #0003}.hm-switch.on{background:var(--color-primary-500)}.hm-switch.on span{left:18px}.hm-switch:disabled{opacity:.4}
.hm-control-screen{color:#F4F7FF;background:#293E65;isolation:isolate}.hm-control-screen>.hm-wallpaper,.hm-control-screen>.hm-status,.hm-control-screen>.hm-phone-body{transform:translateZ(0)}.hm-wallpaper{position:absolute;inset:0;z-index:0;pointer-events:none}.hm-wallpaper:after{content:"";position:absolute;inset:0;background:#293E6560}.hm-wallpaper>svg{width:100%;height:100%;display:block}.hm-control-screen .hm-toolbar{height:30px}.hm-control-screen .hm-icon-button{width:23px;height:23px;padding:5px;background:#ECF4FF26}.hm-control-screen .hm-icon-button svg{width:13px;height:13px}.hm-control-screen .hm-toolbar h2{font-size:17px}.hm-control-screen .hm-gesture{background:white}.hm-control-top{display:grid;grid-template-columns:1fr 1fr;gap:8px}.hm-control-music,.hm-connection,.hm-slider{background:#ECF4FF26;border:1px solid #FFFFFF15;color:inherit}.hm-control-music{padding:8px 10px;border-radius:18px;height:96px;display:flex;flex-direction:column}.hm-mini-album{width:26px;height:26px;float:left}.hm-mini-album svg{width:26px;height:26px}.hm-control-music b{font-size:10px;margin-top:3px}.hm-control-music small{font-size:8px;opacity:.8}.hm-player{display:flex;justify-content:space-between;align-items:center;height:20px;font-size:9px}.hm-player button{border:0;background:none;color:inherit;font-size:14px;padding:0}.hm-timing{display:flex;justify-content:space-between;font-size:8px;opacity:.8}.hm-connect{display:flex;flex-direction:column;gap:8px}.hm-connection{border-radius:99px;display:flex;align-items:center;justify-content:flex-start;gap:7px;min-height:43px;padding:8px;color:inherit}.hm-connect .hm-connection{flex:1;min-width:0}.hm-connection>svg{width:23px;height:23px}.hm-connection.active{background:#0A59F7C9}.hm-connection span{display:flex;flex-direction:column;text-align:left}.hm-connection b{font-size:10px;font-weight:500}.hm-connection small{font-size:8px;opacity:.8}.hm-control-bars{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:8px}.hm-control-bars .hm-connection{min-height:31px;padding:5px 9px}.hm-control-bars svg{width:19px;height:19px}.hm-slider{position:relative;border-radius:99px;min-width:0;overflow:hidden;display:flex;align-items:center;justify-content:space-between;padding:5px 9px;font-size:9px}.hm-slider i{position:absolute;inset:0 auto 0 0;background:#DFEAFF42}.hm-slider svg,.hm-slider span{z-index:1}.hm-controls{display:grid;grid-template-columns:repeat(4,1fr);gap:6px 3px;margin-top:8px}.hm-controls>div{text-align:center;display:flex;flex-direction:column;align-items:center;gap:3px;min-width:0}.hm-controls span{font-size:8px;white-space:nowrap}.hm-round-control{border:0;width:28px;height:28px;border-radius:50%;background:#122E66A8;color:#F8FAFF;padding:5px}.hm-round-control.active{background:#2775F5}.hm-round-control svg{width:18px;height:18px}.hm-notify-settings{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-subtle)}.hm-notify-settings>div{display:flex;align-items:center;gap:12px;justify-content:space-between}.hm-notify-settings>div>span{display:flex;flex-direction:column;gap:3px}.hm-notify-settings b{font-size:12px;font-weight:500}.hm-notify-settings small{font-size:10px;color:var(--text-secondary)}.hm-notify-settings .hm-switch{flex-shrink:0}.hm-flow-captions{display:grid;grid-template-columns:repeat(3,1fr);text-align:center;font-size:11px;color:var(--text-secondary);padding:8px 0 16px}
.hm-panel{border-radius:var(--radius-card-wide);background:var(--bg-elevated);box-shadow:var(--shadow-sm);margin-bottom:20px;overflow:hidden}.hm-tablet{display:grid;grid-template-columns:162px minmax(0,1fr);min-height:476px;border:2px solid var(--border-strong)}.hm-sidebar{background:var(--bg-subtle);padding:20px 12px;display:flex;flex-direction:column;gap:15px}.hm-sidebar h2{font-size:24px}.hm-nav{display:flex;flex-direction:column;gap:3px}.hm-nav button{display:flex;align-items:center;gap:10px;border:0;border-radius:12px;padding:8px;background:none;text-align:left;color:var(--text-primary);font-size:13px}.hm-nav button.selected{background:var(--bg-selected);color:var(--color-primary-500)}.hm-sidebar-note{margin-top:auto;display:flex;flex-direction:column;gap:5px;font-size:12px}.hm-sidebar-note span,.hm-sidebar-note small{color:var(--text-secondary)}.hm-sidebar-note small{font-size:10px}.hm-tablet-content{padding:20px;min-width:0}.hm-section-head{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:16px}.hm-section-head h2{font-size:22px}.hm-section-head span{font-size:12px;color:var(--text-secondary)}.hm-tablet-widgets{display:grid;grid-template-columns:1.25fr 1fr;gap:12px}.hm-tablet-widgets>.hm-widget{background:var(--bg-base);padding:14px}.hm-travel-title{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;color:var(--text-secondary)}.hm-ticket-route{display:flex;align-items:center;justify-content:space-between;margin:14px 0 10px;gap:6px}.hm-ticket-route>div{display:flex;flex-direction:column;gap:5px;white-space:nowrap}.hm-ticket-route b{font-size:18px}.hm-ticket-route span{font-size:18px;font-weight:500}.hm-ticket-route .hm-rail{font-size:12px;color:var(--color-primary-500);text-align:center;flex:1}.hm-rail small{font-size:9px;color:var(--text-secondary)}.hm-rail i{display:block;width:100%;height:1px;background:var(--border-strong)}.hm-ticket-bottom{display:flex;justify-content:space-between;font-size:10px;color:var(--text-secondary);gap:4px}.hm-rail-drawing{height:45px;margin-top:10px;overflow:hidden}.hm-rail-drawing svg{width:100%;height:45px}.hm-delivery h3{font-size:15px;margin:11px 0 4px}.hm-delivery p{font-size:10px;color:var(--text-secondary);margin-bottom:8px}.hm-delivery .hm-btn{font-size:11px;min-height:30px;width:100%}.hm-delivery-progress{height:4px;display:flex;background:var(--border-default);justify-content:space-between;margin:16px 5px 8px;position:relative}.hm-delivery-progress:before{content:'';position:absolute;width:67%;height:4px;left:0;background:var(--color-primary-500)}.hm-delivery-progress i{width:7px;height:7px;border-radius:50%;background:var(--color-primary-500);margin-top:-1.5px;z-index:1}.hm-delivery-progress i:last-child{background:var(--border-strong)}.hm-delivery-labels{display:flex;justify-content:space-between;font-size:9px;margin-bottom:12px}.hm-tablet-widgets .hm-tablet-weather{grid-column:1;display:grid;grid-template-columns:104px 1fr;padding:0;overflow:hidden;background:linear-gradient(125deg,#177DF2,#55A8F5);color:white;min-height:158px}.hm-tablet-weather>.hm-weather{background:none;height:auto;padding:16px 10px}.hm-tablet-weather>div:nth-child(2){padding:16px 10px 10px 0;min-width:0}.hm-tablet-weather h3{font-size:12px;margin-bottom:10px}.hm-tablet-weather small{font-size:8px}.hm-forecast{display:flex;justify-content:space-between;gap:2px;margin-bottom:12px}.hm-forecast>div{display:flex;flex-direction:column;align-items:center;font-size:9px}.hm-forecast svg{width:29px;height:28px}.hm-memo header{display:flex;justify-content:space-between;align-items:center;gap:5px;margin-bottom:12px}.hm-memo h3{font-size:15px}.hm-memo label{display:flex;align-items:center;gap:6px;font-size:11px;margin:9px 0}.hm-memo input{accent-color:#E7B530;margin:0}.hm-memo-foot{font-size:9px;color:var(--text-secondary)}.hm-tablet-footer{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:16px;font-size:11px;color:var(--text-secondary)}
.hm-btn{border:0;border-radius:var(--radius-full);min-height:36px;max-width:448px;padding:7px 18px;display:inline-flex;align-items:center;justify-content:center;font-size:13px;font-weight:500;white-space:nowrap;color:var(--text-primary);background:var(--bg-hover)}.hm-btn-primary{color:var(--text-on-primary);background:var(--color-primary-500)}.hm-btn-secondary{color:var(--color-primary-500);background:var(--bg-selected)}.hm-btn-ghost{color:var(--color-primary-500);background:transparent}.hm-btn-danger{color:var(--text-on-primary);background:var(--color-error-fg)}.hm-btn:hover{box-shadow:inset 0 0 0 999px var(--state-hover)}.hm-btn:active{box-shadow:inset 0 0 0 999px var(--state-pressed)}.hm-btn:disabled,.hm-btn[aria-disabled=true]{opacity:.4;pointer-events:none}.hm-btn[aria-busy=true]{pointer-events:none}.hm-btn[aria-busy=true]:before{content:'';width:12px;height:12px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;margin-right:8px;animation:hm-spin 1s linear infinite}.hm-tag{font-size:10px;padding:2px 8px;border-radius:99px;background:var(--color-primary-500);color:white;white-space:nowrap}.hm-tag-subtle{color:var(--color-primary-500);background:var(--bg-selected)}.hm-tag-outline{color:var(--text-secondary);background:none;border:1px solid var(--border-default)}.hm-widget.outlined{background:none;border:1px solid var(--border-default)}.hm-widget.emphasized{background:var(--bg-selected)}
.hm-agenda{display:grid;grid-template-columns:285px minmax(0,1fr);padding:22px;gap:26px}.hm-month header{display:flex;justify-content:space-between;align-items:center;margin-bottom:15px}.hm-month h2{font-size:20px}.hm-month .hm-btn{font-size:12px;padding:4px 8px}.hm-week,.hm-month-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center}.hm-week b{font-size:10px;font-weight:400;color:var(--text-secondary)}.hm-month-grid span{height:36px;display:flex;align-items:center;justify-content:center;font-size:13px;position:relative}.hm-month-grid .outside{color:var(--text-tertiary)}.hm-month-grid .today{border-radius:50%;background:var(--color-primary-500);color:white}.hm-month-grid i{position:absolute;width:3px;height:3px;background:var(--color-primary-500);border-radius:50%;bottom:3px}.hm-month-grid .today i{background:white}.hm-calendar-legend{display:flex;gap:16px;margin-top:15px;font-size:10px;color:var(--text-secondary)}.hm-calendar-legend i{display:inline-block;width:5px;height:5px;border-radius:50%;margin-right:5px;background:var(--color-primary-500)}.hm-calendar-legend span:nth-child(2) i{background:var(--color-success-fg)}.hm-calendar-legend span:nth-child(3) i{background:var(--color-warning-fg)}.hm-day .hm-section-head{margin-bottom:8px}.hm-day .hm-section-head h2{font-size:19px}.hm-day .hm-section-head span{font-size:11px}.hm-tabs{background:var(--bg-hover);border-radius:99px;display:flex;padding:3px;margin:10px 0}.hm-tabs button{flex:1;background:none;border:0;border-radius:99px;font-size:12px;color:var(--text-secondary);padding:5px}.hm-tabs button.active{background:var(--bg-elevated);color:var(--color-primary-500);box-shadow:var(--shadow-sm)}.hm-agenda-event{display:flex;align-items:center;gap:12px;min-height:63px;border-bottom:1px solid var(--border-subtle)}.hm-agenda-event:last-child{border:0}.hm-agenda-event time{font-size:12px;align-self:center;min-width:38px}.hm-agenda-event time small{font-size:10px;color:var(--text-secondary)}.hm-agenda-event>div{border-left:3px solid var(--color-primary-500);padding-left:10px;flex:1;min-width:0}.hm-agenda-event.green>div{border-color:var(--color-success-fg)}.hm-agenda-event.orange>div{border-color:var(--color-warning-fg)}.hm-agenda-event h3{font-size:13px;font-weight:500}.hm-agenda-event span{font-size:10px;color:var(--text-secondary)}.hm-agenda-event .hm-btn{font-size:10px;padding:5px 10px;min-height:29px}
.hm-notifications{padding:22px}.hm-notice-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.hm-notice{display:flex;align-items:flex-start;gap:10px;padding:14px 12px;border-radius:var(--radius-card);background:var(--bg-base);min-width:0}.hm-notice>svg{width:29px;height:29px}.hm-notice>div{min-width:0;flex:1}.hm-notice header{display:flex;justify-content:space-between;align-items:center;gap:6px;font-size:10px;margin-bottom:10px}.hm-notice header time{color:var(--text-secondary);font-size:9px}.hm-notice h3{font-size:12px;margin-bottom:6px}.hm-notice p{font-size:10px;line-height:1.8;color:var(--text-secondary)}.hm-notice-actions{display:flex;gap:12px;margin-top:9px;flex-wrap:wrap}.hm-notice .hm-btn{font-size:10px;padding:0;min-height:24px}.hm-notifications>footer{margin-top:15px;display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--text-secondary)}.hm-notifications>footer .hm-btn{font-size:11px}.hm-page-foot{display:flex;justify-content:space-between;gap:15px;font-size:11px;color:var(--text-secondary)}

.hm-status-right{display:flex;gap:3px;align-items:center;height:11px}.hm-sheet-handle{width:31px;height:3px;background:var(--text-tertiary);border-radius:3px;margin:0 auto 3px}.hm-card-center .hm-toolbar{height:29px}.hm-card-center .hm-worlds{padding:5px}.hm-card-center .hm-under{padding:2px 0 3px;font-size:9px}.hm-card-center .hm-weather{height:90px;padding:8px;gap:2px}.hm-card-center .hm-weather strong{font-size:27px}.hm-card-center .hm-weather-art{width:39px;top:14px}.hm-card-center .hm-weather small,.hm-card-center .hm-weather>span{font-size:9px}.hm-card-center .compact .hm-list-row{min-height:27px;padding:3px 8px}.hm-card-center .compact .hm-list-row>svg:first-child{width:21px;height:21px}.hm-card-center .compact .hm-row-copy b{font-size:10px}.hm-stress{height:90px;position:relative;overflow:hidden;background:#00BFAA;color:white;display:flex;flex-direction:column;padding:8px;gap:1px}.hm-stress>svg{position:absolute;width:100%;height:100%;inset:0}.hm-stress>span,.hm-stress>strong,.hm-stress>button{position:relative}.hm-stress>span{font-size:9px}.hm-stress strong{font-size:27px;line-height:1.15;font-weight:600}.hm-stress small{font-size:9px;font-weight:400;margin-left:4px}.hm-stress button{border:0;border-radius:99px;background:white;color:#008E96;font-size:9px;display:flex;align-items:center;justify-content:center;gap:4px;min-height:21px;margin-top:auto;padding:2px 3px}.hm-stress button svg{width:13px;height:13px}.hm-setting-symbol{width:28px;height:28px;display:flex;align-items:center;justify-content:center;flex-shrink:0;border-radius:9px;color:white;background:#3478E5}.hm-setting-symbol svg{width:19px;height:19px}.hm-setting-symbol.data{background:#31AC62}.hm-setting-symbol.palette{background:#CC67AF}.hm-setting-symbol.sun{background:#E58B26}.hm-setting-symbol.volume{background:#D85557}.hm-weather-details{grid-column:1/-1;display:grid;grid-template-columns:repeat(4,1fr);gap:4px;border-top:1px solid #FFFFFF38;margin:0 10px;padding:10px 0 14px}.hm-weather-details span{display:flex;flex-direction:column;gap:4px;font-size:9px;text-align:center}.hm-weather-details b{font-size:12px;font-weight:500}.hm-upcoming{margin-top:17px;padding-top:12px;border-top:1px solid var(--border-subtle);font-size:10px}.hm-upcoming>b{font-weight:500}.hm-upcoming>div{display:flex;gap:10px;margin-top:8px;color:var(--text-secondary)}.hm-upcoming time{min-width:62px;color:var(--color-primary-500)}.hm-agenda-event>svg{width:23px;height:23px;color:var(--text-secondary)}

@media(max-width:700px){.hm-demo{padding:0 12px 18px}.hm-header-path{display:none}.hm-screen-flow{grid-template-columns:1fr;gap:16px;max-width:310px;margin:auto}.hm-device{height:472px}.hm-phone-body{padding:0 15px}.hm-toolbar{height:42px}.hm-worlds{padding:12px 8px}.hm-card-center .hm-worlds{padding:9px 8px}.hm-card-center .hm-toolbar{height:36px}.hm-card-center .hm-weather,.hm-card-center .hm-stress{height:114px;padding:10px}.hm-card-center .hm-weather-art{width:47px;top:22px}.hm-card-center .hm-weather>span,.hm-card-center .hm-weather small{font-size:11px}.hm-card-center .hm-weather strong,.hm-card-center .hm-stress strong{font-size:31px}.hm-card-center .hm-stress>span{font-size:11px}.hm-card-center .hm-stress button{min-height:25px;font-size:10px}.hm-card-center .compact .hm-list-row{min-height:32px}.hm-card-center .compact .hm-row-copy b{font-size:11px}.hm-card-center .hm-under{padding:4px 0;font-size:10px}.hm-dial,.hm-dial svg{width:42px;height:42px}.hm-world b{font-size:11px}.hm-widget-grid{gap:12px}.hm-weather{height:130px;padding:12px}.hm-weather>span,.hm-weather small{font-size:12px}.hm-flow-captions{display:none}.hm-screen-flow{margin-bottom:20px}.hm-controls{gap:9px 6px}.hm-round-control{width:36px;height:36px}.hm-controls span{font-size:9px}.hm-control-top{margin-top:5px}.hm-control-music{height:121px}.hm-control-bars{gap:10px}.hm-list-row{min-height:42px}.hm-row-copy b{font-size:12px}.hm-tablet{display:block;min-height:0}.hm-sidebar{padding:16px}.hm-sidebar h2{font-size:22px}.hm-sidebar .hm-search,.hm-sidebar-note{display:none}.hm-nav{flex-direction:row;overflow-x:auto;gap:8px;padding-bottom:4px}.hm-nav button{flex-direction:column;white-space:nowrap;gap:5px;min-width:43px;padding:5px 3px;font-size:10px}.hm-tablet-content{padding:15px}.hm-tablet-widgets{grid-template-columns:1fr}.hm-tablet-widgets .hm-tablet-weather{grid-column:auto}.hm-tablet-footer{flex-wrap:wrap}.hm-section-head h2{font-size:21px}.hm-agenda{display:block;padding:17px}.hm-month{margin-bottom:24px}.hm-month-grid span{height:39px}.hm-day .hm-section-head h2{font-size:18px}.hm-agenda-event{gap:8px;min-height:73px}.hm-agenda-event>div{padding-left:7px}.hm-agenda-event .hm-btn{font-size:9px;padding:4px 7px}.hm-agenda-event span{font-size:9px}.hm-notifications{padding:16px}.hm-notice-grid,.hm-notify-settings{grid-template-columns:1fr}.hm-notice{padding:14px}.hm-notice p{font-size:12px}.hm-notice h3{font-size:14px}.hm-notice header{font-size:12px}.hm-notice header time{font-size:10px}.hm-notice .hm-btn{font-size:12px}.hm-page-foot{font-size:10px;flex-direction:column;gap:5px}}

Motion

Motion

공식 애니메이션 속성 문서는 단순한 색 변화 100ms, 스위치 150ms, 목록 삭제 200ms, 회전 300ms, 큰 이미지 펼침 350ms처럼 행동의 범위에 따라 시간을 나눈다. 모든 동작에 같은 300ms를 붙이는 방식보다 움직이는 면적과 사용자가 기다리는 목적에 맞춘다. 아래의 빠른·기본·느린 변수는 재사용 편의를 위한 웹 이름이며, 공식 예제의 값을 옮겨 연결했다. 스위치 전용 시간과 시트 전용 시간을 따로 남겼다.

곡선도 용도를 나눈다. 표준 cubic-bezier(.4,0,.2,1)은 변화의 시작과 끝을 부드럽게 연결하고, 감속 cubic-bezier(0,0,.4,1)은 새 요소가 나타나 멈출 때 쓴다. 문서에는 다른 곡선과 물리 스프링 매개변수도 있지만 이를 전부 같은 cubic-bezier로 대체하지 않는다. 공식 스프링의 질량·강성·감쇠는 물리 모델의 매개변수다. 그 결과를 정적 SVG에 복사해 흔드는 것이 운영체제의 자연스러운 움직임을 재현하는 일은 아니다.

:root {
  --duration-fast: 100ms; /* 공식 색 변화 예시 */
  --duration-switch: 150ms; /* 공식 스위치 예시 */
  --duration-base: 200ms; /* 공식 목록 삭제 예시 */
  --duration-rotate: 300ms; /* 공식 회전 예시 */
  --duration-slow: 350ms; /* 공식 큰 그림 펼침 예시 */
  --ease-out: cubic-bezier(0,0,.4,1);
  --ease-in-out: cubic-bezier(.4,0,.2,1);
}
.hm-btn,.hm-nav button,.hm-tabs button { transition:background-color var(--duration-fast) var(--ease-in-out),color var(--duration-fast) var(--ease-in-out); }
.hm-switch,.hm-switch span { transition:background-color var(--duration-switch) var(--ease-in-out),left var(--duration-switch) var(--ease-in-out); }
@keyframes hm-spin { to { transform:rotate(360deg); } }
@media(prefers-reduced-motion:reduce) {
  .hm-demo *, .hm-demo *::before, .hm-demo *::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; }
}

움직임 줄이기 설정에서는 회전 표시를 멈추거나 단순한 진행 문구로 대체하고, 이동 거리를 줄인다. 이 문서의 CSS는 reduced-motion에서 전환과 애니메이션을 끄고 즉시 상태를 바꾼다. 색 변화가 사라져도 선택 여부와 버튼 의미가 남아야 한다. 로딩은 aria-busy와 문구로도 알리므로 회전만이 유일한 단서가 되지 않는다. 화면을 스크롤할 때 자동 패럴랙스나 배경의 떠다니는 움직임은 넣지 않았다.

Anti-patterns

Anti-patterns

1. 모든 서비스를 같은 파란 둥근 상자로 만들기. 날씨는 날씨의 그림과 온도, 음악은 앨범과 재생, 건강은 숫자와 진행률이 먼저 보여야 한다. 파랑은 시스템 행동을 연결하는 역할이며, 카드마다 다른 콘텐츠를 지우는 바탕색이 아니다. 같은 너비의 숫자 카드만 반복하면 홈 격자와 서비스 카드의 관계가 사라진다. 해결 방법은 실제 1×2·2×2·2×4 슬롯을 고르고 각 카드에서 가장 중요한 정보 하나를 정하는 것이다.

2. 공식 단위와 웹 픽셀, 현재 문서와 초기 NEXT 화면을 섞기. 네이티브 vp·fp, 기기 물리 픽셀, 룩북 축소 CSS px는 같은 값이 아니다. 또한 중문 대문의 최신 버전 이름만 보고 모든 규칙을 NEXT 출시 규정으로 부를 수 없다. 공식 수치는 출처와 단위를 남기고, 웹에서 옮긴 모서리·행간·그림자는 (추정)으로 표시한다. 공개 표의 모순도 임의로 고치지 않고 이번 재현에서 채택한 값과 이유를 적는다.

3. 다크 판을 검정 바탕과 흰 글자만으로 끝내기. 페이지, 목록, 위젯이 다른 명도여야 하고 보조 글자와 구분선도 함께 바뀌어야 한다. 공식 다크 가이드는 일반 본문의 높은 대비와 눈부심 억제를 함께 다룬다. 작은 글자를 40% 흰색에 일괄 연결하지 말고 역할에 맞춰 90%와 60%를 우선 쓴다. 큰 흰 면의 갑작스러운 출현도 피한다. 날씨나 음악처럼 콘텐츠 고유 색이 있는 카드의 테마 처리는 일반 카드와 구별한다.

4. 둥근 바깥 틀 안에 둥근 틀을 계속 중첩하고 아이콘을 복제하기. 카드 안의 값마다 작은 알약을 붙이면 안전 여백을 잃고 읽는 순서가 무너진다. 상태는 텍스트·세로선·진행 막대 중 필요한 표현만 고른다. 앱 아이콘은 바탕 마스크만 공유하고 수화기, 말풍선, 꽃잎, 렌즈처럼 서로 다른 전경을 써야 한다. 금속 기기 프레임과 앱 카드의 모서리도 같은 수치로 묶지 않는다. 작은 화면일수록 재질과 역할의 차이를 단순하지만 정확하게 남긴다.

5. 작은 미리보기의 밀도를 실제 조작 규격으로 복사하기. 이 룩북은 280×210 안에서 전체 기기와 확대 카드를 함께 보여 준다. 그 안의 작은 글자나 버튼이 실제 앱에서 권장되는 크기는 아니다. 실서비스는 시스템 글자 배율과 터치 영역을 따르고, 입력·오류·로딩·빈 상태를 별도로 검수한다. 한 화면을 넓게 캡처한 뒤 무조건 축소하면 글자가 사라지므로, 작은 폭에서는 열을 바꾸고 중요한 정보부터 보이게 한다.

정보량을 늘릴 때는 실제 서비스에 있을 법한 내용을 더한다. 의미 없는 태그나 색상 칩을 붙여 빈 면을 채우지 않는다. 일정의 장소와 시간, 택배의 단계와 도착 예상, 제어 센터의 연결 이름은 화면을 이해하는 데 도움이 된다. 같은 항목을 숫자만 바꿔 반복하는 것은 실제 목록이 그런 구조일 때만 한다. 위젯의 큰 값과 작은 문구가 서로 겹치지 않는지, 다크에서 보조 정보가 사라지지 않는지, 화면 아래에도 이어지는 정보가 충분한지 함께 확인한다.

Sources

출처

  1. https://developer.huawei.com/consumer/cn/design/
  2. https://developer.huawei.com/consumer/en/design/
  3. https://consumer.huawei.com/cn/harmonyos-next/
  4. https://developer.huawei.com/consumer/en/doc/design-guides/design-concepts-0000001795698445
  5. https://developer.huawei.com/consumer/cn/doc/design-guides/color-0000001776857164
  6. https://developer.huawei.com/consumer/cn/doc/design-guides/font-0000001828772001
  7. https://developer.huawei.com/consumer/cn/doc/doccenter-ux-design/typography-0000002622688363
  8. https://developer.huawei.com/consumer/cn/doc/doccenter-ux-design/application-icon-0000001953444009
  9. https://developer.huawei.com/consumer/cn/doc/design-guides/design-layout-basics-0000001795579413
  10. https://developer.huawei.com/consumer/cn/doc/design-guides/system-features-service-widget-0000002087671904
  11. https://developer.huawei.com/consumer/cn/doc/design-guides/dark-mode-0000001823255497
  12. https://developer.huawei.com/consumer/cn/doc/design-guides/button-0000001929683228
  13. https://developer.huawei.com/consumer/cn/doc/design-guides/list-0000001929853910
  14. https://developer.huawei.com/consumer/cn/doc/design-guides/toggleswitch-0000001956852745
  15. https://developer.huawei.com/consumer/cn/doc/design-guides/animation-attributes-0000001797117229
  16. https://developer.huawei.com/images/new_header/HarmonyOS0407.svg

HarmonyOS NEXT 이름과 로고는 각 권리자의 상표입니다.