# Rating Group Documentation
Allows users to provide ratings using customizable items (like stars).
This is a documentation section that potentially contains examples, demos, and other useful information related to a specific part of Bits UI. When helping users with this documentation, you can ignore the classnames applied to the demos unless they are relevant to the user's issue.
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{/each}
{/snippet}
```
##### Warning
This component is currently in preview. The API may change before it is considered stable. You will know when it is stable because the component will be exported as `RatingGroup` instead of `unstable_RatingGroup`. Your feedback will be invaluable in shaping the final API.
## Structure
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "active"}
{:else}
{/if}
{/each}
{/snippet}
```
## Reusable Components
It's recommended to use the `RatingGroup` primitives to create your own custom rating components that can be used throughout your application.
In the example below, we're creating a custom `MyRatingGroup` component that renders a rating group with configurable maximum rating and styling.
MyRatingGroup.svelte
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "inactive"}
{:else if item.state === "active"}
{:else if item.state === "partial"}
{/if}
{/each}
{/snippet}
{#if showLabel}
Rating: {value} out of {max} stars
{/if}
```
You can then use the `MyRatingGroup` component in your application like so:
+page.svelte
```svelte
```
## Managing Value State
This section covers how to manage the `value` state of the component.
### Two-Way Binding
Use `bind:value` for simple, automatic state synchronization:
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "active"}{:else}{/if}
{/each}
{/snippet}
```
### Fully Controlled
Use a [Function Binding](https://svelte.dev/docs/svelte/bind#Function-bindings) for complete control over the state's reads and writes.
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "active"}{:else}{/if}
{/each}
{/snippet}
```
## HTML Forms
If you set the `name` prop on the `RatingGroup.Root` component, a hidden input element will be rendered to submit the rating value to a form.
```svelte
```
### Required
To make the hidden input element `required` you can set the `required` prop on the `RatingGroup.Root` component.
```svelte
```
## Half Ratings
The rating group supports half ratings when you set the `allowHalf` prop to `true`. This allows for more precise ratings like 3.5 stars.
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "inactive"}
{:else if item.state === "active"}
{:else if item.state === "partial"}
{/if}
{/each}
{/snippet}
```
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "inactive"}
{:else if item.state === "active"}
{:else if item.state === "partial"}
{/if}
{/each}
{/snippet}
```
## Readonly Mode
You can make the rating group readonly by setting the `readonly` prop to `true`. This is useful for displaying existing ratings without allowing user interaction.
```svelte
```
## Disabled State
You can disable the entire rating group by setting the `disabled` prop to `true`.
```svelte
```
## Hover Preview
By default, the rating group shows a preview of the potential rating when hovering over items. You can disable this behavior by setting `hoverPreview` to `false`.
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "active"}{:else}{/if}
{/each}
{/snippet}
```
When disabled, only the currently selected rating will be highlighted, and hovering over items won't show a preview of the potential selection.
```svelte
Hover preview disabled
Only shows selected rating on hover, no preview of potential selection.
```
## RTL Support
The rating group automatically adapts to right-to-left (RTL) text direction. Simply set the `dir="rtl"` attribute on a parent element:
```svelte
```
## Maximum Rating
The `max` prop determines the maximum rating value and the number of rating items rendered. (defaults to `5`)
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{item.index + 1}
{/each}
{/snippet}
```
## Minimum Rating
The `min` prop sets a minimum required rating value. When set, users cannot select a rating below this value, and the rating will not go below the minimum when cleared. (defaults to `0`)
```svelte
{#snippet children({ items })}
{#each items as item (item.index)}
{#if item.state === "active"}{:else}{/if}
{/each}
{/snippet}
```
This is useful for scenarios where you require at least a certain rating, such as feedback forms that must have a minimum 1-star rating.
## Accessibility
The `RatingGroup` component implements comprehensive accessibility features following WAI-ARIA best practices for rating interfaces.
### ARIA Implementation
The component uses the **slider pattern** rather than a radiogroup pattern, which provides better screen reader support for rating interfaces:
- **Root element**: `role="slider"` with complete ARIA slider attributes
- **Rating items**: `role="presentation"` to avoid redundant announcements
- **Value communication**: `aria-valuenow` , `aria-valuemin` , `aria-valuemax` for current state
- **Custom descriptions**: `aria-valuetext` for contextual rating descriptions
- **State indicators**: `aria-disabled` , `aria-required` , `aria-orientation` When users navigate with arrow keys, screen readers announce the new rating value immediately, providing real-time feedback.
### Keyboard Navigation Strategy
The keyboard implementation follows platform conventions while adding rating-specific enhancements:
#### Direct Number Input
The most efficient way to set ratings - users can type the exact rating they want:
- **Integer ratings**: Type `3` to set rating to 3 stars
- **Half ratings**: Type `2.5` to set 2.5 stars (when `allowHalf` is enabled)
- **Clear rating**: Type `0` to remove rating (respects minimum constraints)
- **Input validation**: Invalid numbers are ignored, values are clamped to min/max range #### Arrow Key Navigation
Navigation adapts to both rating precision and text direction:
- **Standard mode**: Arrow keys increment/decrement by 1
- **Half rating mode**: Arrow keys increment/decrement by 0.5 for finer control
- **RTL support**: Left/right arrows automatically reverse in right-to-left layouts
- **Bounds respect**: Navigation stops at min/max values #### Quick Navigation
- **`Home`**: Jump to minimum rating (or 1 if no minimum set)
- **`End`**: Jump to maximum rating
- **`PageUp`/`PageDown`**: Increment/decrement by 1 (alternative to arrows) ### Focus Management
The component handles focus intelligently:
- **Mouse interactions**: Clicking a rating item automatically focuses the root slider
- **Keyboard focus**: Single tab stop - the entire rating group acts as one focusable unit
- **Visual feedback**: Focus styling applied to the root container
- **Disabled state**: Component becomes non-focusable when disabled ### Customizing Accessibility
You can enhance the accessibility experience with custom `aria-valuetext`:
```svelte
{
if (value === 0) return "No rating selected";
return `${value} out of ${max} stars. ${value >= 4 ? "Excellent" : value >= 3 ? "Good" : "Fair"} rating.`;
}}
>
```
## API Reference
### RatingGroup. Root
The rating group component used to group rating items under a common name for form submission.
| Property | Type | Description |
| -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `value` $bindable | `number` | The value of the rating group. You can bind to this value to control the rating group's value from outside the component.`Default: 0` |
| `onValueChange` | `function`- (value: number) => void | A callback that is fired when the rating group's value changes.`Default: undefined` |
| `disabled` | `boolean` | Whether or not the radio group is disabled. This prevents the user from interacting with it.`Default: false` |
| `required` | `boolean` | Whether or not the radio group is required.`Default: false` |
| `name` | `string` | The name of the rating group used in form submission. If provided, a hidden input element will be rendered to submit the value of the rating group.`Default: undefined` |
| `min` | `number` | The minimum value of the rating group.`Default: 0` |
| `max` | `number` | The maximum value of the rating group.`Default: 5` |
| `allowHalf` | `boolean` | Whether or not the rating group allows half values.`Default: false` |
| `readonly` | `boolean` | Whether or not the rating group is readonly.`Default: false` |
| `orientation` | `enum`- 'vertical' \| 'horizontal' | The orientation of the rating group. This will determine how keyboard navigation will work within the component.`Default: 'horizontal'` |
| `hoverPreview` | `boolean` | Whether or not the rating group shows a preview of the rating when hovering over the items.`Default: false` |
| `aria-valuetext` | `union`- string \| (value: number, max: number) =\> string | The text that describes the rating group's value.`` Default: `${value} out of ${max}` `` |
| `ref` $bindable | `HTMLDivElement` | The underlying DOM element being rendered. You can bind to this to get a reference to the element.`Default: undefined` |
| `children` | `Snippet`- Snippet | The children content to render.`Default: undefined` |
| `child` | `Snippet`- type SnippetProps = { props: Record\; }; | Use render delegation to render your own element. See [Child Snippet](/docs/child-snippet) docs for more information.`Default: undefined` | | Data Attribute | Value | Description |
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `data-orientation` | `enum`- '' | The orientation of the rating group. |
| `data-disabled` | `''` | Present when the rating group is disabled. |
| `data-readonly` | `''` | Present when the rating group is readonly. |
| `data-rating-group-root` | `''` | Present on the root element. |
### RatingGroup. Item
An rating item, which must be a child of the `RatingGroup.Root` component.
| Property | Type | Description |
| ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `index` required | `number` | The index of the rating item.`Default: undefined` |
| `disabled` | `boolean` | Whether the rating item is disabled.`Default: false` |
| `ref` $bindable | `HTMLDivElement` | The underlying DOM element being rendered. You can bind to this to get a reference to the element.`Default: undefined` |
| `children` | `Snippet`- Snippet | The children content to render.`Default: undefined` |
| `child` | `Snippet`- type SnippetProps = { props: Record\; }; | Use render delegation to render your own element. See [Child Snippet](/docs/child-snippet) docs for more information.`Default: undefined` | | Data Attribute | Value | Description |
| -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `data-disabled` | `''` | Present when the rating group is disabled. |
| `data-readonly` | `''` | Present when the rating group is readonly. |
| `data-value` | `''` | The value of the rating item. |
| `data-state` | `enum`- '' | The rating item's checked state. |
| `data-orientation` | `enum`- '' | The orientation of the parent rating group. |
| `data-rating-group-item` | `''` | Present on the rating item element. |