ShinyText
The ShinyText component adds an animated shimmer effect to text, creating an elegant and eye-catching visual element that’s perfect for headings, titles, or any text you want to emphasize with subtle movement.
Usage
<script>
import ShinyText from "$lib/components/ui/ShinyText.svelte";
</script>
<ShinyText text="Magical Text" />
Examples
Basic ShinyText
A simple example with default styling.
With Custom Text
ShinyText with different content.
With Custom Class
ShinyText with custom styling applied.
Multiple Instances
Multiple ShinyText components showing different shimmer timings.
In Context
Using ShinyText within a UI component.
A collection of experimental filmmaking tools to enhance your creative process
API Reference
ShinyText Properties
Property | Type | Default | Description |
---|---|---|---|
text | string | '' | The text content to display with the shimmer effect. |
class | string | '' | Additional CSS classes to apply to the container element. |
Implementation
The ShinyText component uses SVG and CSS animations to create a shimmering effect over text. It first renders the text normally, then creates an SVG mask of the text and applies a gradient animation that moves across the text creating the shimmer effect:
<script lang="ts">
import { cn } from '$lib/utils';
let { text = '', class: className = '' } = $props<{ text: string; class?: string }>();
// Create unique IDs for our SVG elements
const maskId = $state(crypto.randomUUID());
const gradientId = $state(crypto.randomUUID());
// Calculate text dimensions for proper shimmer
let textElement: SVGTextElement;
let textWidth = $state(0);
let textHeight = $state(0);
$effect(() => {
if (textElement) {
const bbox = textElement.getBBox();
textWidth = bbox.width;
textHeight = bbox.height;
}
});
</script>
<div class={cn('relative inline-block', className)}>
<span class="invisible">{text}</span>
<svg
class="absolute inset-0 h-full w-full"
preserveAspectRatio="xMidYMid slice"
viewBox="0 0 {textWidth} {textHeight}"
>
<!-- Define the gradient for the shimmer effect -->
<defs>
<linearGradient id={gradientId} x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="transparent" />
<stop offset="45%" stop-color="transparent" />
<stop offset="50%" stop-color="hsl(var(--blue-200))" stop-opacity="0.5" />
<stop offset="55%" stop-color="transparent" />
<stop offset="100%" stop-color="transparent" />
</linearGradient>
<!-- Create a mask from the text -->
<mask id={maskId}>
<text
bind:this={textElement}
x="50%"
y="50%"
text-anchor="middle"
dominant-baseline="middle"
class="font-grotesk fill-white text-4xl tracking-tight"
>
{text}
</text>
</mask>
</defs>
<!-- Base text layer -->
<text
x="50%"
y="50%"
text-anchor="middle"
dominant-baseline="middle"
class="font-grotesk fill-[hsl(var(--foreground))] text-4xl tracking-tight"
>
{text}
</text>
<!-- Animated shimmer layer -->
<rect
width="200%"
height="100%"
fill={`url(#${gradientId})`}
mask={`url(#${maskId})`}
class="animate-shimmer"
/>
</svg>
</div>
<style>
@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0%);
}
}
.animate-shimmer {
animation: shimmer 2.5s ease-in-out infinite;
}
</style>
The component uses Svelte 5 Runes ($state
, $effect
, $props
) for reactive state management, following the coding standards for magic.mov. The shimmer animation is created using CSS keyframes animation that moves a gradient across the text, which is applied using SVG masks to ensure it only appears on the text itself.