Skip to content
Cynosurev0.5.0
SearchStorybookGitHubnpmColour mode: System. Switch to Light

Components / More

HighlightedText

Text with the parts that matched a search marked: the characters a fuzzy matcher returned, or every occurrence of a query. Tree, Combobox and CommandPalette mark their matches with it.

Query marks every occurrence ignoring case

When to useLink to "When to use"

  • Search results: the rows of a filtered list, tree or table, so people see why each one matched.

Use something else when:

  • you want to emphasise words in prose: <strong> or <em> inside Prose
  • the list is a Combobox, CommandPalette or Tree: they mark matches themselves

UsageLink to "Usage"

tsx
Copy
import { HighlightedText } from "@arshad-shah/cynosure";

// Every occurrence of a query, ignoring case
<HighlightedText text={table.name} query={search} />

// The characters a fuzzy matcher picked
const match = fuzzyMatch(search, table.name);
<HighlightedText text={table.name} positions={match?.positions} />

// Each word of a search
<HighlightedText text={command.label} query={search.split(/\s+/)} />

positions are string indices (UTF-16 code units), as JavaScript fuzzy matchers return them; order does not matter and indices outside the text are ignored. When both are given, positions wins. query is plain text, not a pattern: a.b finds only a.b.

To filter a list by the same rule that marks it, use textMatches(text, query): it is true when text contains query (its surrounding spaces trimmed) ignoring case, exactly when query would mark something. Combobox, TagInput, TextArea's mentions, Tree and CommandPalette filter with it.

Positions from afuzzy matcher

PropsLink to "Props"

Every prop of HighlightedText
PropWhat it doesTypeDefault
textRequired
The text to show.string
positions
Indices of the matched characters in text, as fuzzy matchers return them (string indices: UTF-16 code units). Order does not matter; indices outside the text are ignored. Wins over query.readonly number[]
query
Text to find, ignoring case: every occurrence is marked. Several terms (the words of a search) mark each one. Empty terms mark nothing.string | readonly string[]
className
Added to the root element, for layout.string
style
Layout only. Restyle through --cy-highlighted-text-* tokens.CSSProperties

Generated from the type definitions in @arshad-shah/cynosure 0.5.0.

Behaviour and accessibilityLink to "Behaviour and accessibility"

  • Read once: the text is in the page once, with matched runs in <mark> elements. An option or tree row named by its content is named by the whole text ("Select a table", not "Sel", "ect a ", "ta"…), and when it takes focus screen readers read that name, with no "highlighted" between the pieces. There is no hidden second copy, so find-in-page, copying and textContent see the text once.
  • Reading by line: in a screen reader's reading mode, NVDA and JAWS may say "highlighted" at a mark: that is what it means here, the part that matched.
  • Nothing matched: the text is one plain text node.
  • Font: the text inherits the font of where it sits; a matched run is bold and tinted.
  • Forced colours: marks use the system's Mark and MarkText colours and are underlined.
Screen readers read the whole text once

ThemingLink to "Theming"

Tokens: --cy-highlighted-text-highlight (the tint, translucent so it shows on selected rows too), --cy-highlighted-text-ink, --cy-highlighted-text-weight and --cy-highlighted-text-radius.

ts
Copy
createTheme({ components: { highlightedText: { highlight: "rgb(255 220 0 / 0.5)", weight: "inherit" } } });
Readable in light and dark

Tree · Combobox · CommandPalette

These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.

Getting started
Theming
Icons
Accessibility
Code editors and highlighters
Using Cynosure without React
Build-tool adapters
Components
Accordion
AppShell
AspectRatio
Breadcrumbs
Calendar
Card
Container
Disclosure
Divider
DocumentViewport
Grid
Inline
PageHeader
PanZoomCanvas
ScrollArea
SideNav
SortableList
SplitPane
Stack
StatusBar
Tabs
TitleBar
Toolbar
Tree
VirtualList
ZoomControls
Announcer
Avatar
Badge
CodeBlock
DescriptionList
EmptyState
ErrorBoundary
Field
Heading
IconTile
Image
Kbd
List
LoadingDots
Notice
ProgressBar
Prose
Skeleton
Stat
Steps
Table
Text
Button
Checkbox
Checklist
ColorField
ColorSwatches
Combobox
CompareSlider
CopyButton
DateField
FileDrop
IconButton
KeyValueEditor
Link
NumberField
Pagination
PathField
RadioGroup
SearchField
SegmentedControl
Select
SelectionFrame
SignaturePad
Slider
Switch
TagInput
TextArea
TextField
ThemeToggle
TimeField
ButtonBase
ChoiceBase
DialogBase
FileInputBase
HiddenValue
Icon
InputBase
LinkBase
LiveRegion
TextAreaBase
ChatMessage
Choice
DataGrid
DeviceFrame
HighlightedText
HotkeyField
ListRow
OptionList
OverlayFrame
QRCode
RowActions
Section
SiteFooter
SiteHeader
SkipLink
SortButton
VisuallyHidden
CommandPalette
ContextMenu
Dialog
FloatingToolbar
HoverCard
Menu
Menubar
Popover
ProgressOverlay
Sheet
Toast
Tooltip
Changelog