UIPackage
Menu

Gradient Text

gradient-text ui
Edit on GitHub

Applies a CSS gradient as text color via background-clip: text. Supports preset gradients (sunset, ocean, forest, fire, candy, aurora, rainbow, gold, neon, grape), custom from/to colors with a direction, a fully custom CSS gradient string, and an animated mode that shifts the gradient.

Also available for Vue ->

Installation

$ npx shadcn@latest add https://uipkge.dev/r/react/gradient-text.json
Named registry: npx shadcn@latest add @uipkge-react/gradient-text Installs to: components/ui/gradient-text/

Examples

Props

Name Type / Values Default Required
as

Rendered element / component.

React.ElementType optional
asChild

instead of emitting the `as` tag — the React equivalent of reka-ui's as-child.

boolean optional
preset

Preset gradient name. Overrides from/to when set.

GradientPreset optional
from

Start color of a custom two-stop gradient.

string optional
to

End color of a custom two-stop gradient.

string optional
direction

Gradient direction.

Direction optional
gradient

Fully custom CSS gradient (e.g. 'linear-gradient(45deg, #f00, #00f, #0f0)'). Overrides preset/from/to.

string optional
animated

Animate the gradient (subtle background-position shift).

boolean optional
animationDuration

Animation duration in seconds. Default 4.

number optional

Files installed (3)

  • components/ui/gradient-text/GradientText.tsx 3.8 kB
    import * as React from 'react'
    import { Slot } from '@radix-ui/react-slot'
    import { cn } from '@/lib/utils'
    import { gradientTextPresets, type GradientPreset } from './gradient-text.variants'
    
    type Direction =
      | 'to right'
      | 'to left'
      | 'to top'
      | 'to bottom'
      | 'to top right'
      | 'to top left'
      | 'to bottom right'
      | 'to bottom left'
    
    export interface GradientTextProps extends React.HTMLAttributes<HTMLElement> {
      /** Rendered element / component. */
      as?: React.ElementType
      /** Render the child element as the gradient text (merging props/styles)
       *  instead of emitting the `as` tag — the React equivalent of reka-ui's
       *  as-child. */
      asChild?: boolean
      /** Preset gradient name. Overrides from/to when set. */
      preset?: GradientPreset
      /** Start color of a custom two-stop gradient. */
      from?: string
      /** End color of a custom two-stop gradient. */
      to?: string
      /** Gradient direction. */
      direction?: Direction
      /** Fully custom CSS gradient (e.g. 'linear-gradient(45deg, #f00, #00f, #0f0)'). Overrides preset/from/to. */
      gradient?: string
      /** Animate the gradient (subtle background-position shift). */
      animated?: boolean
      /** Animation duration in seconds. Default 4. */
      animationDuration?: number
    }
    
    /* ------------------------------------------------------------------ */
    /* Animation keyframes                                                 */
    /* Ported from GradientText.vue's <style scoped> block. Injected once  */
    /* so the component ships self-contained.                              */
    /* ------------------------------------------------------------------ */
    const gradientTextCss = `
    @media (prefers-reduced-motion: no-preference) {
      @keyframes gradient-text-shift {
        0% {
          background-position: 0% 50%;
        }
        50% {
          background-position: 100% 50%;
        }
        100% {
          background-position: 0% 50%;
        }
      }
    }
    `
    
    function GradientTextStyle() {
      return <style dangerouslySetInnerHTML={{ __html: gradientTextCss }} />
    }
    
    const GradientText = React.forwardRef<HTMLElement, GradientTextProps>(
      (
        {
          className,
          as: asProp = 'span',
          asChild = false,
          preset,
          from,
          to,
          direction = 'to right',
          gradient,
          animated = false,
          animationDuration = 4,
          style,
          children,
          ...props
        },
        ref,
      ) => {
        const Comp = (asChild ? Slot : asProp) as React.ElementType
    
        const gradientValue = React.useMemo(() => {
          if (gradient) return gradient
          if (preset) return gradientTextPresets[preset] ?? ''
          if (from && to) {
            return `linear-gradient(${direction}, ${from}, ${to})`
          }
          // Default fallback: primary token gradient.
          return 'linear-gradient(to right, var(--primary), var(--primary))'
        }, [gradient, preset, from, to, direction])
    
        const computedStyle = React.useMemo<React.CSSProperties>(
          () => ({
            backgroundImage: gradientValue,
            backgroundClip: 'text',
            WebkitBackgroundClip: 'text',
            color: 'transparent',
            WebkitTextFillColor: 'transparent',
            backgroundSize: animated ? '200% 200%' : undefined,
            ...style,
          }),
          [gradientValue, animated, style],
        )
    
        return (
          <>
            <GradientTextStyle />
            <Comp
              data-uipkge=""
              data-slot="gradient-text"
              data-preset={preset ?? undefined}
              data-animated={animated ? 'true' : undefined}
              className={cn(
                'inline-block',
                animated ? `motion-safe:animate-[gradient-text-shift_${animationDuration}s_ease_infinite]` : '',
                className,
              )}
              style={computedStyle}
              ref={ref}
              {...props}
            >
              {children}
            </Comp>
          </>
        )
      },
    )
    GradientText.displayName = 'GradientText'
    
    export { GradientText }
  • components/ui/gradient-text/gradient-text.variants.ts 1.2 kB
    import type { VariantProps } from 'class-variance-authority'
    import { cva } from 'class-variance-authority'
    
    /**
     * Preset gradients keyed by name. Each value is a full CSS gradient string
     * applied as `background-image` with `background-clip: text`.
     */
    export const gradientTextPresets = {
      sunset: 'linear-gradient(to right, #ff7e5f, #feb47b)',
      ocean: 'linear-gradient(to right, #2193b0, #6dd5ed)',
      forest: 'linear-gradient(to right, #11998e, #38ef7d)',
      fire: 'linear-gradient(to right, #f12711, #f5af19)',
      candy: 'linear-gradient(to right, #f857a6, #ff8a5c)',
      aurora: 'linear-gradient(to right, #00c6ff, #0072ff, #00c6ff)',
      rainbow: 'linear-gradient(to right, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3)',
      gold: 'linear-gradient(to right, #bf953f, #fcf6ba, #b38728, #fbf5b7, #aa771c)',
      neon: 'linear-gradient(to right, #00f260, #0575e6)',
      grape: 'linear-gradient(to right, #6a11cb, #2575fc)',
    } as const
    
    export type GradientPreset = keyof typeof gradientTextPresets
    
    export const gradientTextVariants = cva('inline-block', {
      variants: {},
      defaultVariants: {},
    })
    
    export type GradientTextVariants = VariantProps<typeof gradientTextVariants>
  • components/ui/gradient-text/index.ts 0.2 kB
    export { GradientText, type GradientTextProps } from './GradientText'
    export {
      gradientTextPresets,
      gradientTextVariants,
      type GradientPreset,
      type GradientTextVariants,
    } from './gradient-text.variants'

Raw manifest: https://uipkge.dev/r/react/gradient-text.json