Skip to content

polish(desktop): tutorial highlights only on controls, as a fading glow - #3164

Closed
janicduplessis wants to merge 2 commits into
mainfrom
polish/3154-tutorial-highlight
Closed

janicduplessis wants to merge 2 commits into
mainfrom
polish/3154-tutorial-highlight

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Description

The tutorial highlight appeared where it did not help. During "First iOS Build" it outlined the Build sheet's build detail card (the .buildSection anchor in BuildSheet.swift plus the tutorial hint injected into the sheet in WorkspaceDetail.swift) and, on the page behind, a status or build region. On "Rebuild from Cache" it outlined the header status line while the label talked about build details. The highlight was also a solid stroke with the label notched into its edge.

I could not reproduce the large page rectangle from the maintainer's screenshot (device tile through logs). In my copy the build step outlined the header status line only. I did not find which anchor produced the larger region; it no longer exists because the build anchors are gone.

Solution

Two commits:

  • Highlight only controls. A step is highlighted only when its label names one control the user must click or find. Steps whose outcome is just visible (build progress, cache badge, agent actions and replay) get no highlight; the panel text and the Show Me button stay (Show Me appears on the same steps as before). The Build sheet publishes no anchors and no longer receives the tutorial hint.
Step Highlight
sidebar kept: the tutorial workspace's sidebar row
build removed (was the header status line, and the Build sheet card)
rebuild removed (was the header status line)
device kept: the device tile, then the viewer's Control button
logs, refresh kept: the Logs tab/button
agent removed (was the agent actions panel and replay bar)
finish, done kept: the Archived filter
  • Glow. A blurred brand-purple halo with a 1 pt low-alpha edge and a capsule label above the target (below when there is no room above, kept inside the bottom edge). The pulse is driven by a TimelineView (about 1.4 s per cycle), so nothing animates once the glow has faded and left the view tree after 4 s. It shows again when the step or selected page changes, or when the target comes back after being absent for more than 1 s. Reduce Motion: no pulse, same fade.

Test plan

Own test copy via stim macos from apps/desktop, with a temporary local override forcing the tutorial step (not committed), so the maintainer's tutorial state was not changed. stim logs --errors was empty.

Before (header status line outlined, label notched in the border) and after (glow with capsule label, then faded after 4 s), build step, captured before the audit removed that step's highlight:

before
glow
faded

Not verified: dark mode crops and a glow crop on each kept step (sidebar, device, logs, Archived). The machine was at load average 700 and the test copy fell back to the setup guide, so I stopped capturing. swift build and swift test with -Xswiftc -warnings-as-errors, scripts/format.sh --check and check-ascii.mjs pass.

Fixes #3154

@janicduplessis janicduplessis left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fresh review of #3164 (diff, three commits, issue #3154, polish rules). Read from the diff and origin/polish/3154-tutorial-highlight; I did not build or run it. CI build was still pending.

Must fix

  1. The pulse never stops after the fade. TutorialGlow (Design/TutorialAnchors.swift, .onAppear, about line 148) starts repeatForever(autoreverses: true) on pulsed. The 4 s task only sets shown = false, which sets opacity to 0. The view stays in the tree and the animation keeps driving a blur and stroke-width change at opacity 0 until the step or page changes. That is the CPU cost you asked about. Fix: after the fade, remove the glow (render it only if shown, or call back to the parent to drop it). Or set pulsed = false with a non-repeating animation when fading, and start the pulse again when shown becomes true.

  2. "Show Me" now appears on steps that never had it. Before, the whole block was if let hint, let id = hint.anchor, so the fallback button only showed for steps with an anchor. Now it is if let hint, so the showFallback branch also runs for steps whose anchor is nil: begin, phone, machine and the default case. It shows whenever the tour workspace is not the selected page. Removing the build, rebuild and agent anchors keeps their button, as before (their id becomes nil and the match fails, so they fall to the same branch). The extra button on begin, phone and machine is a behavior change to a navigation control, and the polish definition excludes navigation changes. Either restrict the fallback to the steps that had it (hint.anchor != nil || ["build","rebuild","agent"].contains(hint.step)), or take it out of this polish PR into its own issue. Say which in the PR body.

