commit d75fd2e1405a12158d541fdc156c429fd3539372
parent 163a0fb0e12dba17c58e7636e2a48cf46c7f27d3
Author: Michael Camilleri <[email protected]>
Date: Thu, 26 Mar 2026 18:33:15 +0900
Update AGENTS.md regarding overflow menu and focus guard
Diffstat:
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
@@ -103,12 +103,12 @@ Listless is a to-do list app for Apple platforms. It is intended to run on iPhon
## iOS Implementation Notes
- **Platform-specific inits**: iOS and macOS `ItemRowView` have diverged (iOS takes `isDragging: Binding<Bool>`). When adding new parameters, update both `ItemRowView` inits and both `ItemListView` bodies. The watchOS `ItemRowView` is independent and much simpler (tap-to-toggle only).
- **Appearance override**: Use `UIWindow.overrideUserInterfaceStyle` in `ListlessiOSApp`, not `.preferredColorScheme()` (which doesn't properly revert to nil in sheets).
-- **Focus guard for sheets**: The `onChange(of: focusedFieldBinding)` handler skips "reclaim focus to `.scrollView`" logic when a sheet is presented, preventing focus theft from sheet TextFields.
+- **Focus guard for overlays**: The `onChange(of: focusedFieldBinding)` handler skips "reclaim focus to `.scrollView`" logic when an overlay (sheet or alert) is presented, preventing focus theft from overlay TextFields. This is controlled by `InteractionStateData.isShowingOverlay`, a computed property that combines `isShowingSettings`, `isShowingSyncDiagnostics`, and `isShowingRenameAlert`. When adding a new sheet or alert with a text field, add its presentation flag to `isShowingOverlay`.
- **App icon in About screen**: Use `Image("AboutIcon")` from `Media.xcassets/AboutIcon.imageset` — `.appiconset` images can't be loaded via `Image()` in SwiftUI.
- **iOS color system**: `ListlessiOS/Helpers/AppColors.swift` defines `Color.outerBackground` and `Color.itemCard`. Adjust these two values to shift the palette.
- **Pull-to-create/clear**: Scroll gesture handling is in `.pullGestures()` (`ItemListView+PullGestures.swift`); visual indicators are in `ItemListView+PullToCreate.swift` and `ItemListView+PullToClear.swift`. The macOS `body` omits all of these. The pull-to-create indicator and the draft prepend row are separate siblings in the VStack (not a ZStack overlay) — the indicator collapses to zero height when the draft row appears. `revealPhantomRow()` directly sets up draft placement and focus without calling `createNewItemAtTop()`. Row spacing uses explicit `.padding(.bottom, rowGap)` on each row rather than VStack `spacing` (which is set to 0).
- **Haptics**: Gated behind `@AppStorage("hapticsEnabled")`. Pull-to-create/clear thresholds and drag-start use `.light` impact weight. Draft creation uses `.sensoryFeedback` on a `draftCount` trigger.
-- **Liquid Glass**: The iOS settings button uses `.buttonStyle(.glass)` gated behind `if #available(iOS 26.0, *)`, falling back to `.buttonStyle(.plain)` on older versions.
+- **Overflow menu**: iOS uses an overflow menu (ellipsis button) in the navigation header (`ItemListView+NavigationHeader.swift`) instead of a standalone settings button. The menu contains Rename List, Delete All, and Settings. On iOS 26+ the menu label uses `.glassEffect(.clear)`; on older versions it falls back to an `ellipsis.circle` SF Symbol with `.buttonStyle(.plain)`. Rename List presents an alert with a text field (`isShowingRenameAlert`); Delete All presents a destructive confirmation alert (`isShowingDeleteAllAlert`).
- **Selection on iOS/iPadOS is intentionally limited**: iOS supports single-item cursor navigation via arrow keys (for marking complete/incomplete) but does not support multi-select, Select All (Cmd+A), or Cmd+Click toggling. Full selection semantics (range select, multi-select, select all) are macOS-only. Do not add selection features to the iOS target.
## SwiftUI Implementation Notes