diff --git a/.jules/palette.md b/.jules/palette.md index f2d658a..15291fa 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -17,3 +17,6 @@ ## 2024-05-25 - Dynamic Labels and Disabled State Tooltips **Learning:** Users can feel confused when a primary button is disabled without explanation or when a long-running action lacks immediate inline text feedback on the button itself. **Action:** In SwiftUI, enhance button accessibility and UX by adding `.help()` tooltips to explain the required state when disabled, and using dynamic labels (e.g., 'Scanning...') to provide immediate feedback during async operations. +## 2024-05-26 - Dynamic Labels and Help Tooltips on MenuBar Actions +**Learning:** Buttons in compact UIs like MenuBars often lack space for inline error messages or status updates. When a primary action (like Scan or Clean) is disabled or processing, users need immediate contextual feedback to understand why. +**Action:** Always provide dynamic labels (e.g., "Scanning...") and use the `.help()` modifier to explain disabled states or ongoing operations, ensuring users aren't left guessing why a button is unresponsive. diff --git a/Sources/Cacheout/Views/MenuBarView.swift b/Sources/Cacheout/Views/MenuBarView.swift index 9084b59..d003f4a 100644 --- a/Sources/Cacheout/Views/MenuBarView.swift +++ b/Sources/Cacheout/Views/MenuBarView.swift @@ -214,11 +214,12 @@ struct MenuBarView: View { Button { Task { await viewModel.scan() } } label: { - Label("Scan", systemImage: "arrow.clockwise") + Label(viewModel.isScanning ? "Scanning..." : "Scan", systemImage: "arrow.clockwise") .font(.caption.weight(.medium)) } .buttonStyle(.bordered) .disabled(viewModel.isScanning) + .help(viewModel.isScanning ? "Scan in progress" : "Scan for caches") if viewModel.isScanning { ProgressView() @@ -241,6 +242,7 @@ struct MenuBarView: View { .buttonStyle(.borderedProminent) .tint(Color(red: 0.85, green: 0.45, blue: 0.1)) // burnt orange — readable white text .disabled(viewModel.totalRecoverable == 0 || viewModel.isCleaning) + .help(viewModel.isCleaning ? "Cleanup in progress" : (viewModel.totalRecoverable == 0 ? "No recoverable caches found" : "Quick clean recoverable items")) // Open main window Button { @@ -282,12 +284,13 @@ struct MenuBarView: View { Button { Task { await viewModel.dockerPrune() } } label: { - Text("Run") + Text(viewModel.isDockerPruning ? "Running..." : "Run") .font(.caption2.weight(.medium)) } .buttonStyle(.bordered) .controlSize(.mini) .disabled(viewModel.isDockerPruning) + .help(viewModel.isDockerPruning ? "Docker prune in progress" : "Run docker system prune") } }