Skip to content

feat: add iPad sidebar layout and iPad CI test matrix#15

Merged
brendan-ch merged 3 commits into
mainfrom
feat/ipad-ui
Jun 18, 2026
Merged

feat: add iPad sidebar layout and iPad CI test matrix#15
brendan-ch merged 3 commits into
mainfrom
feat/ipad-ui

Conversation

@brendan-ch

Copy link
Copy Markdown
Owner

Summary

Makes OpenAppLock iPad-native and adds iPad to CI. The app already declared
TARGETED_DEVICE_FAMILY = "1,2", so it ran on iPad — but it just stretched the
iPhone bottom tab bar across the canvas. Per Apple's HIG, a bottom tab bar is an
iPhone idiom; on the regular-width iPad the top-level sections belong in a left
sidebar.

The post-onboarding shell is now adaptive, driven by horizontalSizeClass
(not device idiom, so iPad multitasking/Slide Over stays correct):

  • Compact width (iPhone, iPad multitasking) → bottom TabView (MainTabView)
  • Regular width (full-screen iPad) → left NavigationSplitView sidebar (MainSidebarView)

HomeView / RulesListView / SettingsView are reused verbatim in both
layouts — only the navigation chrome differs.

Changes

  • New AppSection enum — single source of truth for tab items and sidebar rows.
  • New MainLayout.resolve(horizontalSizeClass:) — picks tabs vs sidebar (sidebar only for known regular width).
  • New MainView shell — owns the enforcement lifecycle (lifted off MainTabView) so it runs regardless of layout; new MainSidebarView for the iPad sidebar.
  • RootView now renders MainView; MainTabView is compact-only and sources its tabs from AppSection.
  • CI: test.yml runs the suite on iPhone 17 Pro and iPad Pro 13-inch (M4) via a fail-fast: false matrix with per-leg artifacts.
  • Docs: spec §6 and AGENTS.md updated for the adaptive shell + sidebarItem-<section> identifiers + iPad UI-test gotchas.

Test plan

  • TDD red → green: AppSectionTests, MainLayoutTests (unit)
  • New idiom-aware NavigationChromeUITests (sidebar-on-iPad / tabs-on-iPhone)
  • Existing UI suite made sidebar-aware; iPhone-presentation flows adapted to iPad (nav BackButton vs window-edge swipe; scroll the shorter form sheet; window-relative width gated to iPhone)
  • Full suite green on iPad Pro 11" (M5): 231 passed, 1 skipped, 0 failed
  • Full suite green on iPhone 17 Pro: 232 passed, 0 failed
  • Manual (simulator): iPad sidebar + detail-pane swap across Home/Rules/Settings; iPhone bottom tab bar unchanged
  • CI matrix green on both legs (verified by this PR's checks)

Notes

  • One test (testEditorSupportsNativeSwipeBack) is skipped on iPad with a documented reason: its window-edge swipe gesture only maps onto a full-width sheet (iPhone); the equivalent back navigation is covered by testLimitEditorsAreBlockOnly.
  • Validation is simulator-only (the project norm); this change is pure layout, so no on-device behavior is affected.
  • No rules/enforcement/model/extension or project.pbxproj changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SZ9eNtWxt96J66dG3amUSU

brendan-ch and others added 3 commits June 17, 2026 23:35
The post-onboarding shell now adapts to the horizontal size class instead of
stretching the iPhone tab bar across the iPad canvas: a bottom TabView in
compact width (iPhone, iPad multitasking) and a left NavigationSplitView
sidebar in regular width (full-screen iPad), per Apple's HIG. The three
sections (Home / Rules / Settings) and their views are reused verbatim in
both layouts.

- AppSection enum is the single source of truth for tab items and sidebar
  rows; MainLayout.resolve picks the chrome from horizontalSizeClass.
- New MainView shell owns the enforcement lifecycle (lifted off MainTabView)
  so it runs regardless of layout; MainSidebarView is the regular-width view.
- CI: test.yml now runs the suite on both iPhone 17 Pro and iPad Pro 13-inch
  (M4) via a fail-fast:false matrix with per-leg artifacts.

Tests (TDD red -> green): new AppSection / MainLayout unit suites and an
idiom-aware NavigationChromeUITests. Existing UI helpers made sidebar-aware
(goTo*Tab / waitForMainUI); iPhone-presentation-specific flows adapted to
iPad (nav BackButton instead of window-edge swipe, scroll the shorter form
sheet, gate window-relative width to iPhone) or skipped on iPad with a
documented reason. Suite is green on both devices (iPad 231 pass/1 skip,
iPhone 232 pass).

Docs: spec section 6 and AGENTS.md updated for the adaptive shell.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SZ9eNtWxt96J66dG3amUSU
Resolves additive doc conflicts by keeping both sides: the iPad sidebar
identifiers/diagram (this branch) and main's Settings "About" GitHub/Website
links (AGENTS.md identifier list, spec §6 navigation diagram).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SZ9eNtWxt96J66dG3amUSU
iPad Pro 13-inch (M4) is not installed on the macos-26 runner image (only M5
Pros plus Air / mini / A16), so build-for-testing failed with a "destination
not found" error (exit 70) before any test ran. iPad Pro 11-inch (M5) is
present on the runner and is the device the suite was validated on locally;
full-screen iPad is regular width regardless of model, so the sidebar layout
is exercised identically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SZ9eNtWxt96J66dG3amUSU
@brendan-ch brendan-ch merged commit dbc6a91 into main Jun 18, 2026
2 checks passed
@brendan-ch brendan-ch deleted the feat/ipad-ui branch June 18, 2026 05:43
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