# ShinyText

> Atom — orn-ui

> ⚠️ Requires <UIProvider>: This component (like every orn-ui component) must render inside a <UIProvider> ancestor, or it throws at runtime. See https://orn-ui-docs.vercel.app/getting-started.md

> Runs on Expo SDK 54, 55, 56 and 57, and on bare React Native >=0.81 with react >=19.1. No native modules — works in Expo Go, no prebuild.

## Installation

Install just this component (copies the source into your project, no npm dependency)
```bash
npx orn-ui add shiny-text
```

Or install the whole package and import it
```tsx
pnpm add orn-ui
import { ShinyText } from 'orn-ui/shiny-text';
```

Depends on: core (theme + icons), transition

## Variants

### align="center" — wraps by word on several lines

```tsx
<ShinyText text="A headline long enough to wrap onto more than one line" align="center" {...strong} />
```

### duration and delay — slow sweep, long pause

```tsx
<ShinyText text="Taking its time" duration={4000} delay={1200} {...strong} />
```

### animated={false} — plain text in shineColor, same box

```tsx
<VariantRow>
  <ShinyText text="No sweep at all" animated={false} {...strong} />
</VariantRow>
```

## Full demo source

```tsx
function ColorPairs() {
  const colors = useColors();

  return (
    <View style={{ gap: 16 }}>
      <View style={{ gap: 4 }}>
        <Caption>default — textLight resting, primary shining</Caption>
        <ShinyText text="Default pair" />
      </View>
      <View style={{ gap: 4 }}>
        <Caption>border → text — the widest pair the theme has</Caption>
        <ShinyText text="Maximum contrast" color={colors.border} shineColor={colors.text} />
      </View>
    </View>
  );
}

function Spreads() {
  const colors = useColors();

  return (
    <View style={{ gap: 12 }}>
      <ShinyText text="Narrow glint" spread={0.08} color={colors.border} shineColor={colors.text} />
      <ShinyText text="Soft wide wave" spread={0.6} color={colors.border} shineColor={colors.text} />
    </View>
  );
}

function UpgradeCard() {
  const colors = useColors();

  return (
    <Card>
      <ShinyText text="Pro plan" color={colors.primarySoft} shineColor={colors.primary} />
      <Body style={{ marginTop: 4 }}>Unlimited invoices · priority support</Body>
    </Card>
  );
}

export function ShinyTextDemo() {
  const colors = useColors();
  // El par por defecto sólo cambia luminancia; para mirar *cómo* se mueve la
  // banda conviene el par más separado del tema, que cambia tono también.
  const strong = { color: colors.border, shineColor: colors.text };

  const variants: VariantDef[] = [
    {
      label: 'colors — the resting/shine pair is what makes it readable',
      content: <ColorPairs />,
    },
    {
      label: 'align="center" — wraps by word on several lines',
      content: (
        <ShinyText text="A headline long enough to wrap onto more than one line" align="center" {...strong} />
      ),
    },
    {
      label: 'spread — narrow glint vs. soft wave',
      content: <Spreads />,
    },
    {
      label: 'duration and delay — slow sweep, long pause',
      content: <ShinyText text="Taking its time" duration={4000} delay={1200} {...strong} />,
    },
    {
      label: 'animated={false} — plain text in shineColor, same box',
      content: (
        <VariantRow>
          <ShinyText text="No sweep at all" animated={false} {...strong} />
        </VariantRow>
      ),
    },
    {
      label: 'in a card, with the brand accent',
      content: <UpgradeCard />,
    },
  ];
  return <VariantList variants={variants} />;
```

## Props

| Name | Type | Default | Description |
|---|---|---|---|
| `text` | `string` | — | The text to animate. Only a string: the effect needs the characters. |
| `duration?` | `number` | 2400 | Milliseconds a single sweep takes end to end. |
| `delay?` | `number` | 600 | Pause between sweeps, in ms. |
| `spread?` | `number` | 0.28 | Width of the bright band as a fraction of the text, from 0 to 1. Small values give a narrow glint, large ones a soft wave. |
| `animated?` | `boolean` | true | When false it renders plain text in `shineColor`. |
| `color?` | `string` | theme.colors.textLight | Resting color of the characters. |
| `shineColor?` | `string` | theme.colors.primary | Color of the band that travels across. |
| `align?` | `'left' \| 'center' \| 'right'` | left | Horizontal alignment of the line. |
| `style?` | `StyleProp<TextStyle>` | — | Typography only: `color` and `shineColor` win over any color set here. |
