Simple, zero-dependency star rating component for Svelte.
Using your preferred package manager:
npm i @dev-ekkx/svelte-star-rating
pnpm add @dev-ekkx/svelte-star-rating
bun add @dev-ekkx/svelte-star-rating
Peer dependency:
<script lang="ts">
import { StarRating } from '@dev-ekkx/svelte-star-rating';
// Current rating value (number). You can bind and update it.
let value = 4.4;
// Component config
const config = {
readonly: false,
maxVal: 5,
minVal: 0,
step: 0.1, // allows tenth-star granularity
numOfStars: 5,
starConfig: {
size: 26, // pixels
filledColor: '#F98416',
unfilledColor: '#5D5D5D'
}
};
</script>
<StarRating bind:value {config} />
<script lang="ts">
import { StarRating } from '@dev-ekkx/svelte-star-rating';
let value = 3.7;
const config = {
readonly: true,
minVal: 0,
maxVal: 5,
step: 0.1,
numOfStars: 5,
starConfig: { size: 20, filledColor: '#ffc107', unfilledColor: '#e0e0e0' }
};
</script>
<StarRating {config} bind:value />
Note: when readonly is true, the slider is disabled and the current value is preserved.
Component: StarRating
Types:
export interface StylesI {
/** Inline CSS applied to the outer stars container */
containerStyles?: string;
/** Inline CSS applied to the stars row wrapper */
starStyles?: string;
}
export interface StarConfigI {
size: number;
filledColor: string;
unfilledColor: string;
}
export interface ConfigI {
/** Optional name for the underlying input element; defaults to 'stars' */
name?: string;
readonly: boolean;
numOfStars: number;
minVal: number;
maxVal: number;
step: number;
starConfig: StarConfigI;
/** Optional inline styles for container and stars row */
styles?: StylesI;
}
Behavior notes:
Accessibility:
Use starConfig to control visuals per instance:
Because the component uses inline SVG, colors apply directly and do not require external CSS.
Optional styles object (inline CSS strings):
Example:
<script>
import { StarRating } from '@dev-ekkx/svelte-star-rating';
let value = $state(4.4);
const config = $state<ConfigI>({
name: 'stars',
readonly: false,
maxVal: 5,
minVal: 0,
step: 0.1,
numOfStars: 5,
styles: {
containerStyles: "border: 1px solid red; padding: 8px; border-radius: 8px; width:max-content; gap:0rem; margin-inline: auto",
starStyles: "gap: 0.1rem"
},
starConfig: {
size: 26,
filledColor: '#F98416',
unfilledColor: '#5D5D5D'
}
});
</script>
<StarRating bind:value {config} />
<script>
import { StarRating } from '@dev-ekkx/svelte-star-rating';
let value = 0;
const config = {
readonly: false,
minVal: 0,
maxVal: 5,
step: 1,
numOfStars: 5,
starConfig: { size: 32, filledColor: 'gold', unfilledColor: '#ccc' }
};
</script>
<StarRating bind:value {config} /><p>Your rating: {value}</p>
<script>
import { StarRating } from '@dev-ekkx/svelte-star-rating';
let value = 7.5;
const config = {
readonly: false,
minVal: 0,
maxVal: 10,
step: 0.25,
numOfStars: 10,
starConfig: { size: 18, filledColor: '#4f46e5', unfilledColor: '#e5e7eb' }
};
</script>
<StarRating bind:value {config} />
import { StarRating } from '@dev-ekkx/svelte-star-rating';
MIT License © 2025 Emmanuel Komla Kpendo (Dev Ekkx). See LICENSE file for details.