# Peek Rating

> Star rating that lifts a wave of stars up to the pointer, then commits with a pop on click.

A star rating that previews before it commits. Move the pointer along the row and every star up to it rises, the one under the pointer grows, and a small tip names the score. Click (or release a drag on touch) to commit with a pop; click the current score again to clear it. Arrow keys, Home, End and Backspace work from the keyboard.

<demo-peek-rating>



</demo-peek-rating>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import { ref } from 'vue';
  import PeekRating from '~/components/ui/peek-rating/PeekRating.vue';

  const rating = ref(3);
</script>

<template>
  <PeekRating
    v-model="rating"
    :labels="['Poor', 'Fair', 'Good', 'Great', 'Superb']"
    active-color="#f5b400"
    :size="40"
    :lift="8"
  />
</template>
```

Without `v-model` the component keeps its own score, starting at `default-value`.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        model-value
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        undefined
      </code>
    </td>
    
    <td>
      Controlled rating, from 0 to <code>
        count
      </code>
      
       (use <code>
        v-model
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        default-value
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Initial rating when uncontrolled.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        count
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        5
      </code>
    </td>
    
    <td>
      Number of glyphs.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shape
      </code>
    </td>
    
    <td>
      <code>
        'star' | 'heart' | 'bolt'
      </code>
    </td>
    
    <td>
      <code>
        'star'
      </code>
    </td>
    
    <td>
      Built-in glyph shape.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        icon
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Iconify name of a custom glyph that replaces the built-in shape.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        labels
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      <code>
        []
      </code>
    </td>
    
    <td>
      One label per glyph, shown in the tip while previewing. Without labels the tip shows the number.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        active-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5b400'
      </code>
    </td>
    
    <td>
      Colour of lit glyphs and of the focus ring.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        idle-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#52525b'
      </code>
    </td>
    
    <td>
      Colour of unlit glyphs.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tip-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#27272a'
      </code>
    </td>
    
    <td>
      Background of the tip that follows the pointer.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tip-text-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5f5f5'
      </code>
    </td>
    
    <td>
      Text colour of the tip.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        28
      </code>
    </td>
    
    <td>
      Glyph size in pixels; spacing and the tip scale with it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        lift
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        6
      </code>
    </td>
    
    <td>
      How far previewed glyphs rise, in pixels. <code>
        0
      </code>
      
       makes the preview colour-only.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        magnify
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1.15
      </code>
    </td>
    
    <td>
      Scale of the glyph under the pointer.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rise-duration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        320
      </code>
    </td>
    
    <td>
      Duration in ms of each glyph's rise and fall, and of the tip's hop.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pop-scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1.3
      </code>
    </td>
    
    <td>
      Peak scale of the pop on the committed glyph. <code>
        1
      </code>
      
       disables it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        show-tip
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the tip above the pointer glyph while previewing.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        allow-clear
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Clicking the current rating again, or Backspace, clears it to 0.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        read-only
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Display only: no preview, no pop, announced as an image.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disabled
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Dims the control and ignores input.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        aria-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Rating'
      </code>
    </td>
    
    <td>
      Accessible name of the radio group.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the root element.
    </td>
  </tr>
</tbody>
</table>

## Events

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

<tbody>
  <tr>
    <td>
      <code>
        update:modelValue
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      A rating was committed (drives <code>
        v-model
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        change
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      Same as above, for listeners that do not use <code>
        v-model
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        preview
      </code>
    </td>
    
    <td>
      <code>
        number | null
      </code>
    </td>
    
    <td>
      Fired on every slot crossing while previewing, and with <code>
        null
      </code>
      
       when it clears.
    </td>
  </tr>
</tbody>
</table>

## Slots

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

<tbody>
  <tr>
    <td>
      <code>
        icon
      </code>
    </td>
    
    <td>
      Replaces the glyph inside every slot of the row.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The row is a `radiogroup` of `radio` buttons with labels such as "3 of 5, Good", and only the checked star is in the tab order.
- Arrow keys step the score, Home and End jump to the ends, Backspace and Delete clear it, Space and Enter pick the focused star.
- Keyboard changes apply instantly, without the lift or pop.
- In `read-only` mode the whole row is one image announced as "3 of 5".
- With `prefers-reduced-motion`, glyphs do not lift or pop; only colour changes.
- Ported from [React Bits](https://reactbits.dev/micro/peek-rating) by David Haz.
