listless

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

commit edcc9fdb76d8a4b9dd19c97286a98953c16de071
parent cc89aadad02adbe78696fedc38362c7c21b1f1ce
Author: Michael Camilleri <[email protected]>
Date:   Tue,  3 Mar 2026 08:30:27 +0900

Use shadow/glow for selection state on iOS

Previous to this commit, selection state was indicated by a stroke
around the outside of the active task (there was no way to indicate
selection state for a completed task). This commit uses shadows (in
light mode) and glows (in dark mode) instead. It uses a different
background for completed tasks.

Co-Authored-By: Claude 4.6 Opus <[email protected]>

Diffstat:
MListlessiOS/Helpers/AppColors.swift | 21+++++++++++++++++++++
MListlessiOS/Views/TaskRowView.swift | 28+++++++++++++---------------
2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/ListlessiOS/Helpers/AppColors.swift b/ListlessiOS/Helpers/AppColors.swift @@ -13,4 +13,25 @@ extension Color { static let taskCard = Color(uiColor: UIColor { traits in traits.userInterfaceStyle == .dark ? UIColor.secondarySystemBackground : .white }) + + /// Selected background for completed rows. + static let completedSelected = Color(uiColor: UIColor { traits in + traits.userInterfaceStyle == .dark + ? UIColor(white: 0.12, alpha: 1) + : UIColor(red: 0.88, green: 0.86, blue: 0.83, alpha: 1) + }) + + /// Drop shadow for selected active cards in light mode. + static let selectionShadowLight = Color(uiColor: UIColor { traits in + traits.userInterfaceStyle == .dark + ? .clear + : UIColor(white: 0.0, alpha: 0.15) + }) + + /// Glow for selected active cards in dark mode. + static let selectionShadowDark = Color(uiColor: UIColor { traits in + traits.userInterfaceStyle == .dark + ? UIColor(red: 1.0, green: 0.95, blue: 0.5, alpha: 0.2) + : .clear + }) } diff --git a/ListlessiOS/Views/TaskRowView.swift b/ListlessiOS/Views/TaskRowView.swift @@ -122,20 +122,10 @@ struct TaskRowView: View { .clipShape( UnevenRoundedRectangle( topLeadingRadius: 0, bottomLeadingRadius: 0, - bottomTrailingRadius: task.isCompleted ? 0 : TaskRowMetrics.trailingCornerRadius, - topTrailingRadius: task.isCompleted ? 0 : TaskRowMetrics.trailingCornerRadius + bottomTrailingRadius: TaskRowMetrics.trailingCornerRadius, + topTrailingRadius: TaskRowMetrics.trailingCornerRadius ) ) - .overlay { - if isSelected && !task.isCompleted { - UnevenRoundedRectangle( - topLeadingRadius: 0, bottomLeadingRadius: 0, - bottomTrailingRadius: TaskRowMetrics.trailingCornerRadius, - topTrailingRadius: TaskRowMetrics.trailingCornerRadius - ) - .strokeBorder(Color.accentColor, lineWidth: 2) - } - } .overlay(alignment: .leading) { if !task.isCompleted { Rectangle() @@ -177,10 +167,18 @@ struct TaskRowView: View { .clipShape( UnevenRoundedRectangle( topLeadingRadius: 0, bottomLeadingRadius: 0, - bottomTrailingRadius: task.isCompleted ? 0 : TaskRowMetrics.trailingCornerRadius, - topTrailingRadius: task.isCompleted ? 0 : TaskRowMetrics.trailingCornerRadius + bottomTrailingRadius: TaskRowMetrics.trailingCornerRadius, + topTrailingRadius: TaskRowMetrics.trailingCornerRadius ) ) + .shadow( + color: isSelected && !task.isCompleted ? .selectionShadowLight : .clear, + radius: 4, x: 0, y: 2 + ) + .shadow( + color: isSelected && !task.isCompleted ? .selectionShadowDark : .clear, + radius: 10, x: 0, y: 0 + ) } @MainActor @@ -192,7 +190,7 @@ struct TaskRowView: View { @ViewBuilder private var cardBackground: some View { if task.isCompleted { - Color.clear + isSelected ? Color.completedSelected : Color.clear } else { Color.taskCard }