Skip to content

🤖 refactor: style goal row actions as real buttons#3342

Merged
ammario merged 5 commits into
mainfrom
goals-vsn6
May 21, 2026
Merged

🤖 refactor: style goal row actions as real buttons#3342
ammario merged 5 commits into
mainfrom
goals-vsn6

Conversation

@ammar-agent
Copy link
Copy Markdown
Collaborator

@ammar-agent ammar-agent commented May 20, 2026

Summary

Make the Goal tab's Archive controls visually consistent with the rest of the tab, and reshape the completed-goal action row so Archive is the primary action and Reopen the secondary — matching user intent (a finished goal usually wants to be filed, only rarely reopened).

Background

Three layers of inconsistency lived on the Goal tab:

  1. Per-row controls in GoalBoardSections.tsx — Edit / Promote / Remove / Archive / Revive all rendered as bare <button>s with only text-muted + a small icon. They read as inline text labels rather than clickable controls and were inconsistent with the bordered Cancel / Save / Queue-goal buttons in the same file.

  2. Active-goal "Archive this goal" link in GoalTab.tsx — rendered as an underlined muted text link with an inline comment justifying the de-emphasis. After the row controls became buttons, this stood out as the last remaining text-link on the surface.

  3. Completed-goal action hierarchy was inverted — Reopen rendered with the green "primary" tint and Archive lived as a small chip on a separate line below. But filing a finished goal is the obvious next step; reopening is the rare recovery path when the agent declared done too eagerly.

The existing GoalTab.test.tsx mocks GoalBoardSections away entirely, and no existing GoalTab story set workspaceId, so the row Archive button had no automated visual coverage either.

Implementation

Row buttons (GoalBoardSections.tsx)

Added a small RowActionButton helper (exported so GoalTab.tsx can reuse it for the active-goal Clear). Renders a bordered chip-style <button> with a tone prop (neutral / positive / destructive) that tints hover color + background:

  • neutral — Edit / Archive (row) / Revive / Clear goal (active lifecycle)
  • positive — Promote (upcoming → active)
  • destructive — Remove (drops the goal from the board)

Converted all 5 row sites. Aria-labels, click handlers, and goal-context interpolation are preserved verbatim.

Completed-goal action row (GoalTab.tsx)

Restructured {canEdit && <div>…</div>} so that when lifecycle === "complete":

  • Reopen sits on the left with the neutral border-style used by Pause / Mark complete (border-border-light bg-surface-secondary text-foreground). Still available — just no longer looks like the primary action.
  • Archive sits to the right with the accent fill (bg-accent text-accent-foreground hover:bg-accent-dark) used by Save / Set goal. Same px-3 py-1.5 text-sm sizing as the rest of the row so the two buttons read as peers, not as a chip-style afterthought.

The canResume branch is narrowed to non-complete lifecycles to avoid double-rendering Reopen, and the chip-style "Archive this goal" below the action row is dropped for completed goals. Clear stays as a chip for lifecycle-active goals (destructive on an in-flight goal — deserves de-emphasis).

Story coverage

Added a CompleteWithBoard story to GoalTab.stories.tsx that renders the full tab with upcoming + completed + archived board entries so the new Reopen + Archive pair, the budget tile, the goal header, and every row-action button variant are all visible in one snapshot.

  • GoalTab only mounts GoalBoardSections when workspaceId is set, and the board reaches the renderer through useGoalBoard → api.workspace.getGoalBoard. To populate that path:
    • Added a goalBoardSnapshots: Map<workspaceId, GoalBoardSnapshot> option to createMockORPCClient. getGoalBoard returns the seeded snapshot for the calling workspace, or falls back to empty entries.
    • The story is wrapped in an APIProvider decorator backed by the mock client.
  • Tagged with CHROMATIC_SMOKE_MODES for dual-theme baseline coverage.

Tests

Tightened the existing clear control GoalTab test to assert the new primary/secondary hierarchy (bg-accent on Archive, neutral on Reopen) and the absence of "Clear goal" wording for completed goals, instead of the old underline className.

Validation

  • make typecheck, make lint, make fmt-check, make static-check, make storybook-build — all green.
  • bun test src/browser/features/RightSidebar/ — passes.
  • bun test ./tests/ui/storybook/coverage.test.ts — passes.

Risks

Low. Visual restyle + reordering of buttons inside a single component plus a new Storybook story and an additive option on the mock orpc client. No backend, IPC, or business-logic changes. Both completed-goal actions still route through the same backend endpoints they did before (workspace.setGoal({ status: "active" }) for Reopen, workspace.archiveGoal for Archive). Aria-labels are preserved for screen-reader behavior.


Generated with mux • Model: anthropic:claude-opus-4-7 • Thinking: max • Cost: $3.20

The Archive action on completed goals (and its sibling row actions —
Edit / Promote / Remove on upcoming, Revive on archived) rendered as
bare text+icon links with no border, padding, or background. They
looked like inline text instead of clickable controls, breaking visual
consistency with the bordered Cancel / Queue-goal buttons in the same
file and forcing the user to discover the affordance via hover.

Factor a local RowActionButton helper that renders a bordered chip-style
button with neutral / positive / destructive tones, and convert all 5
sites in GoalBoardSections.tsx. Aria-labels and click handlers are
preserved.

The de-emphasized 'Archive this goal' / 'Clear goal' underlined text
link in GoalTab.tsx is intentionally left alone — an inline comment
already documents that it's styled that way so it doesn't compete with
the primary Pause / Resume / Mark complete actions above.
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

