Skip to content

Improve the pin/unpin interaction design #4

Description

@qaid

Background

The floating panel has a pin button in the top-left of the custom header, implemented in DetailPanelContentView (Sources/Spook/App/AppDelegate.swift, lines ~209–216). When pinned, the panel stays visible when clicking outside it — the global event monitor skips closing it (setupClickOutsideMonitor()).

Current implementation:

  • Shows pin (unfilled) / pin.fill (filled) SF Symbol at 12pt
  • Changes button foreground color to .accentColor when pinned
  • Has a .help() tooltip

Problems

  1. Dated visual design: The SF Symbol pin / pin.fill (a map/pushpin icon) is not the most intuitive affordance for "keep this window visible". It can be confused with location pinning. Modern macOS apps often use lock / lock.open or a custom indicator for this concept.
  2. No panel-level visual feedback: When pinned, only the small header button changes. There is no indication on the panel boundary itself that it is locked in place — a user who isn't looking at the header corner has no visual cue.

What to Fix

1. Replace the pin icon

Use a more modern or recognisable icon pair. Recommended options (choose whichever communicates "keep visible / locked in place" most clearly):

  • lock.fill (pinned) / lock.open (unpinned)
  • pin.fill is acceptable if redesigned with better styling (e.g., larger hit target, more contrast)

The icon should be at least 13pt and have a generous tap target (min 24×24pt via .frame(width: 24, height: 24)).

2. Add a panel-level pinned indicator

When isPinned == true, apply a subtle visual change to the panel border. The panel border is currently rendered by this overlay in DetailPanelContentView:

.overlay(
    RoundedRectangle(cornerRadius: 10)
        .stroke(Color.gray.opacity(0.2), lineWidth: 1)
)

Change the stroke color conditionally:

.overlay(
    RoundedRectangle(cornerRadius: 10)
        .stroke(isPinned ? Color.accentColor.opacity(0.6) : Color.gray.opacity(0.2), lineWidth: isPinned ? 1.5 : 1)
)

This gives a clear, panel-wide visual cue without being disruptive.

3. Maintain existing functionality

  • The click-outside protection (setupClickOutsideMonitor) must remain unchanged.
  • Pin state should still reset when the panel closes (no persistence — this is by design).
  • Do not add a keyboard shortcut (out of scope).

Acceptance Criteria

  • The pin button uses an icon that clearly communicates "keep window visible" in a modern macOS style.
  • The icon has a minimum tap target of 24×24pt.
  • When pinned, the panel border changes to a non-gray color (e.g., accentColor) to provide panel-level feedback.
  • When unpinned, the panel border returns to the default subtle gray.
  • The existing pin/unpin toggle behaviour (preventing click-outside close) is unchanged.

Relevant File

  • Sources/Spook/App/AppDelegate.swift, DetailPanelContentView — lines ~200–248.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions