# Faulty Terminal

> A flickering CRT terminal of glowing glyphs, with phosphor trails under the cursor and glitches on click.

Faulty Terminal draws a grid of glowing glyphs on a curved CRT, driven by a swirling noise pattern. Glyphs switch on one by one when it mounts, keep glowing after they switch off like real phosphor, and heat up around the cursor. Move the cursor to leave trails; click to tear the screen or send a degauss wave.

<demo-faulty-terminal>



</demo-faulty-terminal>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import FaultyTerminal from '~/components/ui/faulty-terminal/FaultyTerminal.vue';
</script>

<template>
  <div class="relative size-full min-h-80 overflow-hidden">
    <FaultyTerminal
      class="absolute inset-0 size-full"
      tint="#A7EF9E"
      glyphs="blocks"
      :scale="1.5"
      :digit-size="1.2"
      :time-scale="0.5"
      :brightness="0.75"
      :persistence="0.5"
      click-effect="glitch"
    />
  </div>
</template>
```

The demo presets (Phosphor, Classic, Terminal, Amber, Ice, Meltdown, Data) ship with the component. `faultyTerminalPreset('amber')` returns the full set of visual props; pass `true` as the second argument for the light-page variant.

```vue
<script setup lang="ts">
  import {
    FaultyTerminal,
    faultyTerminalPreset,
  } from '~/components/ui/faulty-terminal';

  const amber = faultyTerminalPreset('amber');
</script>

<template>
  <FaultyTerminal v-bind="amber" />
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        tint
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Phosphor color of the glyphs. In light mode, light colors are deepened so they print clearly.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glyphs
      </code>
    </td>
    
    <td>
      <code>
        'blocks' | 'dots' | 'characters'
      </code>
    </td>
    
    <td>
      <code>
        'blocks'
      </code>
    </td>
    
    <td>
      What each cell draws: squares of lit pixels, round LED dots, or terminal characters that keep changing.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Zoom of the pattern. Higher values show more, smaller glyphs.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grid-mul
      </code>
    </td>
    
    <td>
      <code>
        [number, number]
      </code>
    </td>
    
    <td>
      <code>
        [2, 1]
      </code>
    </td>
    
    <td>
      Glyph density across and down, multiplied with scale.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        digit-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1.5
      </code>
    </td>
    
    <td>
      Space around each glyph. 1 packs them edge to edge, higher values leave wider gaps.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        time-scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.3
      </code>
    </td>
    
    <td>
      Speed of the animation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        brightness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Overall brightness of the screen, or ink strength in light mode.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      Phosphor bloom around the glyphs, with richer color in the halo and paler bright cores.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        persistence
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How long glyphs keep glowing after they switch off. Leaves trails behind the cursor.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-react
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lights up the glyphs around the cursor. The light rests in the middle while the cursor is away.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-strength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      How many glyphs the cursor lights up around it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-glow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      How much the glyphs under the cursor heat up toward white while you move.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scramble
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How fast characters change near the cursor. Only used with <code>
        characters
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-effect
      </code>
    </td>
    
    <td>
      <code>
        'glitch' | 'degauss' | 'none'
      </code>
    </td>
    
    <td>
      <code>
        'glitch'
      </code>
    </td>
    
    <td>
      What a click does: tear the screen into shifting bands, or send a wobbling degauss wave.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scanline-intensity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.3
      </code>
    </td>
    
    <td>
      Strength of the soft halo and the bright band that rolls down the screen.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glitch-amount
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How far the faulty bands of the screen shift sideways.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flicker-amount
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How often the faulty bands appear.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        noise-amp
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Strength of the swirling pattern that decides which glyphs light up.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        chromatic-aberration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Splits the red and blue channels apart, in pixels.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        curvature
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      Bulge of the screen, like the glass of an old tube.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        vignette
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.25
      </code>
    </td>
    
    <td>
      Darkens the edges of the screen so it fades into the page.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dither
      </code>
    </td>
    
    <td>
      <code>
        number | boolean
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Fine noise that smooths color banding.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        page-load-animation
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Switches the glyphs on one by one, each with a short phosphor flash, on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pause
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Freezes the animation. The cursor still lights up glyphs.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        variation
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      random
    </td>
    
    <td>
      Picks a fixed pattern. Leave it out for a different one on every mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        light-mode
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Prints the glyphs as crisp ink on a light page.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dpr
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      auto
    </td>
    
    <td>
      Maximum device pixel ratio, capped at 2.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the container.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative and marked `aria-hidden="true"`; put real content on top of it.
- With `prefers-reduced-motion: reduce`, the pattern holds still, the glitch bands and flicker turn off, the intro is skipped and clicks do nothing. The cursor glow still follows the pointer.
- The render loop stops when the terminal is offscreen, when the tab is hidden, and after the picture has been still for 2.5 seconds.
- Ported from [React Bits](https://reactbits.dev/backgrounds/faulty-terminal) by David Haz.
