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

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

Runtime v2와 v3는 기본적으로 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 대비를 직접 확인한 경우에만 사용합니다. 상태를 색 하나로만 표현하지 말고 아이콘·문구를 함께 제공합니다.

여백

padding과 margin은 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여야 합니다. 고정 width와 height는 아이콘, avatar, 썸네일처럼 크기 의미가 있는 항목에만 쓰고, 본문 카드에는 min/max 제약과 자연 크기를 사용합니다.

정렬

alignment:

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

main_axis_alignment은 start, end, center, space_between, space_around, space_evenly를 사용합니다. cross_axis_alignment은 start, end, center, stretch, baseline을 사용합니다. main_axis_size는 min 또는 max입니다.

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

반응형 규칙

모바일 기본값

모바일에서는 한 화면에 한 가지 주 작업만 두고, 제목·상태·주요 행동 순서로 짧은 세로 흐름을 만듭니다. 장식용 surface 중첩과 별도 색을 줄이고 Host의 typography, semantic color, 기본 여백을 우선합니다. 자주 쓰는 행동은 엄지로 닿는 하단 navigation/action에 두되 파괴적 행동과 붙이지 않습니다. 320px 폭과 큰 글자에서도 가로 스크롤 없이 핵심 문구와 행동이 남아야 합니다.

  • 한 화면의 primary action은 하나를 기본으로 합니다.
  • 긴 설정 form은 의미 단위 screen이나 section으로 나누고 입력값을 보존합니다.
  • 짧은 목록은 card보다 divider와 여백으로 계층을 만들고, card 안에 card를 넣지 않습니다.
  • hover에만 정보를 두지 않고 tap, keyboard focus, screen reader에서 같은 의미를 제공합니다.

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이나 색 변화가 없어도 현재 선택과 진행 상태를 알 수 있어야 합니다.

SDK 1.7.13: 그라데이션과 가로 카드 목록

아래 속성에는 min_morit_version: "1.7.13" 이상이 필요합니다. 구형 앱은 해당 플러그인의 UI를 로드하지 않으며 호환되지 않는 업데이트로 동작 중인 설치를 덮어쓰지 않습니다. 기존 v1/v2 화면과 세로 목록은 그대로 유지됩니다.

  • gradient_colors: 2~8개의 기존 색 토큰 또는 HEX 색상. 왼쪽 위에서 오른쪽 아래로 연결합니다. surface와 card에서도 클릭 효과 아래에 그려집니다. 콘텐츠의 color를 명시해 대비를 확보합니다.
  • list.props.scroll_direction: "horizontal": 자동 재생 없는 가로 카드 목록입니다. height는 기본 280dp, min_item_width는 기본 280dp이며 좁은 화면에서는 다음 카드 일부가 보입니다.
  • list.props.item_key: 결과 항목의 고유한 필드 이름입니다. 서버가 변하지 않는 ID를 제공해야 합니다.
  • 목록 limit은 최대 100입니다. 기본값은 20이며 대량 데이터는 데이터 소스에서 페이지를 나눕니다.

data.news.data.items를 반환하는 news 데이터 소스가 있는 화면의 예:

json
{
  "type": "list",
  "props": {
    "source": "data.news.data.items",
    "item_key": "id",
    "scroll_direction": "horizontal",
    "height": 240,
    "min_item_width": 280,
    "spacing": 12
  },
  "children": [{
    "type": "surface",
    "props": {
      "gradient_colors": ["#00856A", "#176CB3"],
      "border_radius": 18,
      "padding": 20
    },
    "children": [{
      "type": "text",
      "props": {"text": "{{item.title}}", "color": "#FFFFFF", "style": "title", "max_lines": 4}
    }]
  }]
}

브랜드 색상·이미지·장식은 정보 계층을 돕는 범위에서 유지합니다. 모든 플러그인을 같은 무채색 카드로 만들 필요는 없습니다. 라이트·다크 테마는 각각 읽기 편한 배경과 글자색을 지정합니다.

글자와 상호작용 표현

text는 font_size(1064), font_weight(100900, 100 단위), line_height(1~2.5)를 선택적으로 지정합니다. 시스템 글자 확대는 그대로 적용됩니다. 가로 목록의 높이도 글자 확대를 반영합니다. selected_background_color, selected_foreground_color는 selected: true일 때 적용하며, disabled_background_color는 비활성 상태에 적용합니다. surface와 card는 pressed_color로 Material 터치 효과를 지정할 수 있습니다. 기본 색·선택 표시·터치 효과는 속성을 생략하면 유지됩니다.

4종 디자인 예제를 참고하세요.