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.
<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.
<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>