Skip to main content

Multi-state styling

Every match gets a base style. Specific occurrences get additional layered styles on top.

[10:14:02] error: connection refused on port 5432 — retrying in 2s. [10:14:04] error: connection refused on port 5432 — retrying in 4s. [10:14:08] error: connection refused on port 5432 — retrying in 8s. [10:14:16] error: handshake failed after 3 retries. [10:14:16] warning: pool exhausted, no error logged this cycle. [10:14:30] error: timeout exceeded, giving up.
Open in StackBlitz

How it works

Pass a states array. Each entry has a name, exactly one selector field (index, range, or indices), and a className and/or style:

import { Highlight } from 'one-more-highlight';

<Highlight
text={text}
searchWords={['time']}
highlightClassName="hl-base"
states={[
{ name: 'preview', range: [0, 1], className: 'hl-preview' },
{ name: 'active', index: 2, className: 'hl-active' },
{ name: 'bookmarked', indices: [3, 5], className: 'hl-bookmark' },
]}
/>

Every match gets hl-base. Match #2 also gets hl-active. Matches #0 and #1 also get hl-preview. Matches #3 and #5 also get hl-bookmark.

Selectors

HighlightState is a discriminated union — each entry carries exactly one selector field:

Selector fieldSelects
index: iA single match by zero-based index
range: [a, b]Matches from index a to b (inclusive)
indices: [i, j, k]A specific list of match indices

Indexing is global document order — match #0 is the first occurrence in the text regardless of which searchWords entry produced it.

Multi-state composition

A match can belong to multiple states simultaneously. Their classNames are concatenated (via clsx) and their style objects are shallow-merged in declaration order:

states={[
{ name: 'a', index: 0, className: 'text-bold', style: { color: 'red' } },
{ name: 'b', index: 0, style: { background: 'yellow' } },
]}
// Match 0 gets: className="hl-base text-bold", style={{ color: 'red', background: 'yellow' }}