# 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.

{#snippet children({ items })} {#each items as item (item.index)} {/each} {/snippet}

Rating: {value} out of 5 stars

``` ## 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
{#snippet children({ items })} {#each items as item (item.index)} {#if item.state === "active"}{:else}{/if} {/each} {/snippet}
``` In RTL mode, the arrow key navigation is automatically reversed to match the visual direction. ```svelte

(RTL)

Rating group with right-to-left text direction.

{#snippet children({ items })} {#each items as item (item.index)} {#if item.state === "partial"} {:else if item.state === "active"} {:else} {/if} {/each} {/snippet}

: {value} 5

``` ## 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. |