useTextSelection
Track and access the currently selected text and its position on the page.
Select Text Below
React Hooks are functions that let you use state and other React features without writing a class. Highlighting text is a common interaction on the web, often used for sharing quotes or adding comments. Try selecting any part of this paragraph to see the Smart Highlighter in action.
Usage
import { useTextSelection } from 'usehooks-ts'
export default function Component() {
const { text } = useTextSelection()
return (
<div>
Selected text: {text}
</div>
)
}API
const { text, clientRects } = useTextSelection()Return Values
| Name | Type | Description |
|---|---|---|
text | string | The currently selected text string |
clientRects | ClientRect[] | Array of DOMRect objects representing the selected text boundaries |
Hook
import { useState, useLayoutEffect, useEffect } from 'react'
export interface ClientRect {
x: number
y: number
top: number
left: number
bottom: number
right: number
width: number
height: number
}
interface SelectionState {
text: string
clientRects: ClientRect[]
}
const defaultState: SelectionState = {
text: '',
clientRects: [],
}
const isBrowser = typeof window !== 'undefined'
const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect
export function useTextSelection(): SelectionState {
const [state, setState] = useState<SelectionState>(defaultState)
useIsomorphicLayoutEffect(() => {
const handleSelectionChange = () => {
const selection = window.getSelection()
if (!selection || selection.rangeCount === 0) {
setState(defaultState)
return
}
const text = selection.toString()
// If no text selected, clear state
if (!text) {
setState(defaultState)
return
}
const range = selection.getRangeAt(0)
const rects = range.getClientRects()
const clientRects = Array.from(rects).map((rect) => ({
x: rect.x,
y: rect.y,
top: rect.top,
left: rect.left,
bottom: rect.bottom,
right: rect.right,
width: rect.width,
height: rect.height,
}))
setState({
text,
clientRects,
})
}
document.addEventListener('selectionchange', handleSelectionChange)
return () => {
document.removeEventListener('selectionchange', handleSelectionChange)
}
}, [])
return state
}