Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899<script module lang="ts"> import { tv, type VariantProps } from "tailwind-variants";
export const shimmerText = tv({ base: "inline-block w-fit", variants: { color: { inherit: "", default: "text-foreground-default", muted: "text-foreground-muted", subtle: "text-foreground-subtle", success: "text-foreground-success", danger: "text-foreground-danger", warning: "text-foreground-warning", info: "text-foreground-info" } }, defaultVariants: { color: "inherit" } });
export type ShimmerTextVariants = VariantProps<typeof shimmerText>;</script>
<script lang="ts"> import type { Snippet } from "svelte"; import type { HTMLAttributes } from "svelte/elements";
interface Props extends Omit<HTMLAttributes<HTMLSpanElement>, "class" | "children"> { color?: ShimmerTextVariants["color"]; duration?: number; delay?: number; class?: string; children: Snippet; }
let { color = "inherit", duration = 3, delay = 0, class: className, children, ...rest }: Props = $props();
const classes = $derived(shimmerText({ color, class: className }));</script>
<span class="shimmer {classes}" style:--shimmer-duration="{duration}s" style:--shimmer-delay="{delay}s" {...rest}> {@render children()}</span>
<style> @keyframes shimmer { from { background-position-x: -100%; } 50%, to { background-position-x: 250%; } }
.shimmer { /* mixing towards the page colour lightens the highlight in light mode and darkens it in dark mode, so no dark: override is needed. override the custom property when the text sits on a non-default surface. */ --shimmer-highlight: color-mix(in srgb, currentColor 40%, var(--color-background-default));
background-color: currentColor; background-image: linear-gradient( to right, currentColor 0%, var(--shimmer-highlight) 40%, var(--shimmer-highlight) 60%, currentColor 100% ); background-repeat: no-repeat; background-size: 50% 200%; background-position-x: -100%; background-clip: text; -webkit-text-fill-color: transparent;
animation: shimmer var(--shimmer-duration) linear var(--shimmer-delay) infinite; }
@media (prefers-reduced-motion: reduce) { .shimmer { animation: none; } }</style>