proNew240 lines · framer-motion
CTA Sticky Bar
A pinned prompt that never leaves the page it lives on. A CTA bar that stays pinned to the top or bottom of its own small scrollable mock page via CSS `position: sticky`, demonstrated inside a self-contained scroll area so the pin never touches the browser window.
- Use it for
- A persistent prompt inside a scrollable panel, feed or modal body — anywhere a CTA needs to stay reachable without hijacking page scroll.
- Themes
- Light + dark
- License
- Commercial use
Live
Stays in view
A call to action that scrolls with the page, not past it
This bar lives inside its own scroll area below and stays pinned to it as the page moves underneath — never the browser window.
tsx
"use client";
import * as React from "react";
import { motion, useReducedMotion } from "framer-motion";
import { cn } from "@/lib/utils";
function useReducedMotionSafe() {
const prefersReduced = useReducedMotion();
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
return mounted ? !!prefersReduced : false;
}
/**
* A CTA bar that pins itself to the bottom (or top) of its own scroll area —
* never the browser window. The block builds a small scrollable mock "page"
* (a fixed-height `overflow-y-auto` container with a few mock content
* blocks) and puts the bar inside it as a `sticky` child, so CSS keeps it
* pinned to that container's own scroll, not `window`. No `position: fixed`,
* no portal.
*/
The rest is in Pro.
Full source, the rebuild prompt and registry install unlock with Pro or Lifetime.
Get ProHow it behaves
- →The demo scroll area is a fixed-height (520px) overflow-y-auto container; the bar is a sticky top-0 or sticky bottom-0 child of that same container, so it pins to its own scrolling ancestor only — window scroll and position: fixed are never used.
- →position swaps which edge the bar sticks to and flips its border/shadow side to match.
- →tone swaps the bar between a neutral bg-foreground treatment and a bg-signal treatment, both theme-token driven.
- →A soft pulse glow behind the CTA button is gated by an IntersectionObserver + document.hidden check, so it only animates while the block is onscreen and the tab is visible, and is skipped under prefers-reduced-motion.
- →dismissible adds a close control that hides the bar via local state (no native confirm/alert) and calls onDismiss.
- →Mock content is six generic, scrollable content cards with no invented metrics, used purely to demonstrate the pin while scrolling.
Accessibility
- ✓The bar's CTA is a real `<button>` with visible text, not an icon-only control; the dismiss control has an `aria-label`.
- ✓The decorative pulse glow is `aria-hidden` and purely visual, never affecting layout or focus order.
- ✓Scroll container keeps native keyboard/wheel scrolling (`overflow-y-auto` on a focusable, taggable element) rather than a custom scroll hijack.
- ✓Honours prefers-reduced-motion.