textReveal
Character by character
416 components · 0 dependencies · MIT
Not a folder of fades. Variable-font axes that bend to the pointer, words that morph letter by letter, carousels built on the browser's own scrolling, menus that actually trap focus.
01Everything, listed
Every component and the attribute that drives it. Most of the kit needs no JavaScript at the call site at all.
data-rm-textdata-rm-decryptdata-rm-glitchdata-rm-shinydata-rm-countdata-rm-typedata-rm-wavedata-rm-outlinedata-rm-rolldata-rm-countdown—data-rm-pressuredata-rm-morphdata-rm-curvedata-rm-odometerdata-rm-highlightdata-rm-filldata-rm-shimmerdata-rm-sparkdata-rm-swapdata-rm-ripplejsdata-rm-underlinedata-rm-pressdata-rm-halodata-rm-strokedata-rm-btn ×52data-rm-floatdata-rm-growdata-rm-count-charsdata-rm-passworddata-rm-validatedata-rm-rangedata-rm-dropdata-rm-stepsdata-rm-field-focusdata-rm-submitdata-rm-mascotdata-rm-successdata-rm-otpdata-rm-lockdata-rm-islanddata-rm-sheetdata-rm-segmenteddata-rm-frosteddata-rm-modaldata-rm-actionsjsdata-rm-contextdata-rm-skeletondata-rm-spinner ×6data-rm-progress-bardata-rm-dots-loaderdata-rm-statusdata-rm-badgedata-rm-emptydata-rm-sparklinedata-rm-barsdata-rm-donutdata-rm-gaugedata-rm-statdata-rm-ratingdata-rm-inputdata-rm-searchdata-rm-tagsdata-rm-selectdata-rm-clearabledata-rm-maskdata-rm-inline-editdata-rm-circle-navdata-rm-curtain-navdata-rm-hover-spreaddata-rm-breadcrumbsdata-rm-treedata-rm-split-navdata-rm-stack-navdata-rm-dot-navdata-rm-ringsdata-rm-hexdata-rm-plusdata-rm-diagonalsdata-rm-topographydata-rm-circuitdata-rm-vignettedata-rm-halftonedata-rm-scrollbardata-rm-dropdowndata-rm-tooltipdata-rm-toggledata-rm-spotlightdata-rm-tiltdata-rm-borderdata-rm-card-kit ×24data-rm-layersdata-rm-edgedata-rm-fandata-rm-card-parallaxdata-rm-glaredata-rm-traildata-rm-electricdata-rm-beamdata-rm-blur-edgejsjsjsjsdata-rm-meteorsdata-rm-sparklesdata-rm-lampdata-rm-beamsdata-rm-meshdata-rm-starsdata-rm-dotsdata-rm-stripesdata-rm-scanlinedata-rm-cornersdata-rm-carouseldata-rm-ringdata-rm-deckdata-rm-dockdata-rm-panelsdata-rm-comparedata-rm-scratchdata-rm-image-traildata-rm-orbitdata-rm-linesdata-rm-coverflowdata-rm-thumbsdata-rm-autoplaydata-rm-wheeldata-rm-peekdata-rm-tickerdata-rm-slideshowdata-rm-dragdata-rm-shuffledata-rm-accordiondata-rm-flipdata-rm-expanddata-rm-lightboxdata-rm-image-revealdata-rm-pixeldata-rm-previewdata-rm-marqueejsjsjsjsdata-rm-magneticdata-rm-reveal ×50data-rm-parallaxdata-rm-progressdata-rm-horizontaldata-rm-stackdata-rm-scrubdata-rm-skewdata-rm-tracingdata-rm-flattendata-rm-stickydata-rm-mosaicdata-rm-zoom-outdata-rm-lines-indata-rm-text-maskdata-rm-timelinedata-rm-split-scrolldata-rm-reveal-griddata-rm-pinneddata-rm-pilldata-rm-gooeydata-rm-condensedata-rm-overlaydata-rm-tabsdata-rm-spydata-rm-ring-progressdata-rm-commanddata-rm-sidebardata-rm-raildata-rm-bottomdata-rm-megajs02Everything, running
Nothing here is a recording. Hover, press, drag. The ones that normally play once are set to repeat so you can actually see them.
textReveal
Character by character
decrypt
SOYRAGE AGENCY
glitch
404
shiny
Available for work
countUp
1,250
typewriter
waveText hover
Run the pointer over
morph
pressure hover
Pressure
odometer
128,400
curve
marquee drag any row · scroll the page · one runs upward
spotlight hover
tilt hover
border
glare hover
trail
electric
beam
blurEdge
Focus falls off gradually, the way a lens does it — stacked layers, each blurred harder and masked to a narrower band.
One backdrop-filter with a mask blurs everything equally and reads as a smear.
waves hover
retroGrid
dotGrid hover
fill · shimmer · spark · swap · ripple · magnetic hover every one
Six effects on one surface, so you can tell them apart. Black on cream here and cream on black everywhere else — the same components, no second code path.
cursor · target · crosshair · splash
A custom cursor is a page-level decision, so init() leaves it alone. Switch this page's:
carousel drag · arrow keys
pressure · morph · curve · odometer · highlight
beam · trail · glare · electric · blurEdge
waves · retroGrid · dotGrid · grain
carousel · ring · deck · dock · scratch · imageTrail
pill · gooey · condense · overlay · tabs
fill · shimmer · spark · swap · ripple
ring drag · arrow keys
deck
panels hover · tab
orbit
magnetLines hover
dock hover
imageReveal
pixelate hover
scratch drag
hoverPreview hover the rows
imageTrail sweep the pointer
meteors
sparkles
Launch day
lamp
beams
outline scroll
Fills as you scroll
countdown
flip hover · enter
expand click a card
accordion
The height animates from 0fr to 1fr on a grid row, so nothing is measured and nothing is hardcoded.
An image that loads late, a font that swaps, text that rewraps — every version built on scrollHeight breaks on all three.
aria-expanded, aria-controls, and a labelled region.
lightbox click
drag throw it · arrows
confetti press
shuffle filter it
rollText hover the links
scrollbar five looks · scroll them
dropdown arrow keys
tooltip · toggle
underline · press · halo · strokeDraw
corners hover
mesh
starfield scroll
dots
stripes
scanline
Every named start state, on the same component. Scroll them into view — each plays as it arrives, and each runs backwards if you scroll away and come back.
One component, fifty-two named looks. Hover them, reach them with Tab, press them. None replaces the element underneath.
command press ⌘K or ctrl-K
sidebar escape closes
rail follows the page
bottomNav tap one
mega hover intent
mascot · passwordToggle · floatLabel type in it
successButton press it
padlock type 1234
otp type · paste a code
rangeFill
toggle · charCount
autoGrow · validate leave it empty and blur
masonry resize the window
swipeStack drag · arrow keys
filmstrip drag it
hoverPeek hover the titles
polaroids hover · tab
foldGallery hover a panel
gridZoom click a tile
crossfade arrow keys
parallaxGrid scroll
tiltGrid move the pointer
maskReveal scroll
slats scroll
zoomStrip scroll it sideways
spiralGallery scroll
imageWall drag · arrow keys
flipGrid scroll into view
peelStack press the button
focusGrid hover · tab
ribbon scroll
contactSheet click a frame
searchField press the icon
tagsField Enter · Backspace
selectField · clearable
maskField edit the middle
inlineEdit click the title
inputKit three of twenty-four
One component, twenty-four named looks. Type in them, reach them with Tab. Every one keeps the real input underneath, so autofill, paste, undo and your password manager all still work.
One component, twenty-four named looks. None of them animates a width or a height, so a grid of cards never reflows while you move across it.
mosaic assembles from the middle out
lineByLine
Prose arrives a line at a time, because a paragraph read one word at a time is a reading test rather than an effect. The lines are re-split when the width changes, since a line is a fact about the layout and not a property of the text.
timeline
revealGrid a wave from the corner
coverflow scroll it sideways
thumbs pick one, or scroll the frame
wheel hover · arrows
slideshow real controls
ticker opposing rows
autoplay it stops when you touch it
peek the next one shows
island press to change it
sheet drag the grip down
segmented arrow keys
springModal · actionSheet
toast hover the stack to hold it
contextMenu right-click · menu key
spinner six shapes
skeleton
progressBar · dotsLoader
pulseDot · badgeCount
emptyState
An empty state is the moment a product either explains itself or looks broken.
Add the first onesparkline drawn, not scaled
bars
donut · gauge
stat · stars
pill hover · tab
gooey hover · tab
overlay keyboard safe
tabs arrow keys
Move right and the panel arrives from the right; move back and it comes from the left. One comparison, and the difference between tabs that feel spatial and tabs that blink.
A real tablist: arrow keys, Home and End, roving tabindex, and panels genuinely hidden when inactive rather than parked off screen.
Under reduced motion the slide is dropped and the switch is instant. The content was the point; the direction was the flourish.
circleNav arrow keys
curtainNav Escape closes
hoverSpread hover · tab
breadcrumbs open the middle
treeNav arrows · Right opens
splitNav parts open
stackNav deals out
dotNav follows the page
toastStack
snackbar
banner
inlineAlert
The content this wraps around.
pushCard
The content this wraps around.
bell
counter
presenceDot
ribbonAlert
The content this wraps around.
statusBar
progressToast
undoBar
confirmSheet
The content this wraps around.
countdownNote
stackedAvatars
typingDots
Ana is typing
liveTicker
pillAlert
cornerToast
soundBadge
taskList
taskCheck
taskReorder
taskGroup
kanban
taskProgress
taskFilter
subtasks
taskDue
taskPriority
taskAssignee
taskSwipe
taskUndo
The content this wraps around.
taskCount
taskEmpty
Nothing left today.
taskSearch
taskBulk
taskTimer
taskStreak
taskNote
Client wants the blue version by Friday.
areaChart
stepChart
candlestick
| Mon |
waterfall
radar
heatCalendar
bulletChart
funnel
treemap
progressRings
comparisonBars
sparkBars
deltaBadge
bigNumber
rangeBar
pieSlices
scatterPlot
timelineChart
meterRow
numberTicker
strengthMeter
sliderPair
ratingSlider
colourField
dateField
signaturePad
switchRow
quantityStepper
consentBox
The content this wraps around.
the termsThe content this wraps around.
formProgress
errorSummary
avatar
avatarUpload
profileCard
profileHeader
userMenu
accountSwitcher
presenceRing
followButton
bioReveal
Nora Vale has been recording rivers since 2016. Mostly at dawn.
socialRow
statsRow
badgeRow
profileTabs
The content this wraps around.
The content this wraps around.
coverParallax
identityChip
scrollCounter
scrollRotate
The content this wraps around.
scrollScale
The content this wraps around.
scrollBlur
scrollColour
The content this wraps around.
pinSteps
The content this wraps around.
The content this wraps around.
scrollDraw
depthLayers
scrollSnapSections
revealMaskScroll
The content this wraps around.
marqueeScroll
scrollGradient
The content this wraps around.
scrollSplit
Behind
scrollZoomPin
scrollTypeScale
productCard
productGallery
productZoom
colourSwatches
sizePicker
priceTag
discountBadge
stockMeter
ratingStars
reviewSummary
addToCart
wishlistHeart
compareTray
quickView
Heavyweight, garment dyed.
productTabs
variantPicker
breadcrumbTrail
sortBar
filterPanel
resultCount
cartDrawer
cartLine
cartTotals
cartEmpty
The content this wraps around.
Everything in this demo shop is invented.
cartBadge
miniCart
Two invented items.
freeShippingBar
couponField
checkoutSteps
orderSummary
paymentMethods
addressForm
deliveryOptions
giftNote
orderConfirm
A demonstration confirmation for an invented shop.
orderTracking
returnRequest
invoiceRow
| INV-DEMO-004 | £48.00 |
| Two invented items, delivered. | |
saveForLater
recentlyViewed
pricingTable
£0
£24
£78
planToggle
featureMatrix
| Feature | Starter | Studio |
|---|---|---|
| Custom domain | — | ✓ |
savingsBadge
quoteCard
They rebuilt our checkout in a fortnight.
logoWall
ratingRow
faqList
helpTip
shortcutSheet
tourStep
checklistCard
welcomeCard
Three things worth doing first.
footerColumns
announcementRow
Free shipping this week
New: dark mode is live
megaFooter
sortableTable
| Client | MRR |
|---|---|
| Acme | £2,400 |
stickyHeaderTable
| Invoice | Amount |
|---|
rowExpand
| INV-0042 | £1,200 |
| Paid 3 September by card ending 4242. | |
tableEmpty
| Invoice | Amount |
|---|
codeBlock
import { codeBlock } from "@soyrageagency/rage-motion";
diffView
apiRow
Creates a charge.
uptimeDots
changelogFeed
Sortable tables.
bentoGrid
splitPanel
stickyAside
dividerMark
sectionMark
heroBanner
Stoneware thrown in small batches at the Cloudberry Studio, a shop that does not exist.
See the collectioncollectionGrid
€24
€24
€38
lookbook
categoryTiles
saleCountdown
Winter sale ends in
bundleBuilder
sizeGuide
| Size | Chest | Length |
|---|---|---|
| S | 96 | 70 |
| M | 104 | 72 |
| S | 38 | 27.5 |
| M | 41 | 28.5 |
stockNotify
productVideo
swatchGallery
badgeStack
trustRow
shippingEstimate
recentlyBought
crossSell
upsellRow
giftCard
loyaltyPoints
referralBox
subscribeBox
orderList
orderCard
Placed 4 April 2031 · £48.00
orderStatusPill
Order RM-0032
trackingMap
deliverySlot
addressBook
addressCard
paymentCards
subscriptionCard
£14.00 a month, cancel whenever you like.
pauseSubscription
Kelp coffee, every month (invented)
invoiceList
downloadRow
wishlistGrid
reviewForm
reviewCard
Bought this for the studio and it has survived a winter of being knocked off the bench. The glaze has one chip and that was entirely my fault.
questionAnswer
supportTicket
Thanks for getting in touch — we have asked the courier for the drop-off photograph.
chatBubble
Thanks for the photograph.
No problem — the box was empty when it arrived.
refundStatus
accountNav
rings
hexGrid hover
plusGrid
diagonals
topography
circuit
vignette scroll
halftone hover
03Made of scrolling
Which means every one of these runs backwards too. An animation that only plays forwards feels broken the instant somebody scrolls the other way — and most of them do.
tracing
A line drawn down the article as you read it: a real path revealed with
stroke-dashoffset, which is why it can curve and why the
glowing head sits exactly on it.
And here is highlight — the paragraph fills word by word as it crosses the viewport. The unlit state is a muted colour, never an opacity of zero, because prose you cannot read until you have scrolled far enough is a reading tax.
parallax
scrub
--rm-progress runs 0 → 1 as this block crosses the
viewport, and the stylesheet decides what that means. Anything
expressible in CSS becomes scroll-driven without another component.
flatten
stack
Cards pile up and shrink as you pass them. The sticking is position: sticky; only the scale and the brightness are computed.
Every card sticks a little further down than the last, so the pile stays readable at the top rather than disappearing behind the front one.
Under reduced motion the whole effect is dropped and they are simply three cards, in order, at full size.
sticky
The pin is CSS. The only JavaScript decides which panel is in the reading position and swaps the image to match.
The panels are ordinary stacked content, so on a narrow screen you drop the sticky rule in a media query and it degrades to a normal article.
No JavaScript branch for mobile, no separate template. The same markup, one rule lighter.
horizontal
Vertical scroll distance is mapped to horizontal travel by giving the wrapper height.
It never hijacks the wheel, so the trackpad, the keyboard and the scrollbar all keep working.
Which is exactly what the transform-and-wheel-listener version breaks, every time.
And under reduced motion it becomes a plain horizontally scrollable strip.
04Two states, one handle
Almost every before/after slider on the web is pointer-only, which
leaves it unusable on a keyboard and invisible to a screen reader. This
is a real role="slider": arrows, Home, End and an announced
value. Dragging is the enhancement, not the only door.
Drag it, or focus the handle and use ← →
05Hand it to your assistant
Ask any assistant for a scroll reveal and it writes the same snippet it has written ten thousand times. It is not careless — it has no idea what is already in your project, so it writes the most average thing that could possibly work.
Without MCP
window.addEventListener("scroll", () => {
document.querySelectorAll(".fade").forEach((el) => {
if (el.getBoundingClientRect().top < innerHeight)
el.classList.add("show");
});
});
A layout read per element per event. And a .fade { opacity: 0 } waiting for the day the script does not load.
With MCP
<div data-rm-reveal="up" data-rm-delay="120">…</div>
It looks before it writes, finds the component you already have, and tells you why it chose it — because the reasoning travels with the component.
No key, no account, no network. The server only reads files from the installed package.
06Take it with you
Every component depends only on core/motion.js. Take the two and go — that is how most people will use this, and it is designed for exactly that.
npm i @soyrageagency/rage-motion
import { init } from "@soyrageagency/rage-motion";
import "@soyrageagency/rage-motion/css";
init();
<link rel="stylesheet" href="…/rage-motion.css">
<script type="module">
import { init } from "…/index.js";
init();
</script>
The sheet follows your pointer while you hold the grip, and on release it decides from the distance and the speed of the throw. A short fast flick dismisses; a slow drag that stopped halfway springs back.