listless

A simple list app for Apple platforms
Log | Files | Refs | README | LICENSE

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:
MAGENTS.md | 4++--
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