Highlight
Marks the parts of a text that match a search query. Use it to show what matched in a list of search results or a filtered list.
import { Highlight } from 'neba';
<Highlight query="acrylic">A sheet of cut acrylic.</Highlight>
<Highlight query={['data', 'database']} variant="text" color="primary">…</Highlight>
<Highlight query={/\d+/} caseSensitive>…</Highlight>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
| query * | string | string[] | RegExp | — | What to find. An array tries the longest term first, so `database` wins over `data`. A RegExp is used as written with the global flag forced on, and then caseSensitive and wholeWord are ignored |
| variantshared | 'solid' | 'outline' | 'text' | 'solid' | Weight of the mark: `solid` is the highlighter pen, `outline` a hairline box around the word, `text` the colour alone |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'warning' | Semantic colour role. `warning` by default and not arbitrarily: it is the one family whose fill is light with dark ink, so a solid mark is a yellow highlighter over black text |
| caseSensitive | boolean | false | Whether `a` and `A` are different letters |
| wholeWord | boolean | false | Whether a term has to be a word on its own: `cat` marking "cat" but not "concatenate". A word is a run of letters, digits and underscores in any script, which means very little for text that is not delimited by spaces |
| underline | boolean | false | Underlines the mark as well. Combines with every variant |
| weight | 'regular' | 'medium' | 'semibold' | 'bold' | — | Weight of the mark. Omit it and it is the weight of the text around it: the surface already says "this one", and a bolded word changes the rhythm of the whole line |
| children | ReactNode | — | The text to search. Elements are walked into, so a match inside a `<strong>` is marked and the `<strong>` survives |
Pass whatever the search box holds straight into query: a string, an array of strings, or a regular expression. There is no need to pre-compute match offsets. The component holds no state, so the marks update when children or query changes.
There is no size: a mark sits inside running text and takes the surrounding type size.
Examples
variant · underline · weight
variant is the weight of the mark. solid fills it like a highlighter pen, outline draws a hairline around the word, text changes the colour alone. underline and weight are separate axes that combine with all three.
color defaults to warning, the one family whose fill is light with dark ink on it, so solid reads as a yellow highlighter. Any other family becomes white text on a block of colour.
caseSensitive and wholeWord
caseSensitive respects case; wholeWord matches only at word boundaries. A word here is a run of letters, digits and underscores, so it does very little for Korean or Japanese, where phrases are not delimited by spaces: which is why it is off by default.
An array of strings is tried longest first: matching ['data', 'database'] shortest-first would mark data and leave base outside the mark.
Text inside nested elements
children does not have to be a string. The React tree is walked into: text nodes are marked and every other element is left exactly as it was.
Accessibility
- Marks render as real
<mark>elements, which carry the meaning "text of relevance to the reader". Marking too many words in one paragraph dilutes that meaning. - A
<mark>arrives from the browser's own stylesheet with a yellow background, which is whyvariant="text"setsbackgroundtotransparentexplicitly.