Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2b8eb2a
docs(android): design for the screen frame (D-052, 0.6.0)
jlc488 Nov 12, 2026
82782df
docs(android): implementation plan for the screen frame
jlc488 Nov 12, 2026
6d70e2b
docs(android): what the frame design assumed, checked on a device
jlc488 Nov 12, 2026
e6d09d9
docs(android): say what the device probe did not measure
jlc488 Nov 12, 2026
1c47135
feat(android): numbers for the screen frame (840, 680, 264, 400, rail…
jlc488 Nov 12, 2026
1df852c
feat(android): window width classes and what the frame tells a screen
jlc488 Nov 12, 2026
76eb7aa
feat(android): a tab label takes two lines at large sizes; the rail s…
jlc488 Nov 12, 2026
4b1b89d
feat(android): DdsAppFrame — the rail and a fixed list outside the sc…
jlc488 Nov 12, 2026
6965f2a
fix(android): no tabs when the frame has no menu; the rail keeps its …
jlc488 Nov 12, 2026
8c1e815
feat(android): the body column — one start line for every screen
jlc488 Nov 12, 2026
fd58517
feat(android): the top bar keeps to the body's lines; one tall bar fo…
jlc488 Nov 12, 2026
8560ea8
fix(android): the top bar places its arrow, mark, title and icons fro…
jlc488 Nov 12, 2026
e823b33
Merge main (Android 0.6.0) into the screen frame; the frame is 0.7.0
jlc488 Nov 12, 2026
97aedd7
feat(android): the centered block for a screen with one thing to do; …
jlc488 Nov 12, 2026
b3535ef
feat(android): dds-compose-testing — an app checks its own screens ag…
jlc488 Nov 12, 2026
30b9650
test(android): the frame through a change of screen, and a whole samp…
jlc488 Nov 12, 2026
e5b1e40
fix(android): the centered block keeps clear of the bars and the keyb…
jlc488 Nov 12, 2026
ba1a0c5
fix(android): the centered block covers the screen under it; the test…
jlc488 Nov 12, 2026
1851f9f
feat(android): the catalog on the new frame, with a layout page
jlc488 Nov 12, 2026
8f5ceab
docs(android): the screen frame in the guide; 0.7.0
jlc488 Nov 12, 2026
3a7d10d
fix(android): the body and centered columns pass the screen's name; a…
jlc488 Nov 12, 2026
bc83aba
docs(android): what the review found — backlog, claims, compatibility…
jlc488 Nov 12, 2026
d2f50ab
test(android): two frame tests no longer depend on the device's window
jlc488 Nov 12, 2026
19394d7
docs(android): the whole device suite also passed on the unfolded phone
jlc488 Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/android-release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Android release — publishes kr.devslab:dds-android-tokens and
# kr.devslab:dds-compose to Maven Central.
# Android release — publishes kr.devslab:dds-android-tokens,
# kr.devslab:dds-compose and kr.devslab:dds-compose-testing to Maven Central.
#
# Triggered by a hand-pushed `android-v<version>` tag, and by nothing else.
# The web packages release through Changesets on every push to main
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:

- name: Build and test
working-directory: android
run: ./gradlew testDebugUnitTest :dds-tokens:assembleRelease :dds-compose:assembleRelease --no-configuration-cache --stacktrace -PVERSION_NAME=${{ steps.ver.outputs.version }}
run: ./gradlew testDebugUnitTest :dds-tokens:assembleRelease :dds-compose:assembleRelease :dds-compose-testing:assembleRelease --no-configuration-cache --stacktrace -PVERSION_NAME=${{ steps.ver.outputs.version }}

- name: Publish to Maven Central
working-directory: android
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ jobs:
- uses: gradle/actions/setup-gradle@v5
- name: Unit tests, lint and release build
working-directory: android
run: ./gradlew testDebugUnitTest :dds-tokens:lintRelease :dds-compose:lintRelease :dds-tokens:assembleRelease :dds-compose:assembleRelease :catalog:assembleDebug --stacktrace
run: ./gradlew testDebugUnitTest :dds-tokens:lintRelease :dds-compose:lintRelease :dds-compose-testing:lintRelease :dds-tokens:assembleRelease :dds-compose:assembleRelease :dds-compose-testing:assembleRelease :catalog:assembleDebug --stacktrace
2 changes: 1 addition & 1 deletion README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Source-Available License 1.0을 따른다. compatibility canary는 비공개·
때만 만든다 (명세 §8):
`@devslab/dds-tokens` (✅ 2026-08-13) → `dds-css` v1 인벤토리 (Core 6종 ✅ 2026-08-13, +13종 ✅ 2026-08-15) →
AskLinq 적용 → `dds-icons` (✅ 2026-08-15) → `dds-solid` + `site-kit` → 안드로이드 네이티브 값·테마·모션
(0.6.0, 2026-11-12, Maven Central — 테마·모션·부품·아이콘). RN·Ionic 패키지는 그 제품이 생길 때.
(0.6.0, 2026-11-12, Maven Central — 테마·모션·부품·아이콘). 화면 틀과 `dds-compose-testing` 꾸러미를 담은 0.7.0은 만들었지만 **아직 Maven Central에 없다**. 정산나우가 폰에서 확인한 뒤에 올린다(D-052). RN·Ionic 패키지는 그 제품이 생길 때.

## 입력·선택·공유 달력 확장

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Priorities live in [`docs/backlog.md`](docs/backlog.md). Packages are created
only when a consumer exists (spec §8):
`@devslab/dds-tokens` (✅ 2026-08-13) → `dds-css` v1 inventory (Core 6 ✅ 2026-08-13, +13 ✅ 2026-08-15) →
AskLinq adoption → `dds-icons` (✅ 2026-08-15) → `dds-solid` + `site-kit` → native Android values, theme and motion
(0.6.0, 2026-11-12, on Maven Central — theme, motion, components, icons). RN and Ionic packages only when such a product exists.
(0.6.0, 2026-11-12, on Maven Central — theme, motion, components, icons). 0.7.0, the screen frame and the `dds-compose-testing` artifact, is built but **not on Maven Central yet**: it waits for JeongsanNow's check on its phone (D-052). RN and Ionic packages only when such a product exists.

## Input, choice and shared calendar additions

Expand Down
86 changes: 85 additions & 1 deletion android/CHANGELOG.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,93 @@

[English](CHANGELOG.md) · **한국어**

`kr.devslab:dds-android-tokens`와 `kr.devslab:dds-compose`는 한 버전을 쓰고, 웹 패키지와는
`kr.devslab:dds-android-tokens`, `kr.devslab:dds-compose`, 그리고 0.7.0부터 `kr.devslab:dds-compose-testing`은 한 버전을 쓰고, 웹 패키지와는
버전이 따로다(D-048). 릴리스는 `android-v<버전>` 태그로 낸다.

## 0.7.0 — 아직 배포 전

화면 틀(D-052). 정산나우가 펼친 폰에서 찾았다. 화면마다 시작선이 달랐고(187, 147, 127dp, 또는 끝에서
끝까지), 레일은 탭 화면에만 있었고, 상단 줄은 창 끝에서 본문은 가운데에서 시작했다. DDS에 숫자는 있는데
그 숫자를 지키는 부품이 없었다. 이제 부품이 있다. 가이드 §13.

**아직 Maven Central에 없다.** 정산나우가 로컬 빌드로 옮겨 폰의 창 세 가지(접힌 475×751, 펼친 세로
704×933, 펼친 가로 933×704)에서 확인한 뒤에 배포한다. 그때까지는 이 레포에서 `./gradlew publishToMavenLocal`로
만든다.

**새로 생긴 것**

- **`DdsAppFrame`** — 앱에 하나, 화면 전환기 바깥에 둔다. 창 폭이 메뉴를 정한다. 600dp 미만은 하단 탭(최상위
화면이 그린다), 600dp부터 레일, 840dp부터 레일과 영역의 고정 목록. `navigation = false`면 모두 끈다. 메뉴가
나타나거나 사라져도 내용은 제자리라, 접거나 돌려도 스크롤 위치와 입력한 글자가 남는다.
- **`DdsFrame`, `LocalDdsFrame`, `ddsFrame()`** — 틀이 정한 것. 화면은 재지 않고 이것을 읽는다.
- **`DdsWindowWidth`, `ddsWindowWidth()`, `DdsWindowWidth.gutter`** — 600과 840 기준의 Compact / Medium /
Expanded, 옆 여백 16 / 24 / 24.
- **`DdsScaffold(topBar, modifier, bottomTabs)`** — 틀 안의 화면 하나. 안쪽 여백이 이미 비켜 준 시스템 영역은
내용에서 쓴 것으로 표시해, 안에 둔 `DdsCenteredColumn`이나 `imePadding()`이 두 번 비우지 않는다. 예전
`DdsScaffold(topBar, navItems, …)`는 그대로다.
- **`DdsBodyColumn`, `Modifier.ddsBody()`, `Modifier.ddsBodyLines()`, `DdsBodyDefaults`** — 화면마다 본문 기둥
하나. 여백 포함 680dp를 넘지 않고, 레일과 목록이 남긴 자리의 가운데에 선다. `paneTitle`은 화면이 들어올 때
화면 낭독기가 말할 화면 이름이다(`DdsCenteredColumn`도 같다).
- **`DdsTopBar(onBack, backEnabled, backDescription, columnMax)`** — 상단 줄이 본문의 선에 선다. `onBack`을 주면
화살표를 그리고 선에 맞춘다. **`ddsBarNeedsTwoLines()`** — 두 줄 판단. 틀 안에서는 `barTitles`로 창 전체에
대해 정한다(104dp).
- **`DdsCenteredColumn`, `DdsCenteredTitle`** — 한 가지 일만 하는 화면. 최대 400dp의 한 묶음이 시스템 줄과
키보드가 남긴 자리의 가운데에 선다.
- **`DdsPaneList`, `DdsPaneItem`** — 고정 목록의 줄.
- **`DdsTestTags`** — 부품이 스스로 다는 표시.
- **새 꾸러미 `kr.devslab:dds-compose-testing`** — `DdsFrameCheck(rule).look(name, kind)`와
`.assertSameLines()`. 앱의 기기 테스트가 모든 화면이 한 시작선에 서는지, 창 폭과 화면 종류에 맞는 메뉴만
있는지 검사한다. Espresso 3.7.0을 함께 가져온다(Compose BOM이 가져오는 3.5.0은 Android 17에서 돌지 않는다).
- **새 토큰:** `DdsScreen.breakpointExpanded` 840, `bodyMax` 680, `listPane` 264, `centeredMax` 400.
`DdsBar.rail` 80, `topTall` 104.

```kotlin
implementation("kr.devslab:dds-compose:0.7.0")
androidTestImplementation("kr.devslab:dds-compose-testing:0.7.0")
```

**버전만 올려도 달라지는 것**

0.6.0으로 컴파일되던 코드는 0.7.0으로도 컴파일된다. 예외가 하나 있다. `DdsTopBar(title, Modifier, { 로고 },
{ 동작 })`처럼 동작을 자리로 넘기는 호출은 컴파일되지 않는다. 네 번째 인자가 이제 `onBack`이기 때문이다.
`actions`를 이름으로 넘기거나 끝의 람다로 넘긴다. `DdsTopBar` 인자의 변경은 바이너리 호환도 깨진다. 0.6.0에
맞춰 컴파일한 라이브러리가 `DdsTopBar`를 부르면 0.7.0에 맞춰 다시 빌드해야 한다. 아무것도 바꾸지 않아도 이렇게
보인다.

- **`DdsTopBar`.** 넓은 창에서 내용이 본문 기둥 폭(680dp)으로 가운데에 모인다. 아래 선과 바탕은 여전히 영역
전체 폭이다. 옆 여백이 창 폭 600부터 24가 된다(전에는 어디서나 16). `leading` 로고 뒤 제목이 시작선에서
40dp 뒤에서 시작한다. `leading`으로 뒤로 버튼을 넣던 코드는 그대로 동작하지만 선에 맞지 않으니 `onBack`으로
옮긴다. 동작 아이콘은 나란히 붙는다. 48dp 터치 영역이 맞닿는다(0.6.0에서는 12dp 떨어져 있었다).
- **`DdsBottomBar`, `DdsNavRail`.** 라벨이 한 줄에서 잘리지 않고 두 줄까지 쓰며, 탭 줄이나 레일 항목이 그만큼
높아진다. 레일 폭은 늘 80이다. 글자 200%에서 세 줄이 필요한 라벨은 두 번째 줄 뒤에서 잘린다.
- **가운데 묶음 화면이 움직이고 바탕을 칠한다.** `DdsCenteredColumn`이 본문 기둥처럼 화면과 함께 밀려 들어오고,
자리 전체에 페이지 바탕(`bgDefault`)을 칠한다. 그래서 바뀌는 동안 모든 프레임에서 아래 화면을 덮는다.
`NavDisplay` 안에서도 그렇다.
- **고정 목록의 고르지 않은 줄**은 본문 색이 아니라 레일과 같은 회색(`textSecondary`)이다.

정산나우가 자기 틀을 옮기면: 옆 여백이 20에서 접으면 16, 펼치면 24가 되고, 상단 줄 아래 선이 늘 보이고,
본문 위쪽 여백이 12나 20에서 16이나 24가 된다. 정산나우 부품과 DDS 부품의 대응은 인계 메모와 설계(§10)에 있다.

**확인한 것**

- 단위 테스트, 린트, 빌드: 통과.
- 기기 테스트 전체, 결과 파일로 읽었다. 실물 폰(SM-F971N, Android 17): 접은 화면(창 1248x1972) 170개 실행, 실패 0,
오류 0, 건너뜀 2. 펼친 화면(2448x1848, 레일과 고정 목록이 나오는 넓은 창) 최종 코드에서 174개 실행, 실패 0,
오류 0, 건너뜀 2. 건너뛴 둘은 그 폰에서 돌 수 없는 메뉴의 색 값 검사다(0.6.0과 같다). 틀 테스트는 테스트
안에서 창 세 가지로 크기를 고정한다.
- 카탈로그를 새 틀로 옮기고 Layout 쪽을 더해, 475×751, 704×933, 933×704로 고정한 에뮬레이터에서 보았다. 세 창
모두 밝은 화면, 933×704에서 어두운 화면, 475×751에서 가장 큰 글자, 475×751에서 키보드를 연 채. 캡처마다 본문의
시작선과 끝선을 그었고, 화살표, 제목, 마지막 아이콘, 본문 글자가 그 선에 섰다.
- `publishToMavenLocal`: 꾸러미 셋이 0.7.0으로 나온다. Espresso를 적은 POM은 `dds-compose-testing` 것뿐이다.

**확인하지 못한 것**

- 정산나우가 자기 폰에서 확인(배포 조건).
- 폰에서 카탈로그, 틀과 함께 하는 뒤로 밀기, 진짜 옆쪽 카메라 구멍(테스트 안에서만 설정), 오른쪽에서 왼쪽으로
쓰는 기기 언어, 틀 밖의 화면 분할, 따로 만든 앱에서 테스트 꾸러미 받기, 릴리스 워크플로가 세 번째 꾸러미를
올리는지, TalkBack.
- 옆 여백(시스템 줄·구멍)이 있을 때, 폭이 다른 본문일 때, 대화상자가 떠 있을 때의 `DdsFrameCheck`.

## 0.6.0 — 2026-11-12

Qooroo가 앱 모양을 다시 정하면서 나온 것: 주황 면 위의 흰 글자, 종이색 페이지, 흰 면 보조 버튼,
Expand Down
103 changes: 102 additions & 1 deletion android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,110 @@

**English** · [한국어](CHANGELOG.ko.md)

`kr.devslab:dds-android-tokens` and `kr.devslab:dds-compose` share one version,
`kr.devslab:dds-android-tokens`, `kr.devslab:dds-compose` and (from 0.7.0) `kr.devslab:dds-compose-testing` share one version,
separate from the web packages (D-048). Releases are cut by an `android-v<version>` tag.

## 0.7.0 — not released yet

The screen frame (D-052), from JeongsanNow on an unfolded phone: screens started on
different lines (187, 147, 127dp, or edge to edge), the rail was there on tab screens
only, and the top bar started at the window's edge while the body started in the middle.
DDS had the numbers and no part that kept them. Now it has the parts. Guide §13.

**Not on Maven Central yet.** The release waits for JeongsanNow to move onto it from a
local build and check it on its phone in three windows (folded 475×751, unfolded upright
704×933, unfolded on its side 933×704). Until then it is built from this repository with
`./gradlew publishToMavenLocal`.

**What is new**

- **`DdsAppFrame`** — once per app, outside the screen switcher. The window's width
decides the menus: bottom tabs under 600dp (drawn by the top-level screens), a rail from
600dp, a rail and the area's pinned list from 840dp. `navigation = false` turns them all
off. The content stays where it is when a menu appears or goes, so a fold or a rotation
keeps scroll positions and typed text.
- **`DdsFrame`, `LocalDdsFrame`, `ddsFrame()`** — what the frame decided, for a screen to
read instead of measuring.
- **`DdsWindowWidth`, `ddsWindowWidth()`, `DdsWindowWidth.gutter`** — Compact / Medium /
Expanded at 600 and 840; the gutter 16 / 24 / 24.
- **`DdsScaffold(topBar, modifier, bottomTabs)`** — one screen inside the frame. The system
insets its padding already covers are marked used for the content, so a `DdsCenteredColumn`
or an `imePadding()` inside does not pad them twice. The old `DdsScaffold(topBar, navItems, …)`
is unchanged.
- **`DdsBodyColumn`, `Modifier.ddsBody()`, `Modifier.ddsBodyLines()`, `DdsBodyDefaults`**
— one body column per screen, no wider than 680dp with its gutters, in the middle of what
the rail and the list leave. `paneTitle` names the screen for a screen reader when it arrives.
- **`DdsTopBar(onBack, backEnabled, backDescription, columnMax)`** — the bar stands on the
body's lines; `onBack` draws the arrow and lines it up. **`ddsBarNeedsTwoLines()`** — the
two-line decision; inside a frame `barTitles` makes it for the whole window (104dp).
- **`DdsCenteredColumn`, `DdsCenteredTitle`** — a screen with one thing to do: one block,
at most 400dp, in the middle of what the bars and the keyboard leave. Takes `paneTitle` too.
- **`DdsPaneList`, `DdsPaneItem`** — the rows of a pinned list.
- **`DdsTestTags`** — the tags the parts put on themselves.
- **New artifact `kr.devslab:dds-compose-testing`** — `DdsFrameCheck(rule).look(name, kind)`
and `.assertSameLines()`: an app's device tests check that every screen keeps one start
line and has only the menus its window and kind call for. It brings Espresso 3.7.0 (the
one the Compose BOM brings, 3.5.0, does not run on Android 17).
- **New tokens:** `DdsScreen.breakpointExpanded` 840, `bodyMax` 680, `listPane` 264,
`centeredMax` 400; `DdsBar.rail` 80, `topTall` 104.

```kotlin
implementation("kr.devslab:dds-compose:0.7.0")
androidTestImplementation("kr.devslab:dds-compose-testing:0.7.0")
```

**If you move up**

Code that compiled with 0.6.0 compiles with 0.7.0, with one exception: a `DdsTopBar` call
that passes its actions by position, `DdsTopBar(title, Modifier, { mark }, { actions })`,
does not, because the fourth parameter is now `onBack`. Pass `actions` by name or as the
trailing lambda. The change to `DdsTopBar`'s parameters is also binary-incompatible: a
library compiled against 0.6.0 that calls `DdsTopBar` must be rebuilt against 0.7.0. What
looks different without changing anything:

- **`DdsTopBar`.** On a wide window its content gathers into the body column's width
(680dp) in the middle; the line under it and its background still span the area. The side
gutter is 24 from a 600dp window (was 16 everywhere). A title after a `leading` mark
starts 40dp after the start line. Code that passed a back button as `leading` still works
but is not on the lines; move it to `onBack`. Action icons sit side by side, their 48dp
touch areas touching; in 0.6.0 they were 12dp apart.
- **`DdsBottomBar`, `DdsNavRail`.** A label is no longer cut at one line; it takes up to
two, and the bar or the rail item grows with it. The rail is always 80 wide. At 200% font
a label that needs a third line is cut after the second.
- **A centered screen moves and paints.** `DdsCenteredColumn` slides in with the screen as a
body column does, and paints the page (`bgDefault`) behind its whole area, so it covers the
screen under it on every frame of a change, also in a `NavDisplay`.
- **The rows of a pinned list** that are not chosen are in the rail's grey (`textSecondary`),
not the body color.

JeongsanNow, moving its own frame over: the gutter goes from 20 to 16 folded and 24
unfolded, the line under the top bar is always shown, and the space above the body is 16 or
24 (was 12 or 20). The mapping from its parts to DDS's is in the hand-over note and the
design (spec §10).

**Checked**

- Unit tests, lint and build: green.
- Device tests, the whole suite, read from the result files, on the phone (SM-F971N,
Android 17): folded (window 1248x1972) 170 run, 0 failed, 0 errors, 2 skipped; unfolded
(2448x1848, the wide window with the rail and the pinned list) 174 run, 0 failed, 0 errors,
2 skipped, at the final code. The skipped are the menu's two exact-color checks, which cannot run there (0.6.0). The frame
tests force the three windows inside the test.
- The catalog, on the new frame with a Layout page, on an emulator forced to 475×751,
704×933 and 933×704: light at all three, dark at 933×704, the largest font at 475×751,
the keyboard open at 475×751. The body's start and end lines were drawn over every
capture; the arrow, the title, the last icon and the body text stand on them.
- `publishToMavenLocal`: three artifacts at 0.7.0. Only `dds-compose-testing`'s POM names
Espresso.

**Not verified**

- JeongsanNow on its phone (the condition for the release).
- The catalog on the phone; the back swipe with the frame; a real side cutout (set in tests
only); a right-to-left device language; split screen outside a frame; the testing artifact
from a separate app's build; the release workflow publishing the third artifact; TalkBack.
- `DdsFrameCheck` with side insets, with a body of another width, with a dialog open.

## 0.6.0 — 2026-11-12

From Qooroo redrawing its app: white text on an orange face, a paper-colored page, a
Expand Down
Loading
Loading