Repository navigation
Ambient strands behind every hero, and a shimmer border on the yearly plan - #42
Merged
Merged
Conversation
…yearly plan Two pieces of motion, both deliberately restrained. Strands: a slow field of luminous ribbons behind the hero, inspired by React Bits' component of that name. Written from scratch on a 2D canvas rather than adding ogl and a WebGL shader -- that library is ~25kB gzipped, against a page whose entire JS budget is about 2kB, for something purely decorative. Brand blues only, low alpha, and slow enough to read as ambient. It renders on all 13 pages: in PageHeader, which ten of them use, plus the home hero and the two pages that build their own (404 and privateAPI). The component takes multiple instances, selecting by attribute rather than id. It only animates when it is actually on screen and the tab is visible, via an IntersectionObserver and a visibilitychange handler, and it draws one still frame up front so it is never blank. prefers-reduced-motion leaves that still frame and starts no loop, and a change of preference is honoured without a reload. Shimmer: a highlight that travels around the edge of the yearly plan card. A conic gradient rotates behind the card and is masked down to the border ring with mask-composite, so one highlight runs the whole perimeter, corners included. React Bits' "Star Border" slides two radial gradients along the top and bottom edges instead, which reads as two streaks passing rather than a shimmer going around -- the wrong feel for a card, so this is built differently on purpose. The angle is a registered @Property, since a bare custom property cannot be interpolated; where that is unsupported the ring simply sits still. Both are aria-hidden and cannot take pointer events. The shimmer masks itself rather than clipping its parent, so the "Best value" badge overhanging the card is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts: # src/pages/pricing/index.astro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two pieces of motion, both deliberately restrained.
Strands
A slow field of luminous ribbons behind the hero, inspired by React Bits' Strands.
Written from scratch on a 2D canvas rather than adding
ogland a WebGL shader. That library is ~25kB gzipped, against a home page whose entire JS budget is about 2kB — a lot of weight for something purely decorative. Brand blues only, low alpha, slow enough to read as ambient.On all 13 pages: via
PageHeader(which ten of them use), plus the home hero and the two pages that build their own (404,privateAPI). The component takes multiple instances, selecting by attribute rather than id.Behaviour:
IntersectionObserver+visibilitychange)prefers-reduced-motionkeeps the still frame and starts no loop, and a change of preference is honoured without a reloadShimmer border on the yearly plan
A highlight that travels around the edge of the card. A conic gradient rotates behind it, masked to the border ring with
mask-composite, so one highlight runs the whole perimeter, corners included.React Bits' Star Border slides two radial gradients along the top and bottom edges, which reads as two streaks passing rather than a shimmer going around — the wrong feel for a card, so this is built differently on purpose.
The angle is a registered
@property, since a bare custom property can't be interpolated; where that isn't supported the ring simply sits still.Both
aria-hidden, no pointer events. The shimmer masks itself rather than clipping its parent, so the "Best value" badge overhanging the card is unaffected.Note on verification
I verified structure, stacking, masking and that the animations register as running — but not the motion itself, because the browser pane here stops compositing and freezes animation clocks. Worth an eyeball before merging.
🤖 Generated with Claude Code