Skip to content
Sensors

useTextSelection

Reactively tracks the current text selection on the page. Listens to the selectionchange event and exposes the selected text, ranges, and bounding rectangles as observables.

rects$ is computed lazily — getBoundingClientRect() is only called when rects$ is actually accessed, avoiding unnecessary reflows when bounding rectangles are not needed.

Text Selection

Select any text on this page to see the selection details update in real time.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum. Cras porttitor metus justo, ut fringilla enim fermentum sed.

Text
Ranges
0
Rects
0
import {
const useTextSelection: (options?: DeepMaybeObservable<UseTextSelectionOptions>) => UseTextSelectionReturn
useTextSelection
} from "@usels/web";
function
function SelectionTracker(): JSX.Element
SelectionTracker
() {
const {
const text$: ReadonlyObservable<string>

Selected text content

text$
,
const rects$: ReadonlyObservable<{}>

Bounding rectangles of selected ranges

rects$
,
const ranges$: ReadonlyObservable<{}>

Selection ranges

ranges$
} =
function useTextSelection(options?: DeepMaybeObservable<UseTextSelectionOptions>): UseTextSelectionReturn

Framework-agnostic reactive text-selection tracker. Listens to selectionchange on the document and exposes the current selection's text, ranges, rects (lazily computed), and raw Selection object.

useTextSelection
();
return (
<
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
<
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Select some text on the page</
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
<
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Selected: {
const text$: ReadonlyObservable<string>

Selected text content

text$
.
ImmutableObservableBase<string>.get(trackingType?: TrackingType | GetOptions): {}
get
() || "Nothing selected"}</
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
<
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Ranges: {
const ranges$: ReadonlyObservable<{}>

Selection ranges

ranges$
.
ImmutableObservableBase<{}>.get(trackingType?: TrackingType | GetOptions): {}
get
().
any
length
}</
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
<
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Rects: {
const rects$: ReadonlyObservable<{}>

Bounding rectangles of selected ranges

rects$
.
ImmutableObservableBase<{}>.get(trackingType?: TrackingType | GetOptions): {}
get
().
any
length
}</
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
</
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
);
}
// @noErrors
import { useTextSelection } from "@usels/web";
function SelectionHighlight() {
const { text$, rects$ } = useTextSelection();
return (
<>
<p>Select any text to see highlight overlays</p>
{rects$.get().map((rect, i) => (
<div
key={i}
style={{
position: "fixed",
left: rect.x,
top: rect.y,
width: rect.width,
height: rect.height,
background: "rgba(59, 130, 246, 0.2)",
pointerEvents: "none",
}}
/>
))}
</>
);
}

During drag-selection, selectionchange fires many times per frame. Use throttle to limit how often the handler runs while the user is actively selecting.

const { text$ } = useTextSelection({ throttle: 100 }); // at most once per 100ms

Use debounce when you only care about the selection after the user has finished selecting, not the intermediate states.

const { text$ } = useTextSelection({ debounce: 200 }); // fires 200ms after selection stops
ParameterTypeDescription
optionsUseTextSelectionOptions (optional)-
OptionTypeDefaultDescription
throttleMaybeObservable<number>-Throttle selectionchange handler in ms. Mutually exclusive with debounce.
debounceMaybeObservable<number>-Debounce selectionchange handler in ms. Mutually exclusive with throttle.
windowWindowSource--

UseTextSelectionReturn

NameTypeDescription
text$ReadonlyObservable<string>Selected text content
rects$ReadonlyObservable<DOMRect[]>Bounding rectangles of selected ranges
ranges$ReadonlyObservable<Range[]>Selection ranges
selection$ReadonlyObservable<OpaqueObject<Selection> | null>Current Selection object

View on GitHub