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:
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
}