Should fix

  1. The glow re-shows whenever the target view is recreated, so it is not limited to step and page changes. The glow is created only while a match exists and intersects the bounds. If the target leaves and re-enters (scrolling the sidebar or device list off screen and back, inspector toggle, a list re-render that drops the anchor for a pass), TutorialGlow is recreated, @State resets, and it glows for 4 s again. That matches "when the target first appears" in the PR body, but a transient re-render re-flashes. Staying on a static page does not repeat it. Decide whether this is acceptable; a "shown for this restartKey" record in the parent would stop it.

  2. The two commits that move the build anchor to the header and then remove it are churn. Commit 221dda8 adds .tutorialAnchor(.buildSection) on the header, and 7b5c67a removes it, so the net diff of the first commit disappears. The polish rule asks for one commit per change. Squash the build-anchor work into the audit commit so no commit leaves a state the PR does not ship.

  3. Commit prefixes. Recent polish PRs on main use polish(desktop): (a34e7fc, 32e7726, 7a274a4, 1cd98ea, cf6e365). The PR title matches, but all three commits use fix(desktop): / feat(desktop):. If the merge is a squash on the title this is harmless. If commits are kept, rename them to polish(desktop):.

Nits

  1. TutorialHint.callout default: ("Follow the tutorial workspace") is now unreachable, because the glow only renders when hint.anchor is non-nil. Delete it.
  2. id != nil && $0.key.id == id plus if let id, let match checks the same thing twice. Hoisting guard let id is simpler.
  3. The callout picks above or below the target by checking only rect.minY - 24 >= 0. The old code checked room below against geometry.size.height; the new fallback to below is unchecked. A target at the top that also reaches the bottom is unlikely, so low risk.
  4. reduceMotion is read once in onAppear. Toggling Reduce Motion while the glow is up does not stop a running pulse. This is rare; @Environment(\.accessibilityReduceMotion) itself is the right key.

Checked and fine

  • Timers: the 4 s sleep lives in .task(id: restartKey), so it is cancelled on disappear and on a key change, and Task.isCancelled guards the fade.
  • Restart: restartKey is step plus selected path, so a step or page change re-shows without remounting. A restart after a fade pops back to full opacity without animation, which is fine.
  • Step completion: it is driven by TutorialProgress / TutorialModel snapshots and does not read anchor preferences. No remaining reference to the removed keys (buildSection, cacheBadge, agentActions as anchor, replay) in apps/desktop; the other agentActions hits are unrelated retained-bytes fields. The .tutorialAnchor call sites that remain match the five enum cases (sidebarRow, deviceTile, viewerControl, logsTab, archivedFilter).
  • Show Me behavior for removed steps: RootView.tutorialHint.showMe still navigates and opens logs for "agent". Unchanged.
  • The Build sheet no longer gets the hint (.environment(\.tutorialHint) and .tutorialHighlights(showFallback: false) both removed), and the three duplicate .buildSection publishers are gone. .tutorialHighlights(showFallback:) is still used correctly on the root (true) and the viewer sheet (false).
  • Palette.onPrimary exists (Tokens.swift:79).
  • Beyond item 2, no commit changes commands, data, navigation or dependencies.
  • Gaps the author already listed: no dark-mode or per-step glow crops, and no screenshots of the final state on the kept steps. The polish rule asks for a screenshot or recording of each change on each affected platform; add at least the device and Logs steps.

Verdict: not clear to mark ready. Fix items 1 and 2, squash item 4, and add the missing screenshots. Items 3 and 5 are judgment calls.

@janicduplessis
janicduplessis force-pushed the polish/3154-tutorial-highlight branch from 7b5c67a to 01c0709 Compare October 9, 2026 18:39
janicduplessis added a commit that referenced this pull request Oct 10, 2026
Folds the fading glow from #3164: a pulsing halo with a capsule label that
fades after four seconds, only on controls a step names.

Refs #3366
@janicduplessis

Copy link
Copy Markdown
Collaborator Author

Folded into #3380: its fading glow (pulse, capsule label, 4 s fade, Reduce Motion) is in TutorialAnchors.swift there, rebuilt on current main. Closing this draft.

janicduplessis added a commit that referenced this pull request Oct 10, 2026
…view ticks, PR detection (#3380)

* feat(desktop): drop the tutorial's commands disclosure

Refs #3366

* feat(desktop): one Next button per tutorial step

Refs #3366

* feat(tutorial): give the parallel change a copyable prompt that asks for a new worktree

Refs #3366

* feat(tutorial): the agent checks each change on the device with agent-device

Refs #3366

* feat(desktop): tutorial glow points at the launch notice's Show button

Folds the fading glow from #3164: a pulsing halo with a capsule label that
fades after four seconds, only on controls a step names.

Refs #3366

* feat(desktop): Agent Actions and Replay step glows the actions list, then Replay, and ticks both

Refs #3366

* fix(desktop): Live View and Control ticks either tutorial simulator, glows its screen and stays in view

Refs #3366

* feat(desktop): Share Your Finish detects the pull request from the first change's worktree

Refs #3366

* fix(desktop): tint the tutorial's Open the build link

Refs #3366

* fix(desktop): let taps pass through the viewer's tutorial card; align docs with the removed manual section

Refs #3366
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

polish(desktop): tutorial highlight fixes

1 participant