# Falling Text

> Text that breaks apart and tumbles into a pile you can drag, throw and swipe, then flies back into place.

A sentence that collapses under Matter.js physics. Words (or single letters) drop in a chosen order and knock loose the pieces they land on, then pile up on the floor. Drag and throw a piece, or swipe quickly through the pile to scatter it. Once it settles and the pointer leaves, the text springs back into place and can fall again. Switch between plain text and tiles, and tune the feel in the panel.

<demo-falling-text>



</demo-falling-text>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/falling-text.json"
```

## Usage

The component fills its parent (`width` and `height` 100%), so give the parent a height.

```vue
<script setup lang="ts">
  import FallingText from '~/components/ui/falling-text/FallingText.vue';
</script>

<template>
  <div class="relative h-115 w-full overflow-hidden">
    <FallingText
      text="Some sentences are built to last. This one falls apart on contact."
      :highlight-words="['falls', 'apart']"
      trigger="hover"
      variant="tiles"
      font-size="1.5rem"
      accent-color="#5b8cff"
      :restore-delay="2"
      theme="dark"
    />
  </div>
</template>
```

The text inherits `color` from the parent; highlighted words use `accent-color`. The demo presets ship with the component as `fallingTextPreset(name)` (`classic`, `tiles`, `letters`, `domino`, `bouncy`).

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        text
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      The text that falls apart
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        highlight-words
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      <code>
        []
      </code>
    </td>
    
    <td>
      Words starting with any of these get the accent color (or accent tile)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        highlight-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'highlighted'
      </code>
    </td>
    
    <td>
      Extra class added to highlighted pieces
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        trigger
      </code>
    </td>
    
    <td>
      <code>
        'auto' | 'hover' | 'click' | 'scroll'
      </code>
    </td>
    
    <td>
      <code>
        'auto'
      </code>
    </td>
    
    <td>
      What starts the fall. <code>
        scroll
      </code>
      
       starts it when the text scrolls into view
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        variant
      </code>
    </td>
    
    <td>
      <code>
        'text' | 'tiles'
      </code>
    </td>
    
    <td>
      <code>
        'text'
      </code>
    </td>
    
    <td>
      Plain falling text, or words on tiles that stack like blocks
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        split
      </code>
    </td>
    
    <td>
      <code>
        'words' | 'letters'
      </code>
    </td>
    
    <td>
      <code>
        'words'
      </code>
    </td>
    
    <td>
      Whether whole words or single letters fall
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        order
      </code>
    </td>
    
    <td>
      <code>
        'random' | 'sequence' | 'center' | 'together'
      </code>
    </td>
    
    <td>
      <code>
        'random'
      </code>
    </td>
    
    <td>
      Which pieces drop first. Falling pieces knock loose the ones they land on
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stagger
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.03
      </code>
    </td>
    
    <td>
      Delay between pieces dropping, in seconds
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gravity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Strength of gravity. Negative values fall upward
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        bounciness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      How much pieces bounce when they land (0–1)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scatter
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      Spin and sideways push each piece gets as it drops (0–1)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        draggable
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lets people pick up, drag and throw pieces
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-constraint-stiffness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      How tightly a dragged piece follows the pointer (0–1)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cursor-push
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How hard a quick swipe knocks the fallen pieces around. <code>
        0
      </code>
      
       turns it off
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        restore-delay
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Seconds after the pile settles (pointer away) before the text flies back. <code>
        0
      </code>
      
       keeps
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-size
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '1rem'
      </code>
    </td>
    
    <td>
      Font size of the text
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accent-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#5b8cff'
      </code>
    </td>
    
    <td>
      Color of highlighted words, or of their tiles in the tiles variant
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        theme
      </code>
    </td>
    
    <td>
      <code>
        'dark' | 'light'
      </code>
    </td>
    
    <td>
      <code>
        'dark'
      </code>
    </td>
    
    <td>
      Color theme of the tiles
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        background-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'transparent'
      </code>
    </td>
    
    <td>
      Background of the area the text falls into
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        wireframes
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Outlines each piece to show its physics shape
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the root
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The words stay real text nodes in reading order, so screen readers read the sentence whether or not it has fallen.
- With `prefers-reduced-motion: reduce` the text never falls.
- The physics loop runs only while pieces move and pauses while the component is off screen.
- Ported from [React Bits](https://reactbits.dev/text-animations/falling-text) by David Haz.
