True Focus
The TrueFocus component creates a text focus effect with animated borders and blur transitions. It highlights individual words with customizable borders, glow effects, and animation timing.
Usage
True Focus
Highlight specific words in a sentence with dynamic focus effects for emphasis
<template>
<div class="p-6 bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-gray-800 dark:to-gray-900 rounded-xl max-w-2xl mx-auto">
<div class="text-center mb-6">
<h3 class="text-2xl font-bold mb-3 text-highlighted">
True Focus
</h3>
<p class="text-muted">
Highlight specific words in a sentence with dynamic focus effects for emphasis
</p>
</div>
<div class="bg-default rounded-lg p-6 shadow">
<MTrueFocus
sentence="Create stunning interfaces with our animated components"
:manual-mode="true"
:blur-amount="4"
border-color="blue"
class="text-xl text-center"
/>
</div>
<div class="mt-6 flex justify-center gap-3">
<UButton
color="primary"
variant="solid"
size="sm"
>
<UIcon
name="i-lucide-play"
class="w-4 h-4 mr-2"
/>
Animate Focus
</UButton>
<UButton
color="gray"
variant="outline"
size="sm"
>
<UIcon
name="i-lucide-settings"
class="w-4 h-4 mr-2"
/>
Customize
</UButton>
</div>
</div>
</template>
Examples
Automatic cycle
True Focus
<template>
<div class="p-6 bg-elevated rounded-lg">
<h3 class="text-lg font-bold mb-4 text-highlighted">
True Focus
</h3>
<MTrueFocus
sentence="True Focus"
:manual-mode="false"
:blur-amount="5"
border-color="red"
:animation-duration="2"
:pause-between-animations="1"
/>
</div>
</template>
With manualMode off the focus steps through the words on its own: each move
takes animationDuration seconds and rests for pauseBetweenAnimations before
the next. A slow 2s move over a one- or two-word sentence reads as a deliberate
pan rather than a flick.
Amber focus, hover-driven
Manual mode: the focus follows the word you hover. The corner brackets carry a drop shadow tinted by the border colour, so an amber frame gets an amber halo — and `glowColor` resolves through the same theme colour resolver, ready for slots that want it.
<template>
<div class="flex flex-col items-center gap-4 p-8">
<MTrueFocus
sentence="Ship code that lasts"
manual-mode
:blur-amount="4"
border-color="amber"
glow-color="rgba(245, 158, 11, 0.8)"
:animation-duration="0.35"
:pause-between-animations="1.5"
class="text-2xl"
/>
<p class="max-w-sm text-center text-sm text-muted">
Manual mode: the focus follows the word you hover. The corner brackets
carry a drop shadow tinted by the border colour, so an amber frame gets an
amber halo — and `glowColor` resolves through the same theme colour
resolver, ready for slots that want it.
</p>
</div>
</template>
borderColor and glowColor both run through the theme colour resolver, so
Nuxt UI colour names (green, amber, blue) work as well as raw values. The
corners drop-shadow in the resolved border colour; glowColor is written to
the focus overlay's --glow-color custom property for slots that want a second
tint.
Customize
Customize
Props
| Prop | Type | Default | Description |
|---|---|---|---|
sentence | string | 'True Focus' | The sentence to display with focus effects. |
manualMode | boolean | false | Whether to control focus manually or automatically. In manual mode the focus follows the pointer; otherwise it advances on a timer. |
blurAmount | number | 5 | Amount of blur to apply to unfocused words. |
borderColor | string | 'green' | Color of the focus border. Resolved through the theme colour resolver. |
glowColor | string | 'rgba(0, 255, 0, 0.6)' | Color written to the focus overlay's --glow-color custom property. Resolved
through the theme colour resolver. |
animationDuration | number | 0.5 | Duration of the focus animation in seconds. Also the width of each automatic step. |
pauseBetweenAnimations | number | 1 | Pause between automatic animations in seconds. The step interval is
animationDuration + pauseBetweenAnimations. |
class | string | undefined | Classes for the root element, merged after the theme's root slot. Type styles
set here are inherited by every word. |
ui | object | undefined | Per-slot classes merged over the theme defaults. See UI. |
UI
This component's theme exposes the slots below. Override any of them per instance with the ui prop, or app-wide under ui.trueFocus in app.config.ts.
| Prop | Type | Default | Description |
|---|---|---|---|
ui | object | - | Per-slot classes merged over the theme defaults. |
| Slot | Props | Description |
|---|---|---|
root | - | relative flex gap-4 justify-center items-center flex-wrap |
word | - | relative text-[3rem] font-black cursor-pointer |
focus | - | absolute top-0 left-0 pointer-events-none box-border border-0 |
corner | - | absolute w-4 h-4 border-[3px] rounded-[3px] |
Accessibility
The words are plain spans inside a div: no aria-live region, no focus
semantics, no tabindex. Assistive technology reads the full sentence once, in
order, regardless of which word is visually in focus, and the border overlay is
decoration on a pointer-events-none box.
In manual mode the focus follows the pointer only — the words are not focusable and there is no keyboard equivalent, so hover here is visual enrichment and the sentence underneath stays the content. Automatic mode advances on a timer and needs nothing from the user.
There is no reduced-motion handling: the automatic cycle keeps stepping under
prefers-reduced-motion. The per-word blur is a CSS filter transition and the
focus box glides on x/y/width/height — all small, all continuous while a
step is running.
Performance
- The focus box is a single animated element. Its rectangle is measured with two
getBoundingClientRectcalls (container and active word) once per focus change, afternextTick— never per frame. - Word blur is a CSS
filtertransition driven by an inlinetransitionstring. The un-focused words carry a static blur; only the word entering or leaving focus transitions. Blur cost scales with painted area, so very large words are the expensive case. - Automatic mode is one
setIntervalatanimationDuration + pauseBetweenAnimationsmilliseconds. It is cleared on unmount, suspended whilemanualModeis on, and restarted whenmanualModeflips back off. - There are no scroll, resize or rAF listeners, and the focus rectangle is not re-measured on layout changes: resize the page while a word is focused and the box stays where that word was until the next focus change.