PressableFeedback
Press interaction primitive with default scale feedback and optional highlight overlays for hover or pointer tracking.
Import
import { PressableFeedback } from '@/components/pressable-feedback'Anatomy
The module exposes one namespace object. PressableFeedback is callable as the root interactive target (same element as PressableFeedback.Root) and provides press-down scale feedback out of the box.
<PressableFeedback>
<span>Press me</span>
</PressableFeedback>Equivalently, name the root explicitly:
<PressableFeedback.Root className="rounded-2xl px-4 py-3">
Continue
</PressableFeedback.Root>Use the root render prop when the target should be another component, such as a router link.
import { Link } from '@tanstack/react-router'
<PressableFeedback render={<Link to="/settings" />}>
Settings
</PressableFeedback>- PressableFeedback / PressableFeedback.Root: Renders
motion.divby default, or composes with a custom element through Base UI'srenderprop (element or render function). It owns pointer state, highlight position CSS variables, and default press scale. Setanimation={false}to skip root scale while still providing highlight context. - PressableFeedback.Highlight: Visual overlay that fades in while the pointer is over the target (
active). It follows--pressable-feedback-xand--pressable-feedback-yon the interactive element and usesrounded-(--radius)for its shape. - PressableFeedback.Scale: Optional Motion target when a nested element should receive press scale and pointer tracking instead of the root. Use with
animation={false}on the root so only the scale part animates.
Usage
Default press feedback
The recommended default is to render the target directly through PressableFeedback. It applies Motion scale feedback to the root element on press. With the default animation value (true), the pressed scale animates to 0.975 using a spring transition (stiffness: 520, damping: 32, mass: 0.6). Pass an object to animation to override those values; pass false to turn off root scale only.
<PressableFeedback className="rounded-2xl px-4 py-3">
Continue
</PressableFeedback>Custom scale animation
Use animation.scale.value to customize the pressed scale target. animation.transition controls the Motion transition for the built-in scale animation, while animation.scale.timingConfig can override the transition for scale specifically.
<PressableFeedback
animation={{
scale: {
value: 0.9,
},
transition: {
type: 'spring',
stiffness: 700,
damping: 38,
},
}}
className="rounded-2xl px-4 py-3"
>
Press deeper
</PressableFeedback>Highlight overlay
Place PressableFeedback.Highlight inside the target when you want the glaze-style highlight. The root clips the overlay with overflow-hidden, so set --radius (and matching border radius classes) on the same element that receives pointer events.
<PressableFeedback className="rounded-2xl px-4 py-3">
<PressableFeedback.Highlight />
<span className="relative">General</span>
</PressableFeedback>Highlight without root scale
When another component already handles its own pressed styling (for example a Button or router Link), set animation={false} on the root and keep PressableFeedback.Highlight as a child. Pointer tracking and CSS variables are still applied to the rendered target.
import { Link } from '@tanstack/react-router'
<PressableFeedback
animation={false}
render={<Link to="/settings/general" />}
className="rounded-2xl p-3"
>
<PressableFeedback.Highlight />
<span className="relative">General</span>
</PressableFeedback>Render as another component
Use render to make the feedback target a link, button, or another component. Pass a React element or a Base UI render function. The rendered component must forward its ref and spread received props onto its DOM element.
Internally, element renders are wrapped with Motion via motion.create, so Motion props such as animate and transition drive the built-in scale animation.
import { Link } from '@tanstack/react-router'
<PressableFeedback render={<Link to="/settings/general" />} className="rounded-2xl p-3">
<PressableFeedback.Highlight />
General
</PressableFeedback>Highlight tracking offsets
xOffset and yOffset (defaults 48 and 6) control how far the highlight moves in pixels as the pointer moves across the target. They multiply normalized pointer position and write --pressable-feedback-x / --pressable-feedback-y on the interactive element.
<PressableFeedback xOffset={64} yOffset={8} className="rounded-2xl p-3">
<PressableFeedback.Highlight />
Track farther
</PressableFeedback>Disabled state
Pass disabled to ignore pointer handlers and keep active / pressed false. Highlight and scale feedback stay off until re-enabled.
<PressableFeedback disabled className="rounded-2xl p-3 opacity-50">
Unavailable
</PressableFeedback>Scale a specific child
When the root should only provide context but a nested element should receive both press scale and highlight positioning, disable root animation and wrap that element in PressableFeedback.Scale. PressableFeedback.Highlight must remain inside the scale target (or any descendant of the root).
<PressableFeedback animation={false}>
<PressableFeedback.Scale className="rounded-2xl p-3">
<PressableFeedback.Highlight />
<span className="relative">General</span>
</PressableFeedback.Scale>
</PressableFeedback>PressableFeedback.Scale also accepts render if the nested target needs to be a custom element.
<PressableFeedback animation={false}>
<PressableFeedback.Scale render={<button type="button" />} className="rounded-full p-3">
<PressableFeedback.Highlight />
<span className="relative">Open</span>
</PressableFeedback.Scale>
</PressableFeedback>Example
import { PressableFeedback } from '@/components/pressable-feedback'
import { Link } from '@tanstack/react-router'
export default function PressableFeedbackExample() {
return (
<PressableFeedback
render={<Link to="/settings/general" />}
className="flex items-center gap-3 rounded-2xl p-3 text-white"
>
<PressableFeedback.Highlight />
<span className="relative size-6 rounded-full bg-white/20" />
<span className="relative font-medium">General</span>
</PressableFeedback>
)
}API Reference
PressableFeedback (PressableFeedback.Root)
The callable PressableFeedback component is PressableFeedback.Root. Beyond the table below, the root accepts standard React.HTMLAttributes<HTMLElement> (className, style, aria-*, event handlers, etc.).
Prop
Type
PressableFeedback.Highlight
Renders the default highlight overlay. Must be used inside PressableFeedback. There are no component-specific props — use standard React.HTMLAttributes<HTMLSpanElement> (className, style, data attributes).
PressableFeedback.Scale
Optional Motion scale target; use with animation={false} on the root when a nested element should animate instead. Must be used inside PressableFeedback. Beyond the table below, it accepts standard React.HTMLAttributes<HTMLElement>.
Prop
Type
PressableFeedbackAnimation
Configures built-in Motion feedback for PressableFeedback and PressableFeedback.Scale.
Prop
Type
PressableFeedbackScaleAnimation
Configures the pressed scale target and optional scale-specific timing.
Prop
Type
PressableFeedbackScaleState
State passed to Base UI render functions for the root and scale part. Boolean fields also map to data-* attributes on the rendered target (data-active, data-pressed, data-disabled).
Prop
Type