Skip to content

feat(android): the screen frame — rail, pinned list, one body column, top bar on its lines (D-052, 0.7.0) - #147

Merged
jlc488 merged 24 commits into
mainfrom
feat/android-screen-frame
Nov 12, 2026
Merged

jlc488 merged 24 commits into
mainfrom
feat/android-screen-frame

Conversation

@jlc488

@jlc488 jlc488 commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

What

DDS Android 0.7.0 — the screen frame (D-052). The numbers were there, but nothing made a screen keep to them. Now one frame decides the menus from the window width and every screen stands on one column.

  • DdsAppFrame draws the rail (from 600dp) and a pinned list (from 840dp) outside the screen switcher, so they do not move while a screen changes. A top-level screen draws the bottom tabs with the new DdsScaffold(topBar, modifier, bottomTabs, content), so an inner screen covers them.
  • The body column — DdsBodyColumn / Modifier.ddsBody(): at most 680dp with its gutters (16dp below 600, 24dp from there), in the middle of what the rail and the list leave. Every screen of a window starts on the same line.
  • The top bar keeps to the body's lines — DdsTopBar(onBack = …): the arrow and the last icon stand on the body's start and end lines; the title starts at the same place after an arrow or a mark; one tall height for the whole window when any title needs two lines.
  • A screen with one thing to do — DdsCenteredColumn / DdsCenteredTitle: one block of at most 400dp in the middle. It keeps clear of the bars and the keyboard, paints the page and slides like a screen.
  • The pinned list's rows — DdsPaneList / DdsPaneItem, chosen like the rail.
  • New artifact kr.devslab:dds-compose-testing — DdsFrameCheck lets an app check its own screens against the frame in its device tests. It brings Espresso 3.7.0, which runs on Android 17.
  • The catalog runs on the frame and has a Layout page.

If you move up

  • A positional DdsTopBar(title, Modifier, { mark }, { actions }) no longer compiles: the fourth parameter is now onBack. Pass actions by name or as the trailing lambda. The DdsTopBar change is binary-incompatible for a library compiled against 0.6.0.
  • Action icons in the top bar were 12dp apart; now they sit side by side.
  • The rest is opt-in. The guide §13 and the changelog list each visible change.

Verified

  • Unit 82, lint, build, pnpm run verify, verify:source:stage1-2: green.
  • Whole device suite on a phone (SM-F971N, Android 17), read from the result files: folded (1248x1972) 170 run, 0 failed, 0 errors, 2 skipped; unfolded (2448x1848, the wide window with the rail and the list) at the final code, 174 run, 0 failed, 0 errors, 2 skipped. The two skipped are the menu's exact-color checks, which cannot run on that phone's tinted capture (as in 0.6.0).
  • The frame tests force 475×751, 704×933 and 933×704 inside the test; a sample app is walked with DdsFrameCheck at all three.
  • The catalog was captured on an emulator at the three windows (lines drawn on the captures) and looked at.

Not verified

  • An app on its phone (JeongsanNow moving to the local build and checking three windows) — the release waits for this (spec §3).
  • The back swipe; a real side cutout; right-to-left on a device; TalkBack listened to.
  • Two sample-app assertions (page color, assertSameLines) were never seen failing.
  • Resolving the three artifacts from a separate app; the release workflow with the third artifact.

Release

Not released by this PR. After merge and after JeongsanNow's phone check: tag android-v0.7.0 (with the release checklist), then confirm on Maven Central.


무엇을

DDS 안드로이드 0.7.0, 화면 틀(D-052). 숫자는 정해져 있었지만 화면이 그 숫자를 지키게 하는 장치가 없었다. 이제 틀 하나가 창 폭으로 메뉴를 정하고, 모든 화면이 본문 기둥 하나 위에 선다.

  • DdsAppFrame: 레일(600dp부터)과 고정 목록(840dp부터)을 화면 전환 바깥에 그린다. 그래서 화면이 바뀌는 동안 움직이지 않는다. 하단 탭은 최상위 화면이 새 DdsScaffold(topBar, modifier, bottomTabs, content)로 그린다. 그래서 안쪽 화면이 탭을 덮는다.
  • 본문 기둥(DdsBodyColumn / Modifier.ddsBody()): 여백 포함 최대 680dp다. 여백은 600dp 미만에서 16dp, 그 이상에서 24dp이고, 레일과 목록이 남긴 자리의 가운데에 선다. 한 창의 모든 화면이 같은 선에서 시작한다.
  • 상단 줄이 본문 선을 따른다(DdsTopBar(onBack = …)): 화살표와 마지막 아이콘이 본문의 시작선과 끝선에 선다. 제목은 화살표 뒤든 로고 뒤든 같은 자리에서 시작한다. 한 제목이라도 두 줄이 필요하면 창 전체가 같은 높은 줄을 쓴다.
  • 한 가지 일만 하는 화면(DdsCenteredColumn / DdsCenteredTitle): 최대 400dp 블록 하나를 가운데에 둔다. 상태 표시줄과 키보드를 피하고, 페이지 색을 칠하고, 화면처럼 밀려 들어온다.
  • 고정 목록의 행(DdsPaneList / DdsPaneItem): 고른 표시는 레일과 같다.
  • 새 꾸러미 kr.devslab:dds-compose-testing: 앱이 기기 테스트에서 DdsFrameCheck로 자기 화면이 틀을 지키는지 검사한다. Android 17에서 도는 Espresso 3.7.0을 함께 가져온다.
  • 카탈로그를 이 틀로 옮기고 Layout 쪽을 더했다.

