wui
组件

文本扫光 Text Shimmer

在文字表面循环扫过的主题感知高光。

基础示例

Loading…
pnpm dlx wui@latest add @wui/text-shimmer
components/ui/text-shimmer.tsx
"use client"

import * as React from "react"
import { motion, useReducedMotion } from "motion/react"

import { cn } from "@/lib/utils"

export interface TextShimmerProps extends React.ComponentProps<"span"> {
  /** Text carrying the shimmer. */
  children: string
  /** HTML element rendered by the component. @default "span" */
  as?: React.ElementType
  /** Seconds for one shimmer pass. @default 2 */
  duration?: number
  /** Gradient width relative to the text. @default 2 */
  spread?: number
}

/** Sweeps a theme-aware highlight across text. */
function TextShimmer({
  children,
  as = "span",
  duration = 2,
  spread = 2,
  className,
  style,
  ...props
}: TextShimmerProps) {
  const reduceMotion = useReducedMotion()
  const Component = React.useMemo(() => motion.create(as), [as])
  const shimmerSpread = `${Math.max(Array.from(children).length * spread, 0)}px`

  return (
    <Component
      data-slot="text-shimmer"
      className={cn(
        "inline-block bg-clip-text text-transparent [--shimmer-base:var(--muted-foreground)] [--shimmer-highlight:var(--foreground)]",
        className
      )}
      style={{
        backgroundImage: reduceMotion
          ? "linear-gradient(var(--shimmer-base),var(--shimmer-base))"
          : "linear-gradient(90deg,transparent calc(50% - var(--shimmer-spread)),var(--shimmer-highlight),transparent calc(50% + var(--shimmer-spread))),linear-gradient(var(--shimmer-base),var(--shimmer-base))",
        backgroundRepeat: "no-repeat",
        backgroundSize: "250% 100%, auto",
        "--shimmer-spread": shimmerSpread,
        ...style,
      } as React.CSSProperties}
      initial={false}
      animate={
        reduceMotion
          ? { backgroundPosition: "100% center" }
          : { backgroundPosition: ["100% center", "0% center"] }
      }
      transition={
        reduceMotion
          ? { duration: 0 }
          : { duration, ease: "linear", repeat: Infinity }
      }
      {...props}
    >
      {children}
    </Component>
  )
}

export { TextShimmer }

组件作用

TextShimmer 适合生成中、加载中等短暂状态。默认颜色来自 foregroundmuted-foreground,因此自动适配明暗主题。

组件属性

PropTypeDefaultDescription
children *stringText carrying the shimmer.
asElementType<any, keyof IntrinsicElements>spanHTML element rendered by the component.
durationnumber2Seconds for one shimmer pass.
spreadnumber2Gradient width relative to the text.

事件

组件没有自有事件并透传底层元素事件。动画会持续循环,减少动态效果时停留在静态渐变状态。

扩展使用

通过 duration 控制扫过速度,通过 spread 调整高光宽度。可以在 className 中覆盖 --shimmer-base--shimmer-highlight 两个 CSS 变量。