From 657aa83a5ca24dc35572c040df64a0abb85e8612 Mon Sep 17 00:00:00 2001 From: Ruben Beltran del Rio Date: Mon, 15 Jun 2026 14:35:36 +0200 Subject: Initial extraction from Norganize --- Sources/NorgUI/Views/NorgTaskView.swift | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Sources/NorgUI/Views/NorgTaskView.swift (limited to 'Sources/NorgUI/Views/NorgTaskView.swift') diff --git a/Sources/NorgUI/Views/NorgTaskView.swift b/Sources/NorgUI/Views/NorgTaskView.swift new file mode 100644 index 0000000..cfe48c0 --- /dev/null +++ b/Sources/NorgUI/Views/NorgTaskView.swift @@ -0,0 +1,63 @@ +import NorgKit +import SwiftUI + +public struct NorgTaskView: View { + @Environment(\.norgTheme) private var theme + + let status: TaskStatus + let text: AttributedString + var font: Font + let onToggle: () -> Void + let onSetStatus: (TaskStatus) -> Void + + public init( + status: TaskStatus, + text: AttributedString, + font: Font = .body, + onToggle: @escaping () -> Void, + onSetStatus: @escaping (TaskStatus) -> Void + ) { + self.status = status + self.text = text + self.font = font + self.onToggle = onToggle + self.onSetStatus = onSetStatus + } + + public var body: some View { + HStack(alignment: .firstTextBaseline, spacing: 8) { + statusButton + Text(text) + .font(font) + .strikethrough(isResolved, color: .secondary) + .foregroundStyle(isResolved ? .secondary : .primary) + } + } + + private var statusButton: some View { + Button(action: onToggle) { + Image(systemName: theme.statusSymbol(status)) + .font(font) + .foregroundStyle(theme.statusTint(status)) + } + .buttonStyle(.plain) + .contextMenu { + ForEach(TaskStatus.allCases) { option in + Button { + onSetStatus(option) + } label: { + Label { + Text(theme.statusLabel(option)) + } icon: { + Image(systemName: theme.statusSymbol(option)) + } + } + } + } + .accessibilityLabel(Text("Task status: \(Text(theme.statusLabel(status)))", bundle: .module)) + } + + private var isResolved: Bool { + status == .done || status == .cancelled + } +} -- cgit