버전만 올리면

  • DdsTopBar(title, Modifier, { mark }, { actions })처럼 위치로 넘긴 호출은 컴파일되지 않는다. 네 번째 인자가 이제 onBack이기 때문이다. actions는 이름으로 넘기거나 맨 뒤 람다로 넘긴다. 0.6.0으로 컴파일한 라이브러리와는 바이너리 호환이 깨진다.
  • 상단 줄의 동작 아이콘 사이 12dp 간격이 없어지고 나란히 붙는다.
  • 나머지는 앱이 골라 쓰는 것이다. 눈에 보이는 바뀜은 가이드 §13과 변경 기록에 적었다.

확인한 것

  • 단위 테스트 82개, 린트, 빌드, pnpm run verify, verify:source:stage1-2 통과.
  • 실물 폰(SM-F971N, Android 17)에서 기기 테스트 전체를 돌리고 결과 파일로 읽었다.
    • 접은 화면(1248x1972): 170개 실행, 실패 0, 오류 0, 건너뜀 2.
    • 펼친 화면(2448x1848, 레일과 목록이 나오는 넓은 창), 최종 코드: 174개 실행, 실패 0, 오류 0, 건너뜀 2.
    • 건너뛴 둘은 메뉴의 색 값 검사다. 그 폰의 캡처는 색이 물들어 비교할 수 없다(0.6.0과 같다).
  • 틀 테스트는 테스트 안에서 창을 475×751, 704×933, 933×704로 고정한다. 견본 앱을 세 창 모두에서 DdsFrameCheck로 훑었다.
  • 카탈로그를 에뮬레이터에서 세 창으로 캡처하고, 캡처에 선을 그어 직접 봤다.

확인하지 못한 것

  • 실제 앱에서 폰으로 확인하는 것: 정산나우가 로컬 빌드로 옮겨 창 세 가지에서 본다. 배포는 이것을 기다린다(설계 §3).
  • 뒤로 쓸어 넘기기, 실제 옆면 컷아웃, 기기에서 오른쪽에서 왼쪽 언어, TalkBack 실제 청취.
  • 견본 앱 검사 중 둘(페이지 색, assertSameLines)은 실패하는 것을 보지 못했다.
  • 별도 앱에서 꾸러미 셋을 받아 쓰는 것, 세 번째 꾸러미를 포함한 배포 워크플로.

배포

이 PR은 배포하지 않는다. 머지하고 정산나우의 폰 확인을 마친 뒤 android-v0.7.0 태그를 단다(릴리스 체크리스트 확인 후). 그다음 Maven Central에서 받아지는지 확인한다.

The numbers were there and nothing made a screen keep to them: in
JeongsanNow the body started on a different line from screen to screen, the
rail was on the tab screens only, and the top bar and the body stood on
different lines.

The design, agreed with the owner section by section: the side gutter is
16 below 600 and 24 from there (decided; JeongsanNow's 20 moves to it); a
frame outside the screen switcher draws the rail from 600 and a fixed list
from 840, while a top-level screen draws the bottom tabs; the body is one
column of at most 680 and the top bar keeps to its lines; a screen with one
thing to do is one block of at most 400 in the middle; a new artifact lets
an app check its own screens. Not built yet.

Backlog: the frame is approved; requests from Qooroo (the menu's shadow
and end alignment) and JeongsanNow (text fields that keep no copy of the
text, the frame of a step flow); 0.5.0 on the unfolded phone.
DdsBodyColumn centers the screen's content in the area the frame leaves, no wider than 680dp, with the window gutter as the start line. ddsBodyLines puts a bar or divider on the same two edges.
…m one set of pixel lines; every tall bar is the same height; cutouts count in the width check
Both decision records stay (D-053 above D-052). The backlog keeps the 0.6.0
entries from main and the frame's notes; the frame's documents now say 0.7.0.
…rows for the fixed list

DdsCenteredColumn and DdsCenteredTitle (layout/Centered.kt): one block in the middle of its area, 400dp at most, the window's gutter at the sides; taller than the area it starts at the top and scrolls. DdsPaneList and DdsPaneItem (component/Pane.kt): the rows of the pinned list, chosen like the rail's destination (pale brand fill, brand color, heavier label), labels on the pane's gutter line, a group a screen reader counts.

A 475dp window holds the whole 400dp block, so the gutter case is tested at 360dp.
…ing artifact brings an Espresso that runs on Android 17

DdsCenteredColumn paints the page behind its whole area, outside the slide, so
a centered screen covers the one under it on every frame of a change, also in a
NavDisplay, which paints nothing behind its entries. dds-compose-testing carries
espresso-core 3.7.0 (the BOM's 3.5.0 does not run on Android 17). The version is
0.7.0 from here on.
The catalog runs inside DdsAppFrame: each tab is its own DdsScaffold with
bottomTabs, its page is a DdsBodyColumn, and an opened item has a top bar with
onBack. A fifth tab, Layout, lists four demos (body column, top bar, centered
block, whole window). From 840dp the list is pinned beside the demo and
choosing swaps it; narrower, the list is the tab's screen and a demo opens over
it. The whole-window demo turns the menus off. Launch extras open a Motion item
or a Layout demo directly, for captures.
Guide section 13 (rules, numbers, parts, a Navigation 3 app and a DdsScreenHost
app, dds-compose-testing, what was checked and what was not), the 0.7.0
changelog with what changes when moving up, D-052 built and verified, the
backlog, the README version lines (0.7.0 is not on Maven Central yet) and the
design's status with what changed while building.
174 run, 0 failed, 0 errors, 2 skipped at 2448x1848 (the wide window with the
rail and the pinned list), at the final code. The folded run stays as it was.
@jlc488
jlc488 merged commit 48e64e3 into main Nov 12, 2026
3 checks passed
@jlc488
jlc488 deleted the feat/android-screen-frame branch November 12, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant