# AnimatedTextReveal

*Category:* Components
*Section:* Content
*Source:* https://uikit.developers.rio.cloud/#/components/animatedTextReveal
*Captured:* 2026-04-27T14:57:53.077Z

AnimatedTextReveal displays text that smoothly reveals from below while a subtle shimmer effect runs across it. It’s designed for attention-grabbing messages or live-updating content, combining a primary reveal motion with an optional continuous shimmer highlight.

## AnimatedTextReveal

Use this component when you want to emphasize text through motion, such as when showing incremental updates or loading states. The reveal motion ensures readability and hierarchy, while the shimmer accent adds a refined sense of activity or focus.

Avoid using it for large paragraphs or static labels — reserve it for short, meaningful text where animation enhances clarity rather than distracts.

### Example: Text with automatic cycling and animated gradient

Text with automatic cycling and animated gradient
Live stream

System is thinking...

Text with animated gradient
Processing your request...

Text with automatic cycling but without animated gradient
System is thinking...

Text with custom styling
System is thinking...

Revealing text on a button
Continue

#### React (tsx)

```tsx
import Card from '@rio-cloud/rio-uikit/Card';
import AnimatedTextReveal from '@rio-cloud/rio-uikit/AnimatedTextReveal';
import FormLabel from '@rio-cloud/rio-uikit/FormLabel';
import Divider from '@rio-cloud/rio-uikit/Divider';
import Button from '@rio-cloud/rio-uikit/Button';

const phrases = [
    'System is thinking...',
    'Processing your request...',
    'Analyzing the data...',
    'Generating response...',
    'Almost there...',
];

export default () => (
    <div className='space-y-25'>
        <div>
            <FormLabel>Text with automatic cycling and animated gradient</FormLabel>
            <Card className='display-flex flex-column gap-15'>
                <div>
                    <div className='text-uppercase text-size-12'>Live stream</div>
                </div>
                <AnimatedTextReveal text={phrases} />
            </Card>
        </div>
        <Divider />
        <div>
            <FormLabel>Text with animated gradient</FormLabel>
            <Card className='display-flex flex-column gap-15'>
                <AnimatedTextReveal text='Processing your request...' shimmerDuration={2} shimmerSpread={10} />
            </Card>
        </div>

        <div>
            <FormLabel>Text with automatic cycling but without animated gradient</FormLabel>
            <Card className='display-flex flex-column gap-15'>
                <AnimatedTextReveal text={phrases} shimmer={false} />
            </Card>
        </div>

        <div>
            <FormLabel>Text with custom styling</FormLabel>
            <Card className='display-flex flex-column gap-15'>
                <AnimatedTextReveal
                    text={phrases}
                    textColor='dark'
                    shimmerColor='lightest'
                    className='text-size-16'
                    interval={4}
                />
            </Card>
        </div>
        <div>
            <FormLabel>Revealing text on a button</FormLabel>
            <div className='max-width-150'>
                <Button bsStyle='primary' block>
                    <AnimatedTextReveal
                        text={['Continue', 'Checking details...', 'Ready!']}
                        textColor='white'
                        shimmer={false}
                        interval={3}
                    />
                </Button>
            </div>
        </div>
    </div>
);
```

#### HTML (html)

