Skip to content

Text Highlighter

A marker highlight that sweeps behind text when it scrolls into view. The text itself is untouched, ordinary inline text that wraps normally.

Motionv0.1.0experimentalWCAG 2.2 AAView spec

Optional, and kept apart.

Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.

Marked in one sweep
import { TextHighlighter } from "@rdloom/react";

export default function TextHighlighterBasicExample() {
  return (
    <div className="flex w-full justify-center text-2xl font-semibold">
      <TextHighlighter>Marked in one sweep</TextHighlighter>
    </div>
  );
}

Installation

npx rdloom add text-highlighter

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.

It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/text-highlighter.json

Works, but without upgrade tracking, and you import the motion CSS yourself.

Usage

import { TextHighlighter } from "@rdloom/react";

<div className="flex w-full justify-center text-2xl font-semibold">
  <TextHighlighter>Marked in one sweep</TextHighlighter>
</div>

In a paragraph

Every component ships with its own tests, and keyboard and screen reader behaviour is checked before release, not after.

import { TextHighlighter } from "@rdloom/react";

// The highlight is a background on inline text, so it wraps with the line.
export default function TextHighlighterInAParagraphExample() {
  return (
    <div className="flex w-full justify-center">
      <p className="max-w-md text-center text-base leading-relaxed">
        Every component ships with its own tests, and{" "}
        <TextHighlighter delay={0.2}>keyboard and screen reader behaviour is checked before release</TextHighlighter>, not after.
      </p>
    </div>
  );
}

Custom color

A yellow markerA green one, sweeping on load
import { TextHighlighter } from "@rdloom/react";

// A light marker keeps the text readable. Check contrast if you pick your own colour.
export default function TextHighlighterCustomColorExample() {
  return (
    <div className="flex w-full flex-col items-center gap-3 text-xl font-semibold">
      <TextHighlighter color="rgb(253 224 71 / 0.55)">A yellow marker</TextHighlighter>
      <TextHighlighter color="rgb(134 239 172 / 0.5)" whenInView={false} duration={1.2}>
        A green one, sweeping on load
      </TextHighlighter>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
childrenrequired

The text to highlight.

stringnone
color

Any CSS colour for the marker. Defaults to a soft tint of the action colour. Keep enough contrast with the text.

stringnone
whenInView

Waits until the text scrolls into view before sweeping. When false it sweeps on load.

booleantrue
duration

Seconds the sweep takes.

number0.8
delay

Seconds to wait before the sweep starts.

number0
isPaused

Stops the animation and shows the finished text. Moving content that lasts more than five seconds should be stoppable.

booleanfalse

Accessibility

Role generic, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

Not interactive.

Screen readers announce

  • The text, as ordinary text

What your code must do

  • The marker is a background of the text element, so the text is never split, copied or re-announced
  • The marker colour must keep the text at 4.5:1 contrast; the default is a light tint
  • The marker runs once and then stays: nothing keeps moving
  • Decoration only: the animated layers are hidden from assistive technology and never take focus
  • Stands still for visitors who ask for less motion (prefers-reduced-motion), and can also be shown still with the rdm-still class or isPaused
  • In forced-colors (high contrast) mode the text is drawn in the system colours with no effect
  • Does not flash: nothing changes more than three times in a second (WCAG 2.3.1)
  • The text is real text in the server HTML, readable with no script
  • Optional: it is a separate component, so projects that do not add it carry none of its code

Guidelines

Use it when

  • Drawing the eye to one key phrase in a paragraph
  • Marking a phrase as the point of a section

Avoid it when

  • Highlighting whole paragraphs
  • Dark or saturated marker colours that cut the text contrast

Don't

  • Stacking several highlights in one sentence
  • Using the highlight as the only sign that text matters (add words or structure too)

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-text-default
  • --rd-color-action-primary