aboutsummaryrefslogtreecommitdiff
path: root/Sources/NorgUI/Views/NorgTaskView.swift
diff options
context:
space:
mode:
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
+ }
+}