```html
<div class="space-y-25">
    <div>
        <div class="text-color-dark max-width-100pct text-size-12 display-inline-block margin-bottom-5">Text with automatic cycling and animated gradient</div>
        <div class="bg-white rounded border shadow-default padding-15 display-flex flex-column gap-15">
            <div>
                <div class="text-uppercase text-size-12">Live stream</div>
            </div>
            <div class="position-relative" aria-live="polite" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 168px; --atr-text-color: var(--gray-darkest); --atr-shimmer-color: var(--gray-lighter);">
                <div class="animated-text-reveal position-relative" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 168px; --atr-text-color: var(--gray-darkest); --atr-shimmer-color: var(--gray-lighter); opacity: 0.316063; transform: translateY(8.93777px);">System is thinking...</div>
            </div>
        </div>
    </div>
    <div class="Divider position-relative width-100pct" style="padding-top: 15px; padding-bottom: 15px;">
        <div class="divider-line bg-light" style="width: 100%; height: 1px;">
        </div>
    </div>
    <div>
        <div class="text-color-dark max-width-100pct text-size-12 display-inline-block margin-bottom-5">Text with animated gradient</div>
        <div class="bg-white rounded border shadow-default padding-15 display-flex flex-column gap-15">
            <div class="position-relative" aria-live="polite" style="--atr-duration: 2s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 260px; --atr-text-color: var(--gray-darkest); --atr-shimmer-color: var(--gray-lighter);">
                <div class="animated-text-reveal position-relative" style="--atr-duration: 2s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 260px; --atr-text-color: var(--gray-darkest); --atr-shimmer-color: var(--gray-lighter); opacity: 0.316063; transform: translateY(8.93777px);">Processing your request...</div>
            </div>
        </div>
    </div>
    <div>
        <div class="text-color-dark max-width-100pct text-size-12 display-inline-block margin-bottom-5">Text with automatic cycling but without animated gradient</div>
        <div class="bg-white rounded border shadow-default padding-15 display-flex flex-column gap-15">
            <div class="position-relative" aria-live="polite" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 168px; --atr-text-color: var(--gray-darkest); --atr-shimmer-color: var(--gray-lighter);">
                <div class="animated-text-reveal position-relative" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 168px; --atr-text-color: var(--gray-darkest); --atr-shimmer-color: var(--gray-lighter); opacity: 0; transform: translateY(3.36812px);">System is thinking...</div>
            </div>
        </div>
    </div>
    <div>
        <div class="text-color-dark max-width-100pct text-size-12 display-inline-block margin-bottom-5">Text with custom styling</div>
        <div class="bg-white rounded border shadow-default padding-15 display-flex flex-column gap-15">
            <div class="position-relative text-size-16" aria-live="polite" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 168px; --atr-text-color: var(--gray-dark); --atr-shimmer-color: var(--gray-lightest);">
                <div class="animated-text-reveal position-relative is-animated" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 168px; --atr-text-color: var(--gray-dark); --atr-shimmer-color: var(--gray-lightest); opacity: 0; transform: translateY(3.36812px);">System is thinking...</div>
            </div>
        </div>
    </div>
    <div>
        <div class="text-color-dark max-width-100pct text-size-12 display-inline-block margin-bottom-5">Revealing text on a button</div>
        <div class="max-width-150">
            <button type="button" class="btn btn-primary btn-block btn-component" tabindex="0">
                <div class="position-relative" aria-live="polite" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 64px; --atr-text-color: var(--color-white); --atr-shimmer-color: var(--gray-lighter);">
                    <div class="animated-text-reveal position-relative" style="--atr-duration: 5s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 64px; --atr-text-color: var(--color-white); --atr-shimmer-color: var(--gray-lighter); opacity: 0; transform: translateY(3.36812px);">Continue</div>
                </div>
            </button>
        </div>
    </div>
</div>
```

#### Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| text | string \| string[] | — | Text content to display. Accepts a string or an array of phrases that are revealed and cycled through automatically. |
| duration | number | 0.4 | Reveal animation duration in seconds. |
| delay | number | 0 | Reveal animation delay before starting, in seconds. |
| interval | number | 3 | Interval time between phrase transitions when multiple texts are provided, in seconds. |
| distance | number | 10 | Vertical offset in pixels from which the text reveals upward. |
| ease | 'linear' \| 'easeIn' \| 'easeOut' \| 'easeInOut' | 'easeOut' | Easing function applied to the reveal motion. |
| startOnView | boolean | true | Whether the animation should only start once the component enters the viewport when scrolling. |
| once | boolean | false | If true, the reveal animation runs only once per mount when the component enters the viewport. |
| inViewMargin | UseInViewOptions['margin'] | — | Optional root margin passed to the intersection observer for in-view detection (e.g., "0px 0px -10% 0px"). |
| shimmer | boolean | true | Enables or disables the shimmer highlight effect across the text. |
| shimmerDuration | number | 5 | Duration of one shimmer loop in seconds. |
| shimmerDelay | number | 0 | Delay before the shimmer effect starts, in seconds. |
| shimmerSpread | number | 8 | Multiplier controlling the width of the shimmer highlight band. |
| shimmerRepeat | boolean | true | If true, the shimmer animation loops infinitely. |
| shimmerColor | 'black' \| 'darkest' \| 'darker' \| 'dark' \| 'gray' \| 'light' \| 'lighter' \| 'lightest' \| 'white' | 'lighter' | The color of the shimmer highlight band. |
| textColor | 'black' \| 'darkest' \| 'darker' \| 'dark' \| 'gray' \| 'light' \| 'lighter' \| 'lightest' \| 'white' \| 'primary' \| 'secondary' \| 'info' \| 'warning' \| 'danger' \| 'success' | 'darkest' | Base color of the text. |
| innerClassName | string | — | Additional classNames set on the inner element. |
| className | string | — | Additional classNames set on the wrapper element. |

### Example: Status

Status
Idle

Sync now

No sync yet

#### React (tsx)

```tsx
import { useState, useMemo } from 'react';

import Card from '@rio-cloud/rio-uikit/Card';
import AnimatedTextReveal from '@rio-cloud/rio-uikit/AnimatedTextReveal';
import FormLabel from '@rio-cloud/rio-uikit/FormLabel';
import Divider from '@rio-cloud/rio-uikit/Divider';
import Button from '@rio-cloud/rio-uikit/Button';

type StatusKey = 'idle' | 'connecting' | 'syncing' | 'done';

const STATUS_SEQUENCE: StatusKey[] = ['connecting', 'syncing', 'done'];

const STATUS_COPY: Record<StatusKey, string> = {
    idle: 'Idle',
    connecting: 'Connecting…',
    syncing: 'Syncing…',
    done: 'Up to date',
};

export default () => {
    const [status, setStatus] = useState<StatusKey>('idle');
    const [lastSyncedTs, setLastSyncedTs] = useState<number | null>(null);

    const statusPhrase = useMemo(() => STATUS_COPY[status], [status]);

    const isIdle = status === 'idle';

    const handleSync = () => {
        if (!isIdle) {
            return;
        }

        // walk through connecting -> syncing -> done
        let index = 0;
        setStatus(STATUS_SEQUENCE[index]);

        const step = () => {
            index += 1;
            if (index < STATUS_SEQUENCE.length) {
                setStatus(STATUS_SEQUENCE[index]);
                setTimeout(step, 3_200);
            } else {
                setLastSyncedTs(Date.now());
                // keep "done" for a while, then go back to idle for demo purposes
                setTimeout(() => setStatus('idle'), 1_000);
            }
        };

        setTimeout(step, 1200);
    };

    const isShimmering = false; //status === 'connecting' || status === 'syncing';

    return (
        <div className='display-flex justify-content-center padding-25'>
            <Card className='width-400 padding-20'>
                <div className='display-flex flex-column gap-15'>
                    <div className='display-flex justify-content-between align-items-end'>
                        <div className='display-flex flex-column'>
                            <FormLabel className='margin-bottom-5 text-size-12'>Status</FormLabel>
                            <div className={`label overflow-hidden ${isIdle ? 'label-muted' : 'label-info'}`}>
                                <AnimatedTextReveal
                                    text={statusPhrase}
                                    duration={0.35}
                                    distance={8}
                                    ease='easeOut'
                                    startOnView={false}
                                    shimmer={isShimmering} // shimmer (only while connecting/syncing)
                                    shimmerDuration={3}
                                    shimmerSpread={10}
                                    shimmerColor='white'
                                    textColor={isIdle ? 'dark' : 'info'}
                                />
                            </div>
                        </div>

                        <Button
                            onClick={handleSync}
                            disabled={!isIdle}
                            className='min-width-100'
                            bsStyle={isIdle ? 'primary' : 'default'}
                        >
                            Sync now
                        </Button>
                    </div>

                    <Divider />

                    <div className='text-size-12 text-color-darker margin-top--10'>
                        {lastSyncedTs ? (
                            <span>Last synced: {new Date(lastSyncedTs).toLocaleTimeString()}</span>
                        ) : (
                            <span>No sync yet</span>
                        )}
                    </div>
                </div>
            </Card>
        </div>
    );
};
```

