aboutsummaryrefslogtreecommitdiff
path: root/Sources/NorgUI/Views/NorgTaskView.swift
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2026-06-15 14:35:36 +0200
committerRuben Beltran del Rio <jj@r.bdr.sh>2026-06-16 14:47:30 +0200
commit657aa83a5ca24dc35572c040df64a0abb85e8612 (patch)
treefe0b6fd425d8cad9dc6a28ada4ad8600e42b367e /Sources/NorgUI/Views/NorgTaskView.swift
Initial extraction from Norganize
Diffstat (limited to 'Sources/NorgUI/Views/NorgTaskView.swift')
-rw-r--r--Sources/NorgUI/Views/NorgTaskView.swift63
1 files changed, 63 insertions, 0 deletions
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
+ }
+}