Pro

Merge status

Pro component

A pull request in one line: its number linking out, where it stands (draft, checks running, a check failed, conflicts, ready, merged) in its status color, and the move it's waiting for: a Merge button in the success color once it's ready, busy until the merge lands.

#8376 (opens in a new tab)Draft
Every state
#8371Draft
#8372Checks running · 2 of 5
#83732 checks failed
#8374Conflicts with main
#8375Ready to merge
#8370Merged into main

Installation

This is a Pro component. UI Polish Pro costs $149 one time and includes every Pro component, block and template, now and later. Add your license key to your MCP connection or components.json, then install it either way below.

With UI Polish connected, ask your agent:

Add the UI Polish merge status to this project.

Or with the shadcn CLI:

npx shadcn@latest add @uipolish/merge-status
Brings inButton, Icons, Text, Text morph

A pull request in one line: its number, which links out, where it stands in its status color (draft, checks running, a check failed, conflicts, ready, merged) and the one move it's waiting for. Once it's ready that's Merge, in the success color, the only colored button on the screen; it holds a busy state until the merge lands and says why if it doesn't.

TSX
<MergeStatus  number={8376}  href="https://github.com/acme/web/pull/8376"  state={state}  checks={{ passed: 3, failed: 0, total: 5 }}  base="main"  onMerge={() => api.merge(session.id)}/>

When to use it

  • The head of a review pane or a pull request's page: what's in the way of shipping, and the button that ships it.
  • An agent's session that opened a pull request, so the person can merge without leaving it.

When not to

  • A list of many pull requests: show each one's state as a Badge in its row, and keep this for the one that's open.
  • Checks in detail: put Tool steps (or your checks list) under it; this line only counts them.

States

StateMarkTextButton
draftA dashed ring, text color“Draft”None, or your action (“Ready for review”)
checks-runningTool steps' working mark: a dot breathing in a ring, accent“Checks running · 3 of 5” (the count only with checks)Merge, disabled
checks-failedAlert, danger“1 check failed”Merge, disabled, or your action (“Fix checks”)
conflictsWarning, amber“Conflicts with main”Merge, disabled
readyCheck, success“Ready to merge”Merge, in the success color
mergingas readyas readyMerge holds its label, then shimmers “Merging…” after 300ms; presses are ignored
merge failedAlert, dangerThe rejection's messageMerge, enabled again
mergedCheck, text color“Merged into main”None
closedClose, text color“Closed”None

A new state clears an old failure. The text morphs between states and its color eases, so a change reads as the same line moving on.

Props

PropWhat it does
number, hrefThe pull request's number and where it opens (a new tab)
stateOne of the states above
checks{ passed, failed?, total } for the running count and the failed count
baseThe branch it merges into. “main” by default
onMergeMerge. Return a promise for the busy state; a rejection's message shows in the bar
mergeLabel“Merge” by default; “Squash and merge” for a squash-only repository
actionTakes the button's place in any state

Layout

One row, 40px: the button's height. The number is 13px mono, medium, on a link pill whose padding hangs into the gap, so its text lines up with the pane's. The state is 13px with a 14px mark. The button sits at the end. Under 340px the separator goes and the state gives way to the button.

Motion

WhatDurationEasing
Text changingText morph--ui-ease-move
Color changing--ui-dur-base--ui-ease-color
Working dot--ui-dur-pulse each way, alternate--ui-ease-pulse
Merge's busy labelafter 300ms, at least 400msButton

With reduced motion the dot fades instead of breathing, and colors switch at once.

Accessibility

  • The state is a role="status" region, so “Ready to merge” and a failure are announced as they change.
  • The number says it opens in a new tab.
  • A disabled Merge sits beside the words that say why.
  • Text on the success fill is --ui-on-success: white on the light theme's green, ink on the dark theme's lighter one.

Before / after

Before: a green badge that says “Open” whatever the checks say, and a Merge button that's always enabled and fails silently.

TSX
<span className="badge green">Open</span> <button onClick={merge}>Merge</button>

After:

TSX
<MergeStatus number={pr.number} href={pr.url} state={state} checks={counts} onMerge={merge} />