대시보드
Morit Plugin3. 화면과 사용자 경험

토큰, 크기, 색, 여백, 반응형

Runtime v2는 기본적으로 Morit의 Material 3 theme를 사용합니다. 플러그인은 전체 앱의 theme를 바꾸지 않고 자신의 extension 범위 안에서만 제한된 theme와 node props를 적용합니다.

Extension theme

json
{
  "theme": {
    "radius": 18,
    "spacing": 12,
    "density": "standard",
    "surface": {"elevation": 1},
    "border": {"width": 1},
    "icon": {"size": 22},
    "typography": {"scale": 1.0, "body_weight": 400, "title_weight": 700},
    "states": {"disabled_opacity": 0.38},
    "light": {
      "color_scheme": {
        "primary": "#315DA8",
        "on_primary": "#FFFFFF",
        "surface": "#F9F9FF",
        "on_surface": "#1A1B20"
      }
    },
    "dark": {
      "color_scheme": {
        "primary": "#AFC6FF",
        "on_primary": "#002F66",
        "surface": "#111318",
        "on_surface": "#E2E2E9"
      }
    }
  }
}
  • radius: 0~64
  • spacing: 0~32
  • density: compact, standard, comfortable
  • color_scheme: Material role과 #RRGGBB 또는 #AARRGGBB
  • typography: scale 0.81.4, body/title weight 100900
  • surface: color, container_color, elevation 0~24
  • border: color, width 08, radius 064
  • icon: color, size 12~64
  • states: disabled_opacity 0.2~0.8, selected_color, focus_color
  • light, dark: 위 필드의 mode별 partial override

최상위 base → 현재 mode variant → Host Material 3 theme 순서로 병합됩니다. 누락한 role은 Host가 채우므로 기존 플러그인은 선언을 추가하지 않아도 앱의 라이트·다크 모드를 따릅니다. 명백히 같은 literal 전경/배경은 validate 오류이며 계산 가능한 4.5:1 미만 조합은 경고입니다. 대비가 확인된 작은 palette만 override하고 모든 role을 임의로 복제하지 않습니다.

색상 token

node의 color, background_color, foreground_color, border_color는 다음 semantic token이나 hex를 사용합니다.

text
primary, on_primary, primary_container, on_primary_container
secondary, on_secondary, secondary_container, on_secondary_container
tertiary, on_tertiary, tertiary_container, on_tertiary_container
error, on_error, error_container, on_error_container
surface, on_surface, surface_variant, on_surface_variant
outline, outline_variant
inverse_surface, inverse_on_surface, inverse_primary
shadow, scrim, transparent

semantic token을 우선합니다. hex는 브랜드 식별이나 데이터 범례처럼 의미가 명확하고 light/dark 대비를 직접 확인한 경우에만 사용합니다. 상태를 색 하나로만 표현하지 말고 아이콘·문구를 함께 제공합니다.

여백

paddingmargin은 0~128 숫자 하나 또는 다음 세 형태 중 하나입니다.

json
16
json
{"all": 16}
json
{"horizontal": 16, "vertical": 12}
json
{"left": 16, "top": 8, "right": 16, "bottom": 20}

형태를 섞을 수 없습니다. spacing은 children 사이 간격이며 0~128입니다. 화면 가장자리 여백은 Host가 제공하므로 root에 과도한 padding을 중복하지 않습니다.

크기와 surface

prop범위
width, height, min/max variants0~4096
border_width0~8
border_radius0~64
elevation0~24
opacity0~1
aspect_ratio0.1~20
size, max_lines, columns, limit정수 0~100

min_width <= max_width, min_height <= max_height여야 합니다. 고정 widthheight는 아이콘, avatar, 썸네일처럼 크기 의미가 있는 항목에만 쓰고, 본문 카드에는 min/max 제약과 자연 크기를 사용합니다.

정렬

alignment:

text
top_left, top_center, top_right
center_left, center, center_right
bottom_left, bottom_center, bottom_right

main_axis_alignmentstart, end, center, space_between, space_around, space_evenly를 사용합니다. cross_axis_alignmentstart, end, center, stretch, baseline을 사용합니다. main_axis_sizemin 또는 max입니다.

텍스트 alignstart, end, left, right, center, justify입니다. 다국어 화면에는 물리 방향 left/right보다 논리 방향 start/end가 안전합니다.

반응형 규칙

Row 전환

json
{
  "type": "row",
  "props": {"spacing": 12, "stack_at": 480},
  "children": []
}

가용 폭이 stack_at보다 작으면 세로로 배치합니다. 입력과 버튼, 두 개 이상의 긴 텍스트가 있는 row에는 480 전후를 시작점으로 사용하고 실제 큰 글자 크기에서 확인합니다.

Grid 열 축소

json
{
  "type": "grid",
  "props": {"columns": 3, "min_item_width": 160, "spacing": 12},
  "children": []
}

columns는 희망 최대 열 수이고, Host는 min_item_width 96~600을 지키도록 열을 줄입니다. 모바일 가로 폭을 채우기 위해 글자와 숫자를 지나치게 압축하지 않습니다.

Adaptive navigation

navigation.type: "adaptive"는 좁은 화면의 navigation bar와 넓은 화면의 rail/drawer를 Host가 선택하게 합니다. rail_breakpoint는 480~1600이며 꼭 필요한 경우에만 기본값을 조정합니다.

접근성과 동적 크기

  • 중요한 텍스트는 max_lines로 잘라 의미를 잃지 않게 합니다.
  • 버튼은 icon만 두지 말고 label을 제공합니다.
  • 이미지와 의미 있는 icon에는 semantic_label을 제공합니다.
  • 작은 dense 목록은 스캔 중심 화면에만 사용합니다.
  • light/dark theme, 시스템 큰 글자, 320px급 폭, tablet/desktop 폭에서 확인합니다.
  • animation이나 색 변화가 없어도 현재 선택과 진행 상태를 알 수 있어야 합니다.