# Animated List

> A scrolling list whose rows spring into view from the edge they scroll in from, with a gliding selection and arrow keys.

A scrolling list of rows. Rows spring in from the edge they scroll in from, and a selection ring glides between them as you hover or press the arrow keys. Click a row or press Enter to pick it. Rows can show an icon or an image, a description and a label on the right.

<demo-animated-list>



</demo-animated-list>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import AnimatedList from '~/components/ui/animated-list/AnimatedList.vue';
  import type { AnimatedListItem } from '~/components/ui/animated-list/types';

  const items: AnimatedListItem[] = [
    {
      icon: 'lucide:folder',
      title: 'Brand assets',
      description: '24 files',
      meta: '2m',
    },
    {
      image: 'https://picsum.photos/seed/moon/96/96',
      title: 'Moonrise',
      meta: '4:05',
    },
    'Plain rows work too',
  ];

  function onItemSelect(item: AnimatedListItem, index: number) {
    console.log(item, index);
  }
</script>

<template>
  <AnimatedList
    :items="items"
    animation="slide"
    :loop="true"
    @item-select="onItemSelect"
  />
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        items
      </code>
    </td>
    
    <td>
      <code>
        (string | AnimatedListEntry)[]
      </code>
    </td>
    
    <td>
      15 sample files
    </td>
    
    <td>
      Rows to show. Strings become plain rows. Entries take <code>
        id
      </code>
      
      , <code>
        icon
      </code>
      
      , <code>
        image
      </code>
      
      , <code>
        title
      </code>
      
      , <code>
        description
      </code>
      
      , <code>
        meta
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        initial-selected-index
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        -1
      </code>
    </td>
    
    <td>
      Row that starts selected. <code>
        -1
      </code>
      
       for none.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        select-on-hover
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Moves the selection to the row under the pointer.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        enable-arrow-navigation
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Arrow keys, Home and End move the selection while the list is hovered or focused.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        loop
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Wraps keyboard navigation from the last row to the first.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        animation
      </code>
    </td>
    
    <td>
      <code>
        'pop' | 'slide' | 'fade' | 'none'
      </code>
    </td>
    
    <td>
      <code>
        'pop'
      </code>
    </td>
    
    <td>
      How rows animate in as they scroll into view.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        animate-once
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Animates each row only the first time it appears.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stagger
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.05
      </code>
    </td>
    
    <td>
      Delay between rows when the list first appears, in seconds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        show-gradients
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Fades rows out at the top and bottom edges while there is more to scroll.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fade-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        56
      </code>
    </td>
    
    <td>
      Height of the edge fades, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        display-scrollbar
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows a thin scrollbar when the list overflows.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        frame
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the frosted panel around the list.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        theme
      </code>
    </td>
    
    <td>
      <code>
        'dark' | 'light'
      </code>
    </td>
    
    <td>
      <code>
        'dark'
      </code>
    </td>
    
    <td>
      Colors of the panel and rows.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accent-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Color of the selection ring and focus outline. Uses a soft tint of the text when unset.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        14
      </code>
    </td>
    
    <td>
      Corner radius of the rows, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        8
      </code>
    </td>
    
    <td>
      Space between rows, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      <code>
        420
      </code>
    </td>
    
    <td>
      Maximum width of the list.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        max-height
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      <code>
        440
      </code>
    </td>
    
    <td>
      Height at which the list starts to scroll.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the list.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        item-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for each row.
    </td>
  </tr>
</tbody>
</table>

## Events

<table>
<thead>
  <tr>
    <th>
      Event
    </th>
    
    <th>
      Payload
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        item-select
      </code>
    </td>
    
    <td>
      <code>
        [item: AnimatedListItem, index: number]
      </code>
    </td>
    
    <td>
      A row was clicked, or Enter was pressed on the selected row.
    </td>
  </tr>
</tbody>
</table>

## Slots

<table>
<thead>
  <tr>
    <th>
      Slot
    </th>
    
    <th>
      Props
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        item
      </code>
    </td>
    
    <td>
      <code>
        { item: AnimatedListItem, index: number, selected: boolean }
      </code>
    </td>
    
    <td>
      Your own content inside each row instead of the built-in layout.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The list is a focusable `listbox` and each row is an `option`; `aria-activedescendant` follows the selection.
- `↑` `↓` `Home` `End` move the selection, and the list scrolls to keep it clear of the edge fades. `Enter` (or `Space` while focused) picks it.
- A focus outline in the accent color shows when the list has keyboard focus.
- With `prefers-reduced-motion`, rows only fade and the selection ring jumps instead of gliding.
- Ported from [React Bits](https://reactbits.dev/components/animated-list) by David Haz.
