Skip to content

feat: Improve iOS experience to align with Apple HIG#128

Merged
AdamJ merged 5 commits into
mainfrom
claude/ios-apple-guidelines-zgLR0
May 15, 2026
Merged

feat: Improve iOS experience to align with Apple HIG#128
AdamJ merged 5 commits into
mainfrom
claude/ios-apple-guidelines-zgLR0

Conversation

@AdamJ
Copy link
Copy Markdown
Owner

@AdamJ AdamJ commented May 14, 2026

Summary

Update the experience to align with Apple Human Interface Guidelines (HIG) when using on mobile and iOS app (through Capacitor build).

Type of Change

  • New feature
  • Update to existing feature
  • Bug fix
  • Documentation update
  • Other (describe below)

Related Issue

Closes #

Changes Made

  • P1: Convert TaskEditDialog, StartDayDialog, ArchiveEditDialog, and DeleteConfirmationDialog to adaptive bottom sheets on iOS using vaul Drawer via new AdaptiveDialog component; web rendering is unchanged. DeleteConfirmationDialog reverses button order per iOS action-sheet convention (destructive first, Cancel last).

  • P2: Replace unreliable visibilitychange handler in TimeTrackingContext with useAppLifecycle hook that fires @capacitor/app's appStateChange at the Swift layer before WKWebView freezes, with a visibilitychange fallback for web.

  • P3: Add useHaptics hook (light/medium/heavy impact, success/error notifications) wired to: tab-bar navigation, task Edit/Delete buttons, delete confirmation, startNewTask success, postDay success, and sync failure paths.

  • P4: Add useStatusBar hook that syncs iOS status bar text colour with the system dark/light mode. Update apple-mobile-web-app-status-bar-style to black-translucent so the web view extends behind the status bar.

  • P5: Gate desktop SiteNavigationMenu behind !isIosBuild in PageLayout; replace with new IosPageHeader (sticky, 17px SF-style title, back chevron, safe-area-inset-top padding). Inject ios-build class on body in main.tsx and prevent double-stacking of safe-area padding in pwa.css.

  • P6: Configure Capacitor Keyboard plugin (resize: body) in capacitor.config.ts. Add useKeyboardHeight hook and apply its value as paddingBottom on DrawerContent so form fields scroll above the keyboard. Add scroll-margin-bottom rule to pwa.css for native scroll-into-view.

  • P7: Add useLongPress hook and ContextMenu (right-click on desktop, long-press on iOS) to TaskItem with Edit and Delete actions. Hide always-visible action buttons on iOS builds.

  • P8: Bump button sm size from h-9 to h-10 (40px); enforce min-height 44px on all non-hidden buttons at mobile widths via pwa.css.

  • P9: Restore native iOS rubber-band bounce by overriding overscroll-behavior-y on #root inside the @supports iOS block. Add touch-action and overscroll-behavior: contain on vaul drawer to prevent scroll bleed through open sheets.

  • P10: Wrap Routes in a keyed AnimatedRoutes component; apply page-transition-enter CSS animation (subtle 30px slide + fade, 280ms) on iOS route changes via @supports (-webkit-touch-callout: none).

Checklist

Complete all items that apply to your change. Check N/A for items that don't apply.

Documentation

Run sync-docs skill with Claude Code to automatically update relevant files.

  • Any notable changes added to the README.md
  • CHANGELOG.md updated accordingly
  • N/A — no README changes

General

  • Branch is up to date with main
  • No unrelated files included in this PR
  • Tested locally by invoking the npm run test, npm run lint, and npm run build

Notes for Reviewers

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 14, 2026

Deploying timetrackerpro with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1dad6b1
Status: ✅  Deploy successful!
Preview URL: https://7c7f1d85.timetrackerpro.pages.dev
Branch Preview URL: https://claude-ios-apple-guidelines.timetrackerpro.pages.dev

View logs

@AdamJ AdamJ force-pushed the claude/ios-apple-guidelines-zgLR0 branch from 29c9cc2 to 409a8b3 Compare May 14, 2026 16:07
claude added 5 commits May 15, 2026 04:18
- P1: Convert TaskEditDialog, StartDayDialog, ArchiveEditDialog, and
  DeleteConfirmationDialog to adaptive bottom sheets on iOS using vaul
  Drawer via new AdaptiveDialog component; web rendering is unchanged.
  DeleteConfirmationDialog reverses button order per iOS action-sheet
  convention (destructive first, Cancel last).

- P2: Replace unreliable visibilitychange handler in TimeTrackingContext
  with useAppLifecycle hook that fires @capacitor/app's appStateChange
  at the Swift layer before WKWebView freezes, with a visibilitychange
  fallback for web.

- P3: Add useHaptics hook (light/medium/heavy impact, success/error
  notifications) wired to: tab-bar navigation, task Edit/Delete buttons,
  delete confirmation, startNewTask success, postDay success, and sync
  failure paths.

