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

App theme selection (mode + flavor) as a Juice bloc, with optional persistence behind a swappable seam.

example/lib/main.dart

import 'package:juice/juice.dart';
import 'package:juice_theme/juice_theme.dart';

/// In-memory persistence so the demo runs with no storage plugin. Swap for
/// `StorageThemePersistence(storageBloc)` in a real app.
class InMemoryThemePersistence implements ThemePersistence {
  ThemeSelection? _saved;
  @override
  Future<ThemeSelection?> load() async => _saved;
  @override
  Future<void> save(ThemeSelection s) async => _saved = s;
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  BlocScope.register<ThemeBloc>(
    () => ThemeBloc.withConfig(
      ThemeConfig(persistence: InMemoryThemePersistence()),
    ),
    lifecycle: BlocLifecycle.permanent,
  );

  runApp(App());
}

/// The whole MaterialApp rebuilds on theme-mode changes.
class App extends StatelessJuiceWidget<ThemeBloc> {
  App({super.key}) : super(groups: {ThemeGroups.mode});

  @override
  Widget onBuild(BuildContext context, StreamStatus status) {
    return MaterialApp(
      title: 'juice_theme demo',
      debugShowCheckedModeBanner: false,
      themeMode: bloc.state.mode,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.teal,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessJuiceWidget<ThemeBloc> {
  HomeScreen({super.key});

  @override
  Widget onBuild(BuildContext context, StreamStatus status) {
    return Scaffold(
      appBar: AppBar(title: const Text('juice_theme demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Mode: ${bloc.state.mode.name}', key: const Key('mode')),
            const SizedBox(height: 16),
            SegmentedButton<ThemeMode>(
              segments: const [
                ButtonSegment(value: ThemeMode.light, label: Text('Light')),
                ButtonSegment(value: ThemeMode.system, label: Text('System')),
                ButtonSegment(value: ThemeMode.dark, label: Text('Dark')),
              ],
              selected: {bloc.state.mode},
              onSelectionChanged: (s) => bloc.setMode(s.first),
            ),
            const SizedBox(height: 16),
            FilledButton.icon(
              onPressed: bloc.toggle,
              icon: const Icon(Icons.brightness_6),
              label: const Text('Toggle light/dark'),
            ),
          ],
        ),
      ),
    );
  }
}
0
likes
150
points
16
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

App theme selection (mode + flavor) as a Juice bloc, with optional persistence behind a swappable seam.

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#theme #dark-mode #bloc #state-management #appearance

Funding

Consider supporting this project:

github.com

License

MIT (license)

Dependencies

flutter, juice, juice_storage

More

Packages that depend on juice_theme