Liseré
A lightweight and composable React component for selecting and highlighting text.
Installation
Install the package via npm, yarn, or your package manager of choice.
pnpm add lisere
# Basic Usage
Select any part of this text. A default highlight will be applied as soon as the selection is valid.
This component allows you to easily add text highlighting functionality to your React applications. Simply select any text in this paragraph and it will be highlighted automatically. The component is highly customizable and supports various selection modes, styling options, and event callbacks.
1<TextHighlighter
2 onTextHighlighted={(selection: TextSelection) => {
3 setHighlights(prev => [...prev, selection.text]);
4 }}
5>
6 <p>Your content here...</p>
7</TextHighlighter>
# Custom Styling
Choose different highlight styles and see how they apply to new selections.
This paragraph demonstrates custom styling options. Select any text to see how the chosen style is applied. You can customize highlights using CSS classes, inline styles, or a combination of both. The styling system is flexible and allows for complex visual effects.
1<TextHighlighter
2 highlightStyle={{
3 style: {
4 background: 'linear-gradient(45deg, #f3e8ff, #faf5ff)',
5 color: '#431407',
6 padding: '2px',
7 borderRadius: '8px',
8 boxShadow: '0 0 0 1px rgba(126,34,206,0.1), 0 1px 2px -1px rgb(126,34,206), 0 1px 4px -2px rgba(126,34,206,0.1), 0 4px 8px -4px rgba(126,34,206,0.1)',
9 cursor: 'crosshair',
10 }
11 }}
12>
13 <p>Your content here...</p>
14</TextHighlighter>
# Selection Boundary Modes
Compare cursor-based vs word-based selection boundaries. Try selecting partial words in each mode.
Try selecting parts of words like "demonstrat" from "demonstration" or "bound" from "boundaries". In cursor mode, you'll highlight exactly what you select. In word mode, the selection will expand to include complete words. This feature is particularly useful for applications like text annotation tools where you want consistent highlighting behavior.
1<TextHighlighter
2 selectionBoundary="cursor"
3>
4 <p>Your content here...</p>
5</TextHighlighter>
# Custom Render Props
Use render props to completely customize how highlights are displayed.
This example shows how to use custom render props to create unique highlight styles. The highlights here have a gradient background, a sparkle emoji, and a tooltip showing the highlighted text. You can create any custom UI for your highlights using this approach.
1<TextHighlighter
2 renderHighlight={({
3 children,
4 selection,
5 }: {
6 children: React.ReactNode;
7 selection: TextSelection;
8 }) => (
9 <span
10 title={`Highlighted: "${selection.text}"`}
11 style={{
12 background: 'linear-gradient(45deg, #f3e8ff, #faf5ff)',
13 color: '#431407',
14 padding: '2px',
15 borderRadius: '8px',
16 boxShadow: '0 0 0 1px rgba(126,34,206,0.1), 0 1px 2px -1px rgb(126,34,206), 0 1px 4px -2px rgba(126,34,206,0.1), 0 4px 8px -4px rgba(126,34,206,0.1)',
17 cursor: 'crosshair',
18 }}
19 >
20 {children} 🍒
21 </span>
22 )}
23>
24 <p>Your content here...</p>
25</TextHighlighter>
# Custom Selection UI
Add custom UI that appears when text is selected, allowing users to confirm or cancel highlighting. Note that the text is highlighted immediately when selected, and the UI allows you to confirm or cancel the highlight.
Select any text in this paragraph to see the custom selection UI in action. The text will be highlighted immediately, and a popup will appear asking if you want to keep the highlight. Click "Yes" to confirm or "No" to remove it. This is useful for applications where you want to show immediate feedback while still allowing user confirmation.
1<TextHighlighter
2 renderSelectionUI={({
3 selection,
4 modifyHighlight,
5 onClose,
6}: {
7 selection: TextSelection;
8 modifyHighlight: (highlight: TextSelection, cancel: boolean) => void;
9 onClose: () => void;
10}) => (
11 <div className="selection-popup">
12 <span>Highlight "{selection.text}"?</span>
13 <button onClick={() => modifyHighlight?.(selection, false)}>
14 Yes
15 </button>
16 <button onClick={() => modifyHighlight?.(selection, true)}>
17 No
18 </button>
19 <button onClick={onClose}>
20 Cancel
21 </button>
22 </div>
23 )}
24>
25 <p>Your content here...</p>
26</TextHighlighter>
# Pre-selected Content
Highlight specific text automatically when the component mounts. Useful for displaying saved highlights or annotations.
This paragraph has some pre-selected text that gets highlighted automatically when the component loads.
1<TextHighlighter
2 selectedContent={[
3 { text: 'important', startOffset: 0, endOffset: 9 },
4 { text: 'keyword', startOffset: 0, endOffset: 7 }
5 ]}
6>
7 <p>Your content with important keywords here...</p>
8</TextHighlighter>
# Remove Highlight on Click
Enable the toggle below to remove highlights when you click on them.
This demo shows how to remove highlights by clicking on them. First, select some text to highlight it. Then, if the toggle is enabled, click on any highlighted text to remove it. This is useful for creating interactive annotation systems where users can easily remove highlights they no longer need.
1<TextHighlighter
2 removeHighlightOnClick={true}
3 onTextHighlighted={(selection: TextSelection) => {
4 console.log('Highlighted:', selection.text)
5 }}
6 onHighlightRemoved={(selection: TextSelection) => {
7 console.log('Removed:', selection.text)
8 }}
9>
10 <p>Your content here...</p>
11</TextHighlighter>
# useTextHighlighter Hook
Use the hook for more control over highlighting behavior.
This demonstration shows how to use the useTextHighlighter hook for more advanced control. You can programmatically highlight text, change colors dynamically, clear highlights, and get the current text selection. The hook provides a more flexible API for complex use cases where you need fine-grained control over the highlighting behavior.
1 const { highlights, highlightText, clearHighlights } = useTextHighlighter({
2 containerRef,
3 highlightStyle: { style: { backgroundColor: "default" } },
4 onTextHighlighted: (selection: TextSelection) => {
5 console.log("Highlighted:", selection.text);
6 },
7 });
8
# Utility Functions
Use the exported utility functions for direct DOM manipulation and advanced highlighting scenarios.
This example demonstrates direct utility function usage. You can manually highlight specific text using the search input above, or select text with your mouse to test the selection utilities. The utility functions provide low-level control over highlighting behavior for advanced use cases.
1import {
2 highlightRange,
3 removeHighlight,
4 findTextInElement,
5 clearSelection,
6 isValidSelection
7} from 'lisere'
8
9// Manual highlighting
10const container = document.getElementById('content')
11const ranges = findTextInElement(container, 'search term')
12ranges.forEach(range => {
13 const highlight = highlightRange(range, 'span', {
14 className: 'manual-highlight',
15 style: { backgroundColor: 'yellow' }
16 })
17})
18
19// Get current selection
20const selection = window.getSelection()
21if (selection && selection.rangeCount > 0 && !selection.isCollapsed) {
22 const range = selection.getRangeAt(0)
23 const text = range.toString().trim()
24 if (text) {
25 console.log('Selected text:', text)
26 }
27}
28
29// Remove highlight
30const highlightElement = document.querySelector('.highlight')
31if (highlightElement) {
32 removeHighlight(highlightElement)
33}
34
35// Clear selection
36clearSelection()
37window.getSelection()?.removeAllRanges()
38
39// Validate selection
40const selection = window.getSelection()
41if (selection && selection.rangeCount > 0 && !selection.isCollapsed) {
42 const range = selection.getRangeAt(0)
43 const text = range.toString().trim()
44 const isInContainer = container.contains(range.commonAncestorContainer)
45 console.log('Selection valid:', isInContainer && text.length > 0)
46}