smooth_line_chart 0.0.4 copy "smooth_line_chart: ^0.0.4" to clipboard
smooth_line_chart: ^0.0.4 copied to clipboard

The simplest way to add stunning line charts to your Flutter app. Smooth bezier curves, tap/hover tooltips, dark mode, gradient fill, async data loading — all with zero dependencies.

example/lib/main.dart

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

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'smooth_line_chart demo',
      theme: ThemeData(useMaterial3: true),
      home: const DemoPage(),
    );
  }
}

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

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  static const _x = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
  static const _y = [120000.0, 340000.0, 210000.0, 480000.0, 390000.0, 520000.0];
  static const _qty = [12, 34, 21, 48, 39, 52];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('smooth_line_chart demo')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [

            _section('Basic usage'),
            SmoothLineChart(
              xValues: _x,
              yValues: _y,
              qtyValues: _qty,
              title: 'Monthly Revenue',
              labelFormatter: (v) => 'Rp ${shortNumber(v)}',
              qtyFormatter: (q) => 'Orders: $q',
            ),

            _section('onPointTap — bottom sheet'),
            SmoothLineChart(
              xValues: _x,
              yValues: _y,
              qtyValues: _qty,
              title: 'Tap a point to see detail',
              labelFormatter: (v) => 'Rp ${shortNumber(v)}',
              // onPointTap gives you: index, x label, y value, qty, date range
              // Use context from the StatefulWidget to show dialogs/sheets
              onPointTap: (i, x, y, qty, range) {
                showModalBottomSheet(
                  context: context,
                  builder: (_) => _PointDetailSheet(
                    x: x,
                    y: y,
                    qty: qty,
                  ),
                );
              },
            ),

            _section('Gradient fill + dots + value labels'),
            SmoothLineChart(
              xValues: _x,
              yValues: _y,
              title: 'All visual extras',
              labelFormatter: (v) => shortNumber(v),
              theme: const ChartTheme(
                lineColor: Color(0xFF6366F1),
                fillGradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [Color(0x556366F1), Colors.transparent],
                ),
                showDots: true,
                dotRadius: 4,
                showValueLabels: true,
                valueLabelStyle: TextStyle(
                  fontSize: 10,
                  fontWeight: FontWeight.w600,
                  color: Color(0xFF6366F1),
                ),
              ),
            ),

            _section('yMin — high baseline data'),
            SmoothLineChart(
              xValues: _x,
              yValues: const [400000, 420000, 390000, 450000, 430000, 470000],
              title: 'Without yMin (chart looks flat)',
              labelFormatter: (v) => shortNumber(v),
            ),
            const SizedBox(height: 16),
            SmoothLineChart(
              xValues: _x,
              yValues: const [400000, 420000, 390000, 450000, 430000, 470000],
              title: 'With yMin: 350000 (variations visible)',
              yMin: 350000,
              labelFormatter: (v) => shortNumber(v),
            ),

            _section('Empty state'),
            SmoothLineChart(
              xValues: const [],
              yValues: const [],
              title: 'Default empty state',
              labelFormatter: (v) => shortNumber(v),
            ),
            const SizedBox(height: 16),
            SmoothLineChart(
              xValues: const [],
              yValues: const [],
              title: 'Custom empty state',
              labelFormatter: (v) => shortNumber(v),
              emptyWidget: Container(
                height: 120,
                decoration: BoxDecoration(
                  color: Colors.grey.shade100,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: const Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Icon(Icons.bar_chart_outlined, size: 32, color: Colors.grey),
                      SizedBox(height: 8),
                      Text('Belum ada data bulan ini',
                          style: TextStyle(color: Colors.grey)),
                    ],
                  ),
                ),
              ),
            ),

            _section('Card styling — background + border radius'),
            SmoothLineChart(
              xValues: _x,
              yValues: _y,
              title: 'Revenue',
              labelFormatter: (v) => shortNumber(v),
              backgroundColor: const Color(0xFFF0F0FF),
              borderRadius: 16,
            ),

            _section('Dark theme + padding'),
            SmoothLineChart(
              xValues: _x,
              yValues: _y,
              title: 'Revenue',
              theme: ChartTheme.dark,
              labelFormatter: (v) => shortNumber(v),
              backgroundColor: const Color(0xFF111827),
              borderRadius: 16,
              padding: const EdgeInsets.all(16),
              height: 200,
            ),

            _section('Tooltip with arrow'),
            SmoothLineChart(
              xValues: _x,
              yValues: _y,
              title: 'Revenue',
              labelFormatter: (v) => 'Rp ${shortNumber(v)}',
              tooltipArrow: true,
            ),

            _section('Async + range selector'),
            SmoothLineChartAsync(
              title: 'Sales Analysis',
              initialRange: '1M',
              rangeOptions: const [
                RangeOption(label: '1W', value: '1W'),
                RangeOption(label: '1M', value: '1M'),
                RangeOption(label: '3M', value: '3M'),
                RangeOption(label: '6M', value: '6M'),
                // RangeOption(label: '1Y', value: '1Y'),
              ],
              dataLoader: (range) async {
                await Future.delayed(const Duration(milliseconds: 600));
                return _mockData(range);
              },
              onRangeChanged: (range) => debugPrint('Range changed: $range'),
              labelFormatter: (v) => 'Rp ${shortNumber(v)}',
            ),

            const SizedBox(height: 32),
          ],
        ),
      ),
    );
  }

  Widget _section(String title) => Padding(
        padding: const EdgeInsets.only(top: 32, bottom: 8),
        child: Text(title,
            style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
      );

  static ChartData _mockData(String range) {

    return switch (range) {
      '1W' => ChartData(
          xValues: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
          yValues: [50000, 75000, 62000, 90000, 88000, 110000, 95000],
        ),
      '1M' => ChartData(
          xValues: ['W1', 'W2', 'W3', 'W4'],
          yValues: [350000, 420000, 390000, 510000],
        ),
      '3M' => ChartData(
          xValues: ['Jan', 'Feb', 'Mar'],
          yValues: [1200000, 1500000, 1350000],
        ),
      '6M' => ChartData(
          xValues: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
          yValues: [1200000, 1500000, 1350000, 1700000, 1600000, 1900000],
        ),
      _ => ChartData(
          xValues: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
          yValues: [1200000, 1500000, 1350000, 1700000, 1600000, 1900000,
                    2100000, 1950000, 2200000, 2400000, 2300000, 2600000],
        ),
    };
  }
}

class _PointDetailSheet extends StatelessWidget {
  const _PointDetailSheet({required this.x, required this.y, this.qty});
  final String x;
  final double y;
  final int? qty;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(24),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(x, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          const SizedBox(height: 8),
          Text('Revenue: Rp ${shortNumber(y)}',
              style: const TextStyle(fontSize: 16)),
          if (qty != null) ...[
            const SizedBox(height: 4),
            Text('Orders: $qty', style: const TextStyle(fontSize: 16)),
          ],
          const SizedBox(height: 16),
          SizedBox(
            width: double.infinity,
            child: FilledButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('Close'),
            ),
          ),
        ],
      ),
    );
  }
}
2
likes
0
points
17
downloads

Publisher

unverified uploader

Weekly Downloads

The simplest way to add stunning line charts to your Flutter app. Smooth bezier curves, tap/hover tooltips, dark mode, gradient fill, async data loading — all with zero dependencies.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on smooth_line_chart