a1ui
6 new components shipped

Text Banner

Bold text and staggered pixel separators in a seamless, infinitely scrolling banner.

Read agent guide

Demo

a1ui · Components

Installation

pnpm dlx shadcn@latest add https://ui.arjayby1.xyz/r/text-banner.json

Code

"use client";

import { useState } from "react";
import { TextBanner } from "@/components/ui/text-banner";

export function BannerExample() {
  const [paused, setPaused] = useState(false);

  return (
    <div className="flex flex-col gap-4">
      <TextBanner items={["a1ui", "Components"]} speed={80} direction="right" paused={paused} />
      <button type="button" onClick={() => setPaused((current) => !current)} aria-pressed={paused}>
        {paused ? "Resume banner" : "Pause banner"}
      </button>
    </div>
  );
}

API reference

PropTypeDefaultPurpose
itemsreadonly string[]RequiredWords or phrases to repeat. Blank entries are ignored.
speednumber80Movement in pixels per second. Zero or negative values pause. Non-finite values use the default.
direction"left" | "right""right"Direction of travel. The default moves left to right.
pausedbooleanfalsePauses at the current position. Clearing it resumes the loop.
pauseOnHoverbooleanfalsePauses while a pointer is over the banner.
separatorstringPixel motifReplaces the six-pixel motif with text. An empty string removes it.
classNamestringNoneAdds classes to the outer element.
styleCSSPropertiesNoneChanges background, color, font size, font family, or padding.

Standard div attributes pass through to the outer element. The banner inherits the page font and uses --muted, --foreground, and --border for its colors and thin borders. These tokens follow the project's light and dark themes. Set --text-banner-background and --text-banner-foreground on a parent to customize multiple banners, or use style for a single instance.

The banner measures one sequence and repeats it enough to cover the container. Two matching groups loop at a constant speed, including when there is only one short word. ResizeObserver updates the layout when the container, text, or font size changes. Empty lists render nothing. The animation styles ship inside the component.

Screen readers receive the text once. Repeated copies and separators are hidden from the accessibility tree. Reduced motion stops the animation and shows one wrapping sequence so every phrase remains readable. For a continuously moving banner, provide a pause button using paused, as in the example. Hover pausing is an optional addition to that control.