KQ-1381 · SPEED/BANNER
Speed Banner
A marquee that answers the scroll: rows of repeated display type cruise in alternating directions, and the page's scroll velocity feeds one amount carried on springs.glide that runs the rows faster, leans each toward its own direction of travel and opens the letter spacing, the stretch anchored mid-row so the type elongates rather than slides. Scrolling up reverses every row through springs.drift, so the rows slow, stop and pull away the other way, and when scrolling stops everything eases back to the cruise. The banner is a focusable region: Space or Enter holds and releases it, Left and Right push it the way a scroll would, and Up, Down and the page keys scroll the page as usual.
Basinworks · Spring drop
cruising · scroll to push it
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/speed-banner
Props
- text
- string | string[]
- default —
- The items repeated along each row; a string is one item.
- as
- "div" | "section" | "aside" | "header" | "footer"
- default "div"
- The root element.
- rows
- number
- default 2
- How many rows, 1 to 4; rows alternate direction and start on different items.
- speed
- number
- default 1.2
- The rows' calm drift, em per second, so it scales with the type.
- skew
- number
- default 10
- The largest lean at full scroll speed, degrees.
- stretch
- number
- default 0.06
- The most letter spacing opens at full scroll speed, em.
- boost
- number
- default 5
- How many times their base speed the rows reach at full scroll speed.
- sensitivity
- number
- default 2400
- The scroll speed that counts as full, px per second.
- direction
- "left" | "right"
- default "left"
- The first row's direction; the next runs the other way.
- flip
- boolean
- default true
- Scrolling up reverses every row.
- outline
- "none" | "alternate" | "all"
- default "alternate"
- Which rows are drawn in outline.
- separator
- string
- default "·"
- Set between items.
- fade
- boolean
- default true
- Fade the ends of the rows.
- gap
- number
- default 0.1
- Space between rows, em.
- label
- string
- default "Banner"
- The region's name for assistive technology.
- paused / defaultPaused
- boolean
- default false
- Hold the banner; the rows coast to a stop on the drift spring.
- onPausedChange
- (paused: boolean) => void
- default —
- Fires from the key press that held or released the banner.
- onDirectionChange
- (direction: 1 | -1) => void
- default —
- Scrolling flipped the rows: 1 their own way, -1 reversed.
- className
- string
- default —
- Classes for the root; type size, weight, case and tracking carry into the rows.
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | string[] | — | The items repeated along each row; a string is one item. |
| as | "div" | "section" | "aside" | "header" | "footer" | "div" | The root element. |
| rows | number | 2 | How many rows, 1 to 4; rows alternate direction and start on different items. |
| speed | number | 1.2 | The rows' calm drift, em per second, so it scales with the type. |
| skew | number | 10 | The largest lean at full scroll speed, degrees. |
| stretch | number | 0.06 | The most letter spacing opens at full scroll speed, em. |
| boost | number | 5 | How many times their base speed the rows reach at full scroll speed. |
| sensitivity | number | 2400 | The scroll speed that counts as full, px per second. |
| direction | "left" | "right" | "left" | The first row's direction; the next runs the other way. |
| flip | boolean | true | Scrolling up reverses every row. |
| outline | "none" | "alternate" | "all" | "alternate" | Which rows are drawn in outline. |
| separator | string | "·" | Set between items. |
| fade | boolean | true | Fade the ends of the rows. |
| gap | number | 0.1 | Space between rows, em. |
| label | string | "Banner" | The region's name for assistive technology. |
| paused / defaultPaused | boolean | false | Hold the banner; the rows coast to a stop on the drift spring. |
| onPausedChange | (paused: boolean) => void | — | Fires from the key press that held or released the banner. |
| onDirectionChange | (direction: 1 | -1) => void | — | Scrolling flipped the rows: 1 their own way, -1 reversed. |
| className | string | — | Classes for the root; type size, weight, case and tracking carry into the rows. |