thinking_orbs 0.1.0 copy "thinking_orbs: ^0.1.0" to clipboard
thinking_orbs: ^0.1.0 copied to clipboard

Dotted thought-orb loading indicators for AI & agent UIs — six tuned states, two sizes, auto dark/light. A Dart/Flutter reimplementation of Jakub Antalik's thinking-orbs.

example/lib/main.dart

// Playground for the thinking_orbs package — mirrors the original
// thinking-orbs demo: all six states at both tuned sizes, with theme
// toggle, speed slider and play/pause.

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

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

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

  @override
  State<OrbsPlaygroundApp> createState() => _OrbsPlaygroundAppState();
}

class _OrbsPlaygroundAppState extends State<OrbsPlaygroundApp> {
  bool _dark = true;
  double _speed = 1;
  bool _paused = false;

  static const _labels = {
    OrbState.working: 'working',
    OrbState.searching: 'searching',
    OrbState.solving: 'solving',
    OrbState.listening: 'listening',
    OrbState.composing: 'composing',
    OrbState.shaping: 'shaping',
  };

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'thinking_orbs',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        brightness: _dark ? Brightness.dark : Brightness.light,
        scaffoldBackgroundColor: _dark ? const Color(0xFF09090B) : const Color(0xFFFAFAFA),
        useMaterial3: true,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('thinking_orbs'),
          backgroundColor: Colors.transparent,
          actions: [
            IconButton(
              tooltip: _paused ? 'Play' : 'Pause',
              icon: Icon(_paused ? Icons.play_arrow : Icons.pause),
              onPressed: () => setState(() => _paused = !_paused),
            ),
            IconButton(
              tooltip: _dark ? 'Light mode' : 'Dark mode',
              icon: Icon(_dark ? Icons.light_mode : Icons.dark_mode),
              onPressed: () => setState(() => _dark = !_dark),
            ),
          ],
        ),
        body: SafeArea(
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 24),
                child: Row(
                  children: [
                    const Text('speed'),
                    Expanded(
                      child: Slider(
                        value: _speed,
                        min: 0.25,
                        max: 3,
                        divisions: 11,
                        label: '${_speed.toStringAsFixed(2)}x',
                        onChanged: (v) => setState(() => _speed = v),
                      ),
                    ),
                    Text('${_speed.toStringAsFixed(2)}x'),
                  ],
                ),
              ),
              Expanded(
                child: GridView.count(
                  crossAxisCount: 2,
                  padding: const EdgeInsets.all(16),
                  mainAxisSpacing: 16,
                  crossAxisSpacing: 16,
                  children: [
                    for (final state in OrbState.values)
                      _OrbCard(
                        state: state,
                        label: _labels[state]!,
                        theme: _dark ? OrbTheme.dark : OrbTheme.light,
                        speed: _speed,
                        paused: _paused,
                        dark: _dark,
                      ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _OrbCard extends StatelessWidget {
  const _OrbCard({
    required this.state,
    required this.label,
    required this.theme,
    required this.speed,
    required this.paused,
    required this.dark,
  });

  final OrbState state;
  final String label;
  final OrbTheme theme;
  final double speed;
  final bool paused;
  final bool dark;

  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: dark ? const Color(0xFF27272A) : const Color(0xFFE4E4E7),
        ),
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              ThinkingOrb(
                state: state,
                size: OrbSize.size64,
                theme: theme,
                speed: speed,
                paused: paused,
              ),
              const SizedBox(width: 20),
              ThinkingOrb(
                state: state,
                size: OrbSize.size20,
                theme: theme,
                speed: speed,
                paused: paused,
              ),
            ],
          ),
          const SizedBox(height: 12),
          Text(
            label,
            style: TextStyle(
              fontSize: 13,
              color: dark ? const Color(0xFFA1A1AA) : const Color(0xFF71717A),
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
160
points
773
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Dotted thought-orb loading indicators for AI & agent UIs — six tuned states, two sizes, auto dark/light. A Dart/Flutter reimplementation of Jakub Antalik's thinking-orbs.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

flutter

More

Packages that depend on thinking_orbs