githubnext/chopinPublic

Let's compose rich plans together

Open a GitHub card from a pill on hover, focus or caret #435

OpenMaggieAppletonwants to merge 0 commits intogithub-pills/2-pillsfromrefs/pull/435/head
  1. MA

    **Stack:** 1. #429 (summary route, merged) → 2. #434 (pills) → **3. this PR (hover card), based on `github-pills/2-pills`**. Merge #434 first; rebase-merge only.

    GitHub pills now open card B from the jig review, simplified as Maggie specified.

    ## The card

    Rows, top to bottom: 1. Tinted state glyph (`role="img"`, accessible name such as "Merged pull request"), then the title (up to 3 lines) and a quiet `#number` 2. Relative time on its own quaternary line: merged, closed, updated or opened 3. Author: real avatar (18px, faint ring, initial if the image fails) and login 4. Last row, 12px above: the head branch for pull requests, or label chips for issues. Pull requests never show labels.

    - There are no field headings, repository name, state text, activity row or "·" separators. - Label chips use a hairline in `--color-control-edge` with no fill: 22px tall, 8px/10px inline padding, a 10px dot, a 6px gap, `--text-xs`, and 6px between chips. - **Label colour:** GitHub's arbitrary label hex is never drawn. The hue maps to the nearest shared graphic role (danger, warning, success, brand, merged, or neutral for greys). That keeps authored colour out of the interface, and needs no dynamic-style exception. - **Other states:** loading shows a skeleton of the same rows. No access shows `<repo> #N`, "Chopin can’t read this repository." and "Open on GitHub ↗" in the same layout. - **Motion:** 12px offset, the dropdown open/close tokens. Reduced motion drops the scale and the skeleton pulse.

    ## How it opens, and how it fits with the link preview

    Lexical owns the pill's `<a>`, so there is no Base UI trigger to render. `github-hover.tsx` drives a controlled `PreviewCard.Root`, with `Positioner anchor` set to the live `<a>`. Delegated listeners on the editor root do the trigger's job: - pointer hover opens after 450ms and closes after 120ms; the popup's own hover keeps it open - keyboard focus opens it immediately; links only take focus in read-only documents - Escape closes it

    Reconciling with the caret-driven `LinkPreview` in `toolbar/link.tsx`: - **Caret in a GitHub link** (keyboard or click in an editable document; click in a read-only one): the existing link preview shows the same card above its URL / Open / Edit row. That is the keyboard path in editable documents. - **The hover card stays away** from a pill that holds the caret or was just pressed. It also closes when the caret arrives. The two surfaces never show the same pill twice.

    `@base-ui/react` 1.7.0 was already a declared dependency of `@chopin/editor`; the jig's relative import is not used.

    ## Tests

    - Unit tests (`github-card.test.tsx`): relative time, which moment the card shows, label tone mapping, row order (author before branch or labels), PRs never show labels, loading and no-access layouts. - `e2e/github-cards.e2e.ts`: - hover opens and closes the card - the caret entering a pill by keyboard shows the card once, inside the link preview, and hovering adds nothing - pressing a hovered pill hands it to the preview - The e2e passed twice locally against my own server on a non-default port, together with #434's pill specs. I also checked read-only Tab focus (the card opens) and Enter (the link preview shows a single card) in a headless browser. - `bun run fix`, `bun test` (4263 pass), `bun run types` and `bun run ci` all pass.

    ## Needs a design-contract review

    None. No review hash changed.

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

  2. Unknown GitHub usercommitted cd6cc336b6fclast month on GitHub