SELECTION CONTROLS

Star Rating

A single, reusable Flutter star rating that works both ways — tap a star to set a whole-number rating, or render a read-only bar that shows half stars for fractional averages. Filled stars use the house lavender, empty stars a hairline grey, and the star size is a single parameter. No external packages, fully DartPad-ready.

ratingstarsreview
Preview7 variants

1 star

3 stars

5 stars

What's Included

  • Tap-to-rate — tapping a star sets a whole-number value
  • Read-only mode that renders half stars for averages
  • Lavender filled stars, hairline-grey empties
  • Configurable star count (default 5) and pixel size
  • Rounded star glyphs from the Material icon set
  • One AppStarRating widget driven by a value + onChanged

Use Cases

  • Collecting a product or app review rating
  • Showing an average rating (4.5★) read-only on a card
  • Difficulty or satisfaction pickers in a form
  • Any 1–5 (or 1–N) score capture or display

PRO TIP

Let users tap to set whole stars, but display fractional averages with half stars so a 4.3 average never rounds away its nuance. Keep the interactive size at least 40px wide per star for a comfortable tap target, and shrink to a compact read-only size when the rating is just being shown alongside other content.

Complete Dart Code

Copy this into your Flutter project. No external packages required.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double _rating = 3;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: const Color(0xFFFAFAFB),
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              AppStarRating(
                value: _rating,
                onChanged: (v) => setState(() => _rating = v.toDouble()),
              ),
              const SizedBox(height: 24),
              const AppStarRating(value: 4.5, size: 20, readOnly: true),
            ],
          ),
        ),
      ),
    );
  }
}

/// FlutterKit Star Rating — house design system (Linear lavender, light).
/// Tap to rate, or render read-only with half stars for averages.
/// rohansurve.in/flutterkit/star-rating

class AppStarRating extends StatelessWidget {
  const AppStarRating({
    super.key,
    required this.value,
    this.onChanged,
    this.count = 5,
    this.size = 28,
    this.readOnly = false,
  });

  /// Current rating (supports halves in read-only mode).
  final double value;

  /// Called with the tapped star (1..count). Null = read-only.
  final ValueChanged<int>? onChanged;

  /// Number of stars.
  final int count;

  /// Star size in logical pixels.
  final double size;

  /// Force a non-interactive bar.
  final bool readOnly;

  // ── House tokens — docs/flutterkit-design.md §1 ──
  static const Color _accent = Color(0xFF5E6AD2);
  static const Color _empty = Color(0xFFD5D8DD);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: List.generate(count, (i) {
        final pos = i + 1;
        late final IconData icon;
        if (value >= pos) {
          icon = Icons.star_rounded;
        } else if (value >= pos - 0.5) {
          icon = Icons.star_half_rounded;
        } else {
          icon = Icons.star_outline_rounded;
        }
        final filled = value >= pos - 0.5;
        final star = Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: Icon(icon, size: size, color: filled ? _accent : _empty),
        );
        if (readOnly || onChanged == null) return star;
        return GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () => onChanged!(pos),
          child: star,
        );
      }),
    );
  }
}

// ── Usage ──
// AppStarRating(value: v, onChanged: (n) {})                       // tap to rate
// const AppStarRating(value: 4.5, readOnly: true)                  // read-only
// const AppStarRating(value: 3, count: 5, size: 20)                // compact

How to use this widget

  1. 1Copy the complete Dart code above
  2. 2Create a new file — app_star_rating.dart in your Flutter project
  3. 3Use AppStarRating(value: v, onChanged: (n) {}) — switch the look with the count, size, and readOnly parameters

Related components

Selection Controls

Slider

Themed value slider — lavender track, optional value bubble, discrete steps & disabled

View component →
Selection Controls

Quantity Selector

Minus / value / plus stepper — bounded min & max, disabled ends, touch-sized buttons

View component →
Selection Controls

Choice Chips

Single-select chip group — lavender selected chip, pill shape, wraps across lines

View component →