- P4: Add useStatusBar hook that syncs iOS status bar text colour with
  the system dark/light mode. Update apple-mobile-web-app-status-bar-style
  to black-translucent so the web view extends behind the status bar.

- P5: Gate desktop SiteNavigationMenu behind !isIosBuild in PageLayout;
  replace with new IosPageHeader (sticky, 17px SF-style title, back
  chevron, safe-area-inset-top padding). Inject ios-build class on body
  in main.tsx and prevent double-stacking of safe-area padding in pwa.css.

- P6: Configure Capacitor Keyboard plugin (resize: body) in
  capacitor.config.ts. Add useKeyboardHeight hook and apply its value as
  paddingBottom on DrawerContent so form fields scroll above the keyboard.
  Add scroll-margin-bottom rule to pwa.css for native scroll-into-view.

- P7: Add useLongPress hook and ContextMenu (right-click on desktop,
  long-press on iOS) to TaskItem with Edit and Delete actions. Hide
  always-visible action buttons on iOS builds.

- P8: Bump button sm size from h-9 to h-10 (40px); enforce min-height
  44px on all non-hidden buttons at mobile widths via pwa.css.

- P9: Restore native iOS rubber-band bounce by overriding
  overscroll-behavior-y on #root inside the @supports iOS block.
  Add touch-action and overscroll-behavior: contain on vaul drawer
  to prevent scroll bleed through open sheets.

- P10: Wrap Routes in a keyed AnimatedRoutes component; apply
  page-transition-enter CSS animation (subtle 30px slide + fade, 280ms)
  on iOS route changes via @supports (-webkit-touch-callout: none).

https://claude.ai/code/session_014br3fcYa3SDmGjBHnDYZec
Update CHANGELOG.md, README.md, README-EXT.md, and CLAUDE.md to reflect
the ten Apple HIG improvements landed in the previous commit: bottom
sheets, haptics, app lifecycle persistence, status bar theming, iOS nav
header, keyboard avoidance, long-press context menus, touch target fixes,
scroll bounce, and page transitions.

CLAUDE.md: bump to v2.3.0, expand Key Files table with new hooks and
components, document installed Capacitor plugins, and extend the iOS
"when adding new features" guidance with AdaptiveDialog and useHaptics
usage patterns.

https://claude.ai/code/session_014br3fcYa3SDmGjBHnDYZec
- dialog.tsx: add pr-8 to DialogHeader so the absolute X button (right-4
  top-4) never overlaps title text when DialogContent padding is narrow
- StartDayDialog: remove extra px-4 from form content div that caused
  fields to be indented relative to the header and footer
- TaskEditDialog: move Cancel/Save buttons into AdaptiveDialogFooter
  outside the overflow-y-auto scroll container so they are always visible
  regardless of scroll position; content area changed to flex-col with
  flex-1 min-h-0 overflow-y-auto inner wrapper

https://claude.ai/code/session_014br3fcYa3SDmGjBHnDYZec
- Index.tsx: pass title/icon to PageLayout so IosPageHeader shows
  "Dashboard" in the center nav bar; remove the page's own inline h1
  which was doubling the heading and leaving the iOS header blank
- NewTaskForm: add fab-nav-offset CSS class so the floating + button
  clears the MobileNav (64px) plus safe-area-inset-bottom on iOS;
  was hidden behind the nav at the previous bottom-20 (80px) offset
- adaptive-dialog: control vaul activeSnapPoint so drawers open at the
  first snap point immediately rather than requiring the user to swipe
  up from a near-zero peek height; resets to snapPoints[0] each time
  the dialog opens
- pwa.css: add .fab-nav-offset rule under @supports iOS selector

https://claude.ai/code/session_014br3fcYa3SDmGjBHnDYZec
MobileNav was h-16 (64px), 15px over the HIG-specified 49pt tab bar
height. Changed to h-12 (48px). Updated the two pwa.css values that
were calibrated to 4rem (h-16): body padding-bottom and the iOS FAB
offset rule, both reduced by 1rem to stay in sync. Also updated the
FAB's Tailwind bottom value from bottom-20 to bottom-16.

The IosPageHeader height (env(safe-area-inset-top) + h-11 = ~103px on
iPhone 16) is correct per HIG — the 59px Dynamic Island clearance is
mandatory and is not doubled.

https://claude.ai/code/session_014br3fcYa3SDmGjBHnDYZec
@AdamJ AdamJ added enhancement New feature or request iOS labels May 15, 2026
@AdamJ AdamJ force-pushed the claude/ios-apple-guidelines-zgLR0 branch from 409a8b3 to 1dad6b1 Compare May 15, 2026 04:19
@AdamJ AdamJ merged commit 5ee3da4 into main May 15, 2026
1 check passed
@AdamJ AdamJ deleted the claude/ios-apple-guidelines-zgLR0 branch May 15, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request iOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants