Skip to content

feat(mobile): Material 3 segmented lists for Android grouped rows - #2348

Merged
DoodleBears merged 17 commits into
mainfrom
claude/project-thread-m7tsnr-shape
Oct 21, 2026
Merged

DoodleBears merged 17 commits into
mainfrom
claude/project-thread-m7tsnr-shape

Conversation

@DoodleBears

@DoodleBears DoodleBears commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Generated with Claude Code

https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

Why the change

On Android, grouped rows in Settings and bottom sheets (for example the Activity options sheet) looked hard-edged: one 28dp card with hairline dividers and square inner corners. Material 3 now draws these as a segmented list with soft corners on every row.

Before: each group was one card, rows split by dividers, with square corners between rows.

After: each row is its own tile, 2dp apart, with 16dp outer corners on the first and last rows and 4dp corners between rows, and no dividers. iOS is unchanged.

Refs #2339 (android-material skill), #2338 (native first). Stacked on #2342; retarget to main after it merges.

Special things to note

  • Merge risk: Android-only styling in SettingsSection, SettingsGroupItem and the Activity options sheet. Values come from the m3.material.io list tokens: md.comp.list.container.shape = corner.large (16dp), md.comp.list.list-item.container.expressive.shape = corner.extra-small (4dp), md.comp.list.segmented.gap = 2dp. androidSettings.radius (28dp) stays for dialogs and cards; the new listRadius token is 16dp. Revert by reverting this commit.
  • Verification: pnpm lint, mobile tsc --noEmit, oxfmt, vitest apps/mobile/test (114 files passed, 7 skipped), and the new segmented-list-android.test.ts.
  • CI test plan: affected. No new config or test directory.

Change outline

  • tokens.ts: androidSettings.listRadius = 16, innerRadius = 4, segmentGap = 2.
  • settings-row.tsx: segmentCorners(first, last); Android SettingsSection and SettingsGroupItem render separate tiles; SettingsDivider removed.
  • activity-filters.tsx: Android choice rows and the Unread only row use the same segmented shape.
  • DESIGN.md: Android groups and bottom sheet rules updated.

Physical phone: Xiaomi, Android 16 / HyperOS 3, gesture navigation, Chinese UI. Debug dev client built from main 48f35fb with this branch's JS over Metro, paired to an isolated QA Host. Status bar and computer names redacted. Files are in .github/pr-screenshots/2348-android-shape/phone/ on this branch (Files changed).

Light Dark Text size 2.0
Settings groups settings-light.png settings-dark.png settings-font.png
Activity filter sheet filter-sheet-light.png filter-sheet-dark.png filter-sheet-font.png

Result: PASS. Settings groups and the Activity filter sheet: gaps between rows, large outer corners and small inner corners, in light and dark. At text size 2.0 the arrow in the usage card's "最近 7 天 >" wraps to its own line; that row is outside this change and is left for a follow-up.


Generated by Claude Code

Segmented, PercentageSlider and Chip gain Android variants built on
@expo/ui Jetpack Compose (segmented buttons, Slider, FilterChip). The
Activity options sheet uses a Compose RadioButton through a new RadioMark
primitive, and its unread-only switch moves to the Toggle primitive.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
Compose reads each SegmentedButton's position from its parent once, so a
row that grows from two to four options (Usage, once longer periods are
supported) kept the two-item shapes: the selected middle segment drew a
rounded end. Key the row on its option values.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 11 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9159d66d-38b7-44b7-af72-28940dc3e6a6
📥 Commits

Reviewing files that changed from the base of the PR and between 38f5dca and 9902f4c.

⛔ Files ignored due to path filters: 6
  • .github/pr-screenshots/2348-android-shape/phone/filter-sheet-dark.png is excluded by !**/*.png
  • .github/pr-screenshots/2348-android-shape/phone/filter-sheet-font.png is excluded by !**/*.png
  • .github/pr-screenshots/2348-android-shape/phone/filter-sheet-light.png is excluded by !**/*.png
  • .github/pr-screenshots/2348-android-shape/phone/settings-dark.png is excluded by !**/*.png
  • .github/pr-screenshots/2348-android-shape/phone/settings-font.png is excluded by !**/*.png
  • .github/pr-screenshots/2348-android-shape/phone/settings-light.png is excluded by !**/*.png
📒 Files selected for processing: 9
  • apps/mobile/DESIGN.md
  • apps/mobile/src/ui/design/segment-corners.ts
  • apps/mobile/src/ui/design/tokens.ts
  • apps/mobile/src/ui/primitives/segmented.android.tsx
  • apps/mobile/src/ui/primitives/settings-row.tsx
  • apps/mobile/src/ui/shell/activity-filters.tsx
  • apps/mobile/test/material-controls-android.test.tsx
  • apps/mobile/test/segmented-list-android.test.ts
  • changes/2348-android-segmented-lists.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

claude and others added 12 commits October 19, 2026 20:31
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
Captured on an Android 16 x86_64 emulator with gesture navigation and a
debug dev client built from main plus #2342 and #2343. Light and dark at the default font, plus the largest font (2.0) for Usage and the Activity filter.
Computer names are redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-m7tsnr

# Conflicts:
#	apps/mobile/DESIGN.md
#	apps/mobile/src/ui/shell/activity-filters.tsx
…parent container

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
…uses the list shape

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
…typecheck stays on Node timers

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
Recaptured on an Android 16 x86_64 emulator with gesture navigation and a
fresh debug dev client built from main 55c8848 plus #2342 and #2343. Light and dark at the default font, plus the radio-list fallback at the largest font (2.0).
Computer names are redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-m7tsnr

# Conflicts:
#	apps/mobile/DESIGN.md
#	apps/mobile/src/ui/primitives/segmented.android.tsx
…to claude/project-thread-m7tsnr-shape

# Conflicts:
#	apps/mobile/src/ui/primitives/segmented.android.tsx
Captured on a Xiaomi phone (Android 16, HyperOS 3, arm64, gesture navigation,
zh-CN) running an arm64 debug dev client of main 48f35fb with this branch's
JavaScript, in light, dark and font scale 2.0. Settings groups and the Activity filter sheet: gaps between rows, large outer and small inner corners.
Status bar and computer names are redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@DoodleBears
DoodleBears marked this pull request as ready for review October 20, 2026 07:38
@DoodleBears
DoodleBears changed the base branch from claude/project-thread-m7tsnr to main October 21, 2026 04:52
The radio-list fallback for segmented rows from #2342 now uses the
segmented-list corners and gap from this PR.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbudM552v4qrLMzopz7j7k
@DoodleBears
DoodleBears merged commit 83bd44a into main Oct 21, 2026
11 checks passed
@DoodleBears
DoodleBears deleted the claude/project-thread-m7tsnr-shape branch October 28, 2026 04:24
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.

2 participants