#### HTML (html)

```html
<div class="display-flex justify-content-center padding-25">
    <div class="bg-white rounded border shadow-default padding-15 width-400 padding-20">
        <div class="display-flex flex-column gap-15">
            <div class="display-flex justify-content-between align-items-end">
                <div class="display-flex flex-column">
                    <div class="text-color-dark max-width-100pct text-size-12 display-inline-block margin-bottom-5 text-size-12">Status</div>
                    <div class="label overflow-hidden label-muted">
                        <div class="position-relative" aria-live="polite" style="--atr-duration: 3s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 40px; --atr-text-color: var(--gray-dark); --atr-shimmer-color: var(--color-white);">
                            <div class="animated-text-reveal position-relative" style="--atr-duration: 3s; --atr-delay: 0s; --atr-iterations: infinite; --atr-spread: 40px; --atr-text-color: var(--gray-dark); --atr-shimmer-color: var(--color-white); opacity: 1; transform: none;">Idle</div>
                        </div>
                    </div>
                </div>
                <button type="button" class="btn btn-primary btn-component min-width-100" tabindex="0">Sync now</button>
            </div>
            <div class="Divider position-relative width-100pct" style="padding-top: 15px; padding-bottom: 15px;">
                <div class="divider-line bg-light" style="width: 100%; height: 1px;">
                </div>
            </div>
            <div class="text-size-12 text-color-darker margin-top--10">
                <span>No sync yet</span>
            </div>
        </div>
    </div>
</div>
```

#### Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| text | string \| string[] | — | Text content to display. Accepts a string or an array of phrases that are revealed and cycled through automatically. |
| duration | number | 0.4 | Reveal animation duration in seconds. |
| delay | number | 0 | Reveal animation delay before starting, in seconds. |
| interval | number | 3 | Interval time between phrase transitions when multiple texts are provided, in seconds. |
| distance | number | 10 | Vertical offset in pixels from which the text reveals upward. |
| ease | 'linear' \| 'easeIn' \| 'easeOut' \| 'easeInOut' | 'easeOut' | Easing function applied to the reveal motion. |
| startOnView | boolean | true | Whether the animation should only start once the component enters the viewport when scrolling. |
| once | boolean | false | If true, the reveal animation runs only once per mount when the component enters the viewport. |
| inViewMargin | UseInViewOptions['margin'] | — | Optional root margin passed to the intersection observer for in-view detection (e.g., "0px 0px -10% 0px"). |
| shimmer | boolean | true | Enables or disables the shimmer highlight effect across the text. |
| shimmerDuration | number | 5 | Duration of one shimmer loop in seconds. |
| shimmerDelay | number | 0 | Delay before the shimmer effect starts, in seconds. |
| shimmerSpread | number | 8 | Multiplier controlling the width of the shimmer highlight band. |
| shimmerRepeat | boolean | true | If true, the shimmer animation loops infinitely. |
| shimmerColor | 'black' \| 'darkest' \| 'darker' \| 'dark' \| 'gray' \| 'light' \| 'lighter' \| 'lightest' \| 'white' | 'lighter' | The color of the shimmer highlight band. |
| textColor | 'black' \| 'darkest' \| 'darker' \| 'dark' \| 'gray' \| 'light' \| 'lighter' \| 'lightest' \| 'white' \| 'primary' \| 'secondary' \| 'info' \| 'warning' \| 'danger' \| 'success' | 'darkest' | Base color of the text. |
| innerClassName | string | — | Additional classNames set on the inner element. |
| className | string | — | Additional classNames set on the wrapper element. |