Skip to content

Commit

Permalink
feat: add theme mode switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
dtscalac committed Jun 24, 2024
1 parent cd064ad commit 283aa3b
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 48 deletions.
62 changes: 62 additions & 0 deletions catalyst_voices/uikit_example/lib/examples_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'dart:async';

import 'package:catalyst_voices/widgets/menu/voices_list_tile.dart';
import 'package:flutter/material.dart';
import 'package:uikit_example/examples/voices_chip_example.dart';
import 'package:uikit_example/examples/voices_navigation_example.dart';

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

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('UI kit examples'),
),
body: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 32),
itemCount: examples.length,
itemBuilder: (context, index) => examples[index],
separatorBuilder: (context, index) => const Divider(),
),
);
}

static List<ExampleTile> get examples {
return const [
ExampleTile(
title: 'VoicesNavigation (AppBar + Drawer)',
route: VoicesNavigationExample.route,
page: VoicesNavigationExample(),
),
ExampleTile(
title: 'Voices Chips',
route: VoicesChipExample.route,
page: VoicesChipExample(),
),
];
}
}

class ExampleTile extends StatelessWidget {
final String title;
final String route;
final Widget page;

const ExampleTile({
super.key,
required this.title,
required this.route,
required this.page,
});

@override
Widget build(BuildContext context) {
return VoicesListTile(
title: Text(title),
trailing: const Icon(Icons.chevron_right),
onTap: () => unawaited(Navigator.of(context).pushNamed(route)),
);
}
}
112 changes: 64 additions & 48 deletions catalyst_voices/uikit_example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import 'dart:async';

import 'package:catalyst_voices/widgets/menu/voices_list_tile.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:catalyst_voices_localization/generated/catalyst_voices_localizations.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localized_locales/flutter_localized_locales.dart';
import 'package:uikit_example/examples/voices_chip_example.dart';
import 'package:uikit_example/examples/voices_navigation_example.dart';
import 'package:uikit_example/examples_list.dart';

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

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

@override
State<UIKitExampleApp> createState() => _UIKitExampleAppState();
}

class _UIKitExampleAppState extends State<UIKitExampleApp> {
ThemeMode _themeMode = ThemeMode.system;

@override
Widget build(BuildContext context) {
return MaterialApp(
Expand All @@ -27,63 +30,76 @@ class UIKitExampleApp extends StatelessWidget {
localeListResolutionCallback: basicLocaleListResolution,
theme: ThemeBuilder.buildTheme(BrandKey.catalyst),
darkTheme: ThemeBuilder.buildDarkTheme(BrandKey.catalyst),
routes: {
Navigator.defaultRouteName: (_) => const _ExamplesList(),
VoicesNavigationExample.route: (_) => const VoicesNavigationExample(),
VoicesChipExample.route: (_) => const VoicesChipExample(),
},
themeMode: _themeMode,
onGenerateRoute: _onGenerateRoute,
);
}
}

class _ExamplesList extends StatelessWidget {
const _ExamplesList();
Route<dynamic> _onGenerateRoute(RouteSettings settings) {
final page = ExamplesListPage.examples
.where((e) => e.route == settings.name)
.map((e) => e.page)
.firstOrNull ??
const ExamplesListPage();

@override
Widget build(BuildContext context) {
final examples = _examples;
return Scaffold(
appBar: AppBar(
title: const Text('UI kit examples'),
),
body: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 32),
itemCount: examples.length,
itemBuilder: (context, index) => examples[index],
separatorBuilder: (context, index) => const Divider(),
),
return MaterialPageRoute(
settings: settings,
builder: (_) {
return _ThemeModeSwitcherWrapper(
onChanged: _onThemeModeChanged,
child: page,
);
},
);
}

List<_Example> get _examples {
return const [
_Example(
title: 'VoicesNavigation (AppBar + Drawer)',
route: VoicesNavigationExample.route,
),
_Example(
title: 'Voices Chips',
route: VoicesChipExample.route,
),
];
void _onThemeModeChanged(ThemeMode themeMode) {
setState(() {
_themeMode = themeMode;
});
}
}

class _Example extends StatelessWidget {
final String title;
final String route;
class _ThemeModeSwitcherWrapper extends StatelessWidget {
final ValueChanged<ThemeMode> onChanged;
final Widget child;

const _Example({
required this.title,
required this.route,
const _ThemeModeSwitcherWrapper({
required this.onChanged,
required this.child,
});

@override
Widget build(BuildContext context) {
return VoicesListTile(
title: Text(title),
trailing: const Icon(Icons.chevron_right),
onTap: () => unawaited(Navigator.of(context).pushNamed(route)),
return Column(
children: [
Expanded(
child: child,
),
Material(
color: Theme.of(context).colorScheme.surface,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Text('Light / Dark'),
Padding(
padding: const EdgeInsets.only(left: 8),
child: Switch(
value: Theme.of(context).brightness == Brightness.dark,
onChanged: (value) {
onChanged(
value ? ThemeMode.dark : ThemeMode.light,
);
},
),
),
],
),
),
),
],
);
}
}

0 comments on commit 283aa3b

Please sign in to comment.