feat(ui): grid/table layout toggle for tosses list#23
Merged
Conversation
Add a macOS-only segmented toolbar picker that toggles the Tosses list between the existing card grid and a new SwiftUI Table with sortable Content / Type / Created columns. The choice persists via @AppStorage on AppSettings. The grid rendering is extracted into a standalone TossGridView, and a new macOS-only TossTableView drives interactive sorting via an in-memory [KeyPathComparator<Toss>], selection via Set<Toss.ID>, and a selection-aware context menu with a primaryAction that reuses the existing selectedToss sheet flow for row activation. iOS stays on the grid layout and does not show the picker. SwiftUI Table collapses to a single header-less column at compact iPhone width per Apple's documented behavior, so a real multi-column table is only offered on macOS. The architecture keeps the #if os(macOS) dispatcher trivial to relax into a horizontal-size-class check if iPad support is added later. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tablewith sortable Content / Type / Created columns. The chosen layout persists across launches via@AppStorageonAppSettings.TossGridView.TossTableView(macOS only) with interactive header sorting via[KeyPathComparator<Toss>], selection viaSet<Toss.ID>, and a selection-aware context menu (contextMenu(forSelectionType:)) whoseprimaryActionreuses the existingselectedTosssheet flow for double-click / Return activation.TossLayoutModeenum inTossKit, stored as a raw-string@AppStorage("layout_mode")onAppSettingswith a computed enum accessor (standard SwiftUI pattern for@AppStorageenums).Why
Card grid is great for browsing visual content (links with thumbnails), but hundreds of text tosses are easier to scan as a dense sortable list with headers. The toggle gives users both affordances on macOS without affecting the iPhone experience.
Why macOS only?
Per Apple's documented behavior and WWDC22 session 10058, SwiftUI
Tableon iPhone compact width hides headers and collapses all columns after the first — it's not a usable multi-column table there. The iOS target is iPhone-only (SUPPORTED_PLATFORMS = iphoneos iphonesimulator), so aTable-based layout on iOS would be strictly worse than the grid. The#if os(macOS)dispatcher gate is trivial to relax into a horizontal-size-class check later if iPad support is added.Architecture notes
sorted(using:)on the filtered array) rather than a dynamic@Queryrebuild — simpler, flexible, and fine at this data volume.Tablesits directly underNavigationStack, NOT inside an outerScrollView— embeddingTablein aScrollViewcollapses its height to zero. The grid branch retains itsScrollView; both layouts share the same.navigationTitle/.searchable/.toolbarmodifiers via a@ViewBuilderdispatcher..sharedBackgroundVisibility(.hidden)on the picker — toolbar controls inherit reasonable Liquid Glass styling and a segmented picker is a native control; only the solo-spinner sync indicator needed the explicit opt-out.\.typeRawValue(the stored String) rather than the computedtypeenum — the enum isn'tComparableand the raw value gives stable alphabetic ordering.Test plan
+button. Default is Grid (unchanged behavior).@Querywithin a couple of seconds.🤖 Generated with Claude Code