import { Box, Marquee } from '@fidely-ui/react'
export const MarqueeBasics = () => {
return (
<Marquee.Root pauseOnInteraction>
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
)
}
const items = [
'Accessible by default',
'Composable components',
'Built on Ark UI',
'Powered by Panda CSS',
'Design-system ready',
'TypeScript-first',
'Production tested',
]
Usage
import { Marquee } from '@fidely-ui/react'<Marquee.Root>
<Marquee.Viewport>
<Marquee.Content>
<Marquee.Item />
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>Features
- Smooth, GPU-accelerated scrolling with seamless looping
- Supports horizontal and vertical directions
- Optional reverse scrolling and RTL layouts
- Auto-fill mode to duplicate items for continuous flow
- Configurable speed, gap, and spacing
- Pause on interaction (hover or focus)
Autofill
Use the autoFill prop to automatically duplicate content to fill the viewport. The spacing prop controls the gap between duplicated content instances:
import { Box, Marquee } from '@fidely-ui/react'
export const MarqueeAutofill = () => {
return (
<Marquee.Root autoFill spacing="2">
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
)
}
const items = ['Mango', 'Pineapple', 'Strawberry']
Reverse
Pass the reverse prop to the Root component to reverse the scroll
direction of the marquee content.
import { Box, Marquee } from '@fidely-ui/react'
export const MarqueeReverse = () => {
return (
<Marquee.Root reverse>
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
)
}
const items = [
'Reverse direction',
'Right-to-left motion',
'Top-to-bottom motion',
'Continuous scrolling',
'Smooth animation',
]
Vertical Orientation
Set side="bottom" (or side="top") to create a vertical marquee:
import { Card, Flex, Marquee, Persona, VStack } from '@fidely-ui/react'
export const MarqueeVertical = () => {
return (
<VStack>
<Flex gap="2">
{/* Bottom scrolling marquee */}
<Marquee.Root side="bottom" height="320px">
<Marquee.Viewport>
<Marquee.Content
role="region"
aria-roledescription="marquee"
aria-label="Team members"
>
{items.map(({ name, role }) => (
<Marquee.Item key={name}>
<Card.Root
bg="bg.emphasized"
_hover={{ bg: 'bg.emphasized/70' }}
width="250px"
>
<Card.Body gap="2">
<Card.Header>
<Flex justify="space-between" align="flex-start">
<Persona name={name} title={role} size="lg" />
</Flex>
</Card.Header>
<Card.Description>{`${role} at ${name}`}</Card.Description>
</Card.Body>
</Card.Root>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
{/* Top scrolling marquee */}
<Marquee.Root side="top" height="320px">
<Marquee.Viewport>
<Marquee.Content
role="region"
aria-roledescription="marquee"
aria-label="Team members"
>
{items.map(({ name, role }) => (
<Marquee.Item key={name}>
<Card.Root
bg="bg.emphasized"
_hover={{ bg: 'bg.emphasized/70' }}
width="250px"
>
<Card.Body gap="2">
<Card.Header>
<Flex justify="space-between" align="flex-start">
<Persona name={name} title={role} size="lg" />
</Flex>
</Card.Header>
<Card.Description>{`${role} at ${name}`}</Card.Description>
</Card.Body>
</Card.Root>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
</Flex>
</VStack>
)
}
const items = [
{ name: 'Alice', role: 'Designer' },
{ name: 'Bob', role: 'Developer' },
{ name: 'Clara', role: 'Product Lead' },
{ name: 'David', role: 'Engineer' },
{ name: 'Ella', role: 'Manager' },
]
Edge Gradients
Add Marquee.Edge components to create fade effects at the start and end of the scrolling area:
import { Box, Marquee } from '@fidely-ui/react'
export const MarqueeEdge = () => {
return (
<>
<Marquee.Root side="start">
<Marquee.Edge side="start" />
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
<Marquee.Edge side="end" />
</Marquee.Root>
<Marquee.Root side="end">
<Marquee.Edge side="start" />
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
<Marquee.Edge side="end" />
</Marquee.Root>
</>
)
}
const items = [
'Reverse direction',
'Right-to-left motion',
'Top-to-bottom motion',
'Continuous scrolling',
'Smooth animation',
]
Pause on Interaction
Enable pauseOnInteraction to pause the marquee when users hover or focus on it, improving accessibility:
import { Box, Marquee } from '@fidely-ui/react'
export const MarqueePause = () => {
return (
<Marquee.Root pauseOnInteraction>
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
)
}
const items = [
'Accessible by default',
'Composable components',
'Built on Ark UI',
'Powered by Panda CSS',
'Design-system ready',
'TypeScript-first',
'Production tested',
]
Custom Speed
Control the scrolling speed of the marquee by passing the speed prop.
The value is measured in pixels per second, allowing precise control
over how fast the content moves.
import { Box, Marquee } from '@fidely-ui/react'
export const MarqueeSpeed = () => {
return (
<Marquee.Root speed={150}>
<Marquee.Viewport>
<Marquee.Content>
{items.map((item, i) => (
<Marquee.Item key={i}>
<Box
css={{
px: '6',
py: '4',
borderRadius: 'xl',
border: '1px solid',
borderColor: 'border.default',
boxShadow: 'md',
whiteSpace: 'nowrap',
}}
>
{item}
</Box>
</Marquee.Item>
))}
</Marquee.Content>
</Marquee.Viewport>
</Marquee.Root>
)
}
const items = [
'Apple',
'Banana',
'Cherry',
'Date',
'Elderberry',
'Fig',
'Grape',
]
Props
Root
| Prop | Type | Default | Description |
|---|---|---|---|
autoFill | boolean | false | Whether to automatically duplicate content to fill the container. |
defaultPaused | boolean | false | Whether the marquee is paused by default. |
delay | number | 0 | The delay before the animation starts (in seconds). |
ids | Partial<{}> | - | The ids of the elements in the marquee. Useful for composition |
loopCount | number | 0 | The number of times to loop the animation (0 = infinite).. |
onComplete | () => void | - | Function called when the marquee completes all loops and stops. Only fires for finite loops (loopCount > 0).. |
onLoopComplete | () => void | - | Function called when the marquee completes one loop iteration.. |
onPauseChange | (details: PauseStatusDetails) => void | - | Function called when the pause status changes. |
paused | boolean | - | Whether the marquee is paused |
pauseOnInteraction | boolean | false | Whether to pause the marquee on user interaction (hover, focus). |
as | React.ElementType | - | The underlying element to render. |
asChild | boolean | - | Use the provided child element as the default rendered element, combining their props and behavior. |
reverse | boolean | false | Whether to reverse the animation direction. |
side | Side | start | The side/direction the marquee scrolls towards. |
spacing | string | 1rem | The spacing between marquee items. |
speed | number | 50 | The speed of the marquee animation in pixels per second. |
translations | IntlTranslations | - | The localized messages to use. |
Edge
| Prop | Type | Default | Description |
|---|---|---|---|
side | Side | — | The side where the edge gradient should appear. |
RootProvider
| Prop | Type | Default | Description |
|---|---|---|---|
value | UseMarqueeReturn | — | - |
asChild | boolean | - | Use the provided child element as the default rendered element, combining their props and behavior. |