Skip to content

feat(docs): build the Performant card's story - #243

Merged
hunterbecton merged 8 commits into
mainfrom
hunter/sha-215-build-the-performant-cards-story
Oct 11, 2026
Merged

hunterbecton merged 8 commits into
mainfrom
hunter/sha-215-build-the-performant-cards-story

Conversation

@hunterbecton

Copy link
Copy Markdown
Member

Why

The Performant feature card still showed the image exported from the mock. SHA-215 rebuilds its illustration in code and gives it a story that plays on hover.

What changes

The Performant story

The card shows the mock's GPU chip alone, 1.5 times the mock's size, in the lit look the mock gives its CPU chip. The motion brief dropped the CPU chip, so the GPU does the work on its own. On the still frame the chip glows softly with nothing under it. A hover streams particles into a band under the chip, some rising into the pins and some falling out, and brings the halo up to the mock's full glow. When the pointer leaves, nothing new enters, each particle finishes its trip, and the halo settles back. The illustration is DOM, driven by one Motion frame loop that runs only during a play. SHA-178's features section decisions record the values.

A story that holds

story.tsx gains useHeldStory() beside useStory(). A hover starts the story, it holds while the pointer stays, and its ending plays once the pointer leaves. Both hooks share one hover gate, so the Extensible card behaves as before, and its spec still passes.

Particles at the window's edge

A particle is transparent until it enters the band and after it leaves, and the band clips itself. A clip alone isn't enough, because where the band's edge meets the window's rounded clip, a browser can let a pixel's sliver of a waiting particle through.

Tests

features-performant.spec.ts covers the hover, the drain back to an empty still frame, a hover during the drain, touch, a touch-screen laptop, and reduced motion. homepage.spec.ts now finds a code-built illustration by text it shows, because two cards have one.

Replace the exported image with two gray chips drawn from the mock, with
no work flowing to either. The story hands the work to the GPU from here
and winds it down back to this frame.
Add useHeldStory beside useStory: a hover plays the story's opening, the
story holds while the pointer stays, and its ending plays once the pointer
leaves. Each part finishes once started. Both shapes share one hover gate,
so the Extensible card's repeating story behaves as before.
Draw the mock's GPU chip alone at 1.5 times its size. A hover warms the
chip and starts a band of work flowing into and out of its pins, which
runs while the pointer stays. Leaving cuts back to the still frame until
the ending lands.
The still frame now shows the chip softly lit with no work under it. A
hover streams particles in from the band's ends and brings the halo up to
the mock's full glow. Once the pointer leaves, nothing new enters, each
particle finishes its trip, and the halo settles as the last one leaves.

Particles waiting at either end of the band are transparent, and the band
clips itself, so none shows at the window's edge in any browser.

The band streams in from the hover, so the held story drops its opening
stage: a hover goes straight to the hold.
Check that a hover streams the band in and that it runs dry after the
pointer leaves, back to the still frame. A hover during that ending must
not cut it short, and touch and reduced motion must leave the still frame.
The band carries a data-band attribute for the spec to find it.
Copilot AI balanced review requested due to automatic review settings October 11, 2026 00:22
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 53f166e.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The drain can admit delayed particles after the pointer has already left.

1 open finding
What changed in this PR

Rebuilds the Performant homepage card’s illustration in React/CSS and adds its hover-driven particle story.

Changes:

  • Adds the GPU chip, particle flow, and glow animation.
  • Introduces reusable held-story lifecycle handling.
  • Adds Playwright coverage for interaction and motion preferences.
File Description
apps/​docs/​src/​components/​features/​story.tsx Adds shared pointer handling and held stories.
apps/​docs/​src/​components/​features/​performant-illustration.tsx Implements the animated illustration.
apps/​docs/​src/​components/​features/​performant-illustration.module.css Styles the chip, glow, and particles.
apps/​docs/​src/​components/​features/​features.tsx Installs the code-built illustration.
apps/​docs-tests/​docs/​homepage.spec.ts Updates illustration presence assertions.
apps/​docs-tests/​docs/​features-performant.spec.ts Tests hover, touch, draining, and reduced motion.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/docs/src/components/features/performant-illustration.tsx
Copilot AI balanced review requested due to automatic review settings October 11, 2026 00:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Passive effect timing can allow particles to enter after pointer leave, and halo activation lacks regression coverage.

0 open findings

1 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Medium severity Synchronize stage ref in layout effect before animation frames

apps/​docs/​src/​components/​features/​performant-illustration.tsx:254

The frame loop can observe the previous stage for one frame after a pointer leave because this ref is synchronized in a passive effect, which may run after Motion's next animation-frame callback. If a delayed particle enters during that frame, the following ending frame sees a positive trip count and drains it even though it entered after the leave. Synchronize stageRef in a layout effect (before animation frames run) so ending captures the pre-leave particle set.

Medium severity Add Playwright assertion for full hover halo opacity

apps/​docs/​src/​components/​features/​performant-illustration.tsx:314

The new hover specs only observe particle count/position; none checks this halo branch, so the halo could remain at the still-frame value and every test would pass. Add a Playwright assertion that the chip halo reaches its full computed opacity while the pointer remains on the card (the existing final screenshot already covers the return to the still value).

🧠 Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 11, 2026 00:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The implementation is coherent, preserves existing story behavior, and includes strong interaction coverage.

0 open findings

🧠 Review effort: Balanced

@hunterbecton
hunterbecton merged commit 2c95be9 into main Oct 11, 2026
12 of 19 checks passed
@hunterbecton
hunterbecton deleted the hunter/sha-215-build-the-performant-cards-story branch October 11, 2026 01:07
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