GoalBoardSections owns the Archive / Revive / Edit / Promote / Remove
per-row buttons, but it has no story file of its own — and
GoalTab.test.tsx mocks GoalBoardSections away — so the recent restyle
to bordered chip-style RowActionButtons had zero automated visual
coverage.

Add a colocated GoalBoardSections.stories.tsx that:

- mounts the component under a lightweight APIProvider + TooltipProvider
  so the section subcomponents' useAPI() calls don't throw
- hand-rolls a GoalBoardSnapshot with upcoming, completed, and archived
  entries so every RowActionButton variant renders
- pins one smoke story (FullBoard) to CHROMATIC_SMOKE_MODES so a future
  regression on either theme is caught by Chromatic
- splits the remaining sections into focused stories (UpcomingOnly /
  CompletedOnly / ArchivedOnly / EmptyBoard) so individual surfaces are
  reviewable in isolation
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Added storybook coverage for the goal row-action buttons (GoalBoardSections.stories.tsx).

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Replace the standalone GoalBoardSections story with a full-tab
`CompleteWithBoard` story so the row Archive button (and its
RowActionButton siblings — Revive / Promote / Remove / Edit) render
in context alongside the goal header, budget tile, and de-emphasized
'Archive this goal' link.

GoalTab only mounts GoalBoardSections when `workspaceId` is set, and
the board reaches the renderer through `useGoalBoard → api.workspace
.getGoalBoard`. To populate that path in storybook:

- Add a `goalBoardSnapshots: Map<workspaceId, GoalBoardSnapshot>`
  option to `createMockORPCClient`; `getGoalBoard` returns the seeded
  snapshot for the calling workspace or falls back to empty entries.
- Wrap the new story in an `APIProvider` decorator backed by the mock
  client, with one upcoming / one completed / one archived entry.
- Tag the story with `CHROMATIC_SMOKE_MODES` so the restyle gains
  dual-theme baseline coverage in Chromatic.

`GoalTab.test.tsx` still mocks GoalBoardSections away, so this is the
only automated visual surface for the row-action buttons.
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Replaced the standalone GoalBoardSections story with a populated GoalTab story (CompleteWithBoard) so the Archive button is visible in the full-tab context. Added a goalBoardSnapshots option to the mock orpc client to seed getGoalBoard per workspace, and tagged the story with CHROMATIC_SMOKE_MODES for dual-theme baseline coverage.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Previously the 'Archive this goal' / 'Clear goal' affordance on the
active-goal card was rendered as an underlined muted text link with an
inline comment justifying the de-emphasis. With the rest of the goal
tab's Archive controls now sharing a chip-style RowActionButton, the
text-link variant was the last remaining link-vs-button anti-pattern on
the surface and stood out in the new Chromatic baseline.

Export RowActionButton from GoalBoardSections.tsx and reuse it here.
The action stays visually de-emphasized relative to Pause / Resume /
Mark complete by virtue of the smaller chip size and its position below
the primary action row. Inbox icon for 'Archive this goal' matches the
row Archive button in CompletedSection (which calls the same archiveGoal
endpoint); Trash2 for 'Clear goal' mirrors Remove in UpcomingRow.

The GoalTab test that previously asserted on the legacy 'underline'
className is updated to assert the meaningful behavioral guard (no
primary 'bg-accent' background) instead of the now-stale implementation
detail.
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Followed up: the "Archive this goal" affordance on the active-goal card now uses the same RowActionButton chip styling as the row controls (no more underlined text link). The de-emphasis intent is preserved via the smaller chip size + its position below the primary Pause/Resume/Mark-complete row. Visible in the CompleteWithBoard Chromatic story.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Previously a completed goal showed the green-tinted Reopen as the only
'main' action and Archive as a small chip below — but the user-intent
hierarchy is the opposite: when a goal is finished, filing it away is
the obvious next step, and Reopen is the rare recovery affordance for
goals the agent declared done too eagerly.

Restructure the action row so that when `lifecycle === "complete"`:

- Reopen sits on the left with the neutral border style used by Pause /
  Mark complete; it stays available but no longer looks like the primary
  action.
- Archive sits to the right of Reopen with the accent fill used by Save
  / Set goal; both buttons share the `px-3 py-1.5 text-sm` sizing of
  the rest of the action row so they read as peers.

The `canResume` branch is narrowed to non-complete lifecycles to avoid
double-rendering Reopen, and the underlined-link/chip 'Archive this
goal' below the action row is dropped for completed goals (Clear stays
as a chip for lifecycle-active goals — destructive for an in-flight
goal, deserves de-emphasis).

The GoalTab test that previously asserted on the legacy 'underline'
className was already updated last commit; tighten it further to assert
the new primary/secondary hierarchy (`bg-accent` on Archive, neutral
on Reopen) and the absence of 'Clear goal' wording for completed goals.
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Followed up: on completed goals, Archive now sits to the right of Reopen as the accent-colored primary action (filing is the obvious next step), while Reopen is demoted to the neutral border style as the secondary recovery path. Both buttons share the row's px-3 py-1.5 text-sm sizing so they read as peers. The chip-style "Archive this goal" below the action row is dropped for completed goals; Clear remains a chip for lifecycle-active goals (destructive — deserves de-emphasis). Test updated to guard the new primary/secondary hierarchy.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ammario ammario merged commit ba23f39 into main May 21, 2026
40 of 42 checks passed
@ammario ammario deleted the goals-vsn6 branch May 21, 2026 16:47
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.

2 participants