Skip to content

Highlighter

This component draws a hand-drawn annotation, such as a highlight, underline, box or circle, around inline content. It builds on rough-notation, so every stroke looks sketched rather than perfectly geometric, and the annotation animates itself into place.

Flux makes it easy to build beautiful and accessible interfaces.

The annotation is purely decorative and is drawn on top of the content, so it never affects layout or readability. The draw animation is skipped when prefers-reduced-motion is set, in which case the annotation appears instantly.

Inside a Highlighter group the group draws all annotations as one sequence and can supply defaults for the annotation props; a highlighter's own props always win. The component also exposes show(), hide() and replay() through a template ref for programmatic control.

Props

variant?: "highlight" | "box" | "circle" | "underline" | "strike-through" | "crossed-off" | "bracket"
The annotation style to draw.
Default: highlight

color?: string
The color of the annotation. Accepts any CSS color.
Default: var(--warning-200)

stroke-width?: number
The width of the annotation stroke.
Default: 1.5

animation-duration?: number
The duration of the draw animation in milliseconds.
Default: 500

iterations?: number
How many times the annotation is drawn.
Default: 2

padding?: number
The spacing between the element and the annotation, in pixels.
Default: 2

multiline?: boolean
Annotate wrapped inline text line by line instead of as a single block.
Default: true

when-in-view?: boolean
Draw the annotation only once the element scrolls into view instead of immediately.

Emits

shown: []
Triggered when the draw animation completes. Inside a Highlighter group the group draws the annotation, so this is not emitted there.

hidden: []
Triggered when the annotation is hidden through the exposed hide() method.

Slots

default
The content to annotate.

Examples

Actions

Seven annotation styles are available: highlight, underline, box, circle, bracket, strike-through and crossed-off.

The highlight marker.An underline stroke.A box outline.A circle around it.A bracket aside.A strike-through line.A crossed-off word.

<template>
    <FluxFlex
        direction="vertical"
        :gap="18"
        style="font-size: 18px;">
        <span>The <FluxVisualHighlighter variant="highlight">highlight</FluxVisualHighlighter> marker.</span>
        <span>An <FluxVisualHighlighter variant="underline" color="var(--primary-400)">underline</FluxVisualHighlighter> stroke.</span>
        <span>A <FluxVisualHighlighter variant="box" color="var(--primary-400)">box</FluxVisualHighlighter> outline.</span>
        <span>A <FluxVisualHighlighter variant="circle" color="var(--danger-400)">circle</FluxVisualHighlighter> around it.</span>
        <span>A <FluxVisualHighlighter variant="bracket" color="var(--primary-400)">bracket</FluxVisualHighlighter> aside.</span>
        <span>A <FluxVisualHighlighter variant="strike-through" color="var(--danger-500)">strike-through</FluxVisualHighlighter> line.</span>
        <span>A <FluxVisualHighlighter variant="crossed-off" color="var(--danger-500)">crossed-off</FluxVisualHighlighter> word.</span>
    </FluxFlex>
</template>

<script
    lang="ts"
    setup>
    import { FluxFlex } from '@flux-ui/components';
    import { FluxVisualHighlighter } from '@flux-ui/visuals';
</script>

Colors

Any CSS color works. Reach for the theme tokens to keep the annotation in sync with light and dark mode.

A warning tone.A success tone.An info tone.

<template>
    <FluxFlex
        direction="vertical"
        :gap="18"
        style="font-size: 18px;">
        <span>A <FluxVisualHighlighter color="var(--warning-200)">warning</FluxVisualHighlighter> tone.</span>
        <span>A <FluxVisualHighlighter color="var(--success-200)">success</FluxVisualHighlighter> tone.</span>
        <span>An <FluxVisualHighlighter color="var(--info-200)">info</FluxVisualHighlighter> tone.</span>
    </FluxFlex>
</template>

<script
    lang="ts"
    setup>
    import { FluxFlex } from '@flux-ui/components';
    import { FluxVisualHighlighter } from '@flux-ui/visuals';
</script>

When in view

Set `when-in-view` to defer the animation until the element scrolls into the viewport.

This annotation is drawn only once it scrolls into view.

<template>
    <p style="max-width: 369px; font-size: 21px; line-height: 1.9; text-align: center;">
        This
        <FluxVisualHighlighter
            when-in-view
            color="var(--success-200)">annotation</FluxVisualHighlighter>
        is drawn only once it scrolls into view.
    </p>
</template>

<script
    lang="ts"
    setup>
    import { FluxVisualHighlighter } from '@flux-ui/visuals';
</script>

Replay

Call show(), hide() or replay() through a template ref to control the annotation programmatically.

Draw the annotation again on demand.

<template>
    <FluxFlex
        align="start"
        direction="vertical"
        :gap="12">
        <p style="font-size: 21px;">
            Draw the
            <FluxVisualHighlighter ref="highlighter">annotation</FluxVisualHighlighter>
            again on demand.
        </p>

        <FluxSecondaryButton
            icon-leading="rotate"
            label="Replay"
            @click="highlighterRef?.replay()"/>
    </FluxFlex>
</template>

<script
    lang="ts"
    setup>
    import { FluxFlex, FluxSecondaryButton } from '@flux-ui/components';
    import { FluxVisualHighlighter } from '@flux-ui/visuals';
    import { useTemplateRef } from 'vue';

    const highlighterRef = useTemplateRef<InstanceType<typeof FluxVisualHighlighter>>('highlighter');
</script>