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.
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.
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> );}import { createTextSelection } from "@usels/web";
function SelectionTracker() { "use scope" const { text$, rects$, ranges$ } = createTextSelection();
return ( <div> <p>Select some text on the page</p> <p>Selected: {text$.get() || "Nothing selected"}</p> <p>Ranges: {ranges$.get().length}</p> <p>Rects: {rects$.get().length}</p> </div> );}Highlight selected area
Section titled “Highlight selected area”// @noErrorsimport { 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", }} /> ))} </> );}Throttle during drag-select
Section titled “Throttle during drag-select”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 100msDebounce for final selection only
Section titled “Debounce for final selection only”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 stopsParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
options | UseTextSelectionOptions (optional) | - |
UseTextSelectionOptions
Section titled “UseTextSelectionOptions”Returns
Section titled “Returns”UseTextSelectionReturn
| Name | Type | Description |
|---|---|---|
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 |