reis-mobile 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/.claude-plugin/marketplace.json +24 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/CHANGELOG.md +103 -0
  4. package/LICENSE +21 -0
  5. package/README.md +631 -0
  6. package/THIRD_PARTY_NOTICES.md +105 -0
  7. package/agents/flutter-architect.md +92 -0
  8. package/agents/flutter-performance-engineer.md +103 -0
  9. package/agents/flutter-test-engineer.md +100 -0
  10. package/agents/lead-mobile.md +107 -0
  11. package/agents/mobile-code-reviewer.md +66 -0
  12. package/agents/mobile-staff-engineer.md +85 -0
  13. package/agents/plugin-native-expert.md +97 -0
  14. package/bin/reis-mobile.mjs +256 -0
  15. package/commands/debate.md +135 -0
  16. package/commands/doctor.md +23 -0
  17. package/commands/reis-mobile.md +50 -0
  18. package/commands/review.md +53 -0
  19. package/core/config/language.mjs +83 -0
  20. package/core/context/context-engine.mjs +113 -0
  21. package/core/detection/project-probe.mjs +104 -0
  22. package/core/detection/stack-detector.mjs +204 -0
  23. package/core/diagnostics/doctor.mjs +181 -0
  24. package/core/install/claude-plugin.mjs +76 -0
  25. package/core/paths.mjs +4 -0
  26. package/core/registry/frontmatter.mjs +81 -0
  27. package/core/registry/registry.mjs +140 -0
  28. package/core/router/intent-detector.mjs +75 -0
  29. package/core/router/intents.mjs +91 -0
  30. package/core/router/router.mjs +83 -0
  31. package/core/security/redact.mjs +24 -0
  32. package/package.json +35 -0
  33. package/skills/architecture-feature-first/SKILL.md +116 -0
  34. package/skills/bloc/SKILL.md +354 -0
  35. package/skills/code-review/SKILL.md +89 -0
  36. package/skills/dart-3-updates/SKILL.md +223 -0
  37. package/skills/dart-add-unit-test/SKILL.md +126 -0
  38. package/skills/dart-collect-coverage/SKILL.md +145 -0
  39. package/skills/dart-fix-runtime-errors/SKILL.md +170 -0
  40. package/skills/dart-generate-test-mocks/SKILL.md +159 -0
  41. package/skills/dart-migrate-to-checks-package/SKILL.md +532 -0
  42. package/skills/dart-resolve-package-conflicts/SKILL.md +120 -0
  43. package/skills/dart-run-static-analysis/SKILL.md +108 -0
  44. package/skills/dart-use-pattern-matching/SKILL.md +240 -0
  45. package/skills/dart-use-pattern-matching/examples/json_patterns.dart +85 -0
  46. package/skills/detect-mobile-stack/SKILL.md +33 -0
  47. package/skills/effective-dart/SKILL.md +187 -0
  48. package/skills/firebase-ai/SKILL.md +93 -0
  49. package/skills/firebase-analytics/SKILL.md +129 -0
  50. package/skills/firebase-app-check/SKILL.md +124 -0
  51. package/skills/firebase-auth/SKILL.md +224 -0
  52. package/skills/firebase-cloud-firestore/SKILL.md +165 -0
  53. package/skills/firebase-cloud-functions/SKILL.md +148 -0
  54. package/skills/firebase-crashlytics/SKILL.md +182 -0
  55. package/skills/firebase-data-connect/SKILL.md +80 -0
  56. package/skills/firebase-database/SKILL.md +224 -0
  57. package/skills/firebase-in-app-messaging/SKILL.md +111 -0
  58. package/skills/firebase-messaging/SKILL.md +201 -0
  59. package/skills/firebase-remote-config/SKILL.md +131 -0
  60. package/skills/firebase-storage/SKILL.md +158 -0
  61. package/skills/flutter-add-integration-test/SKILL.md +167 -0
  62. package/skills/flutter-add-widget-preview/SKILL.md +149 -0
  63. package/skills/flutter-add-widget-test/SKILL.md +158 -0
  64. package/skills/flutter-adding-home-screen-widgets/SKILL.md +205 -0
  65. package/skills/flutter-animating-apps/SKILL.md +185 -0
  66. package/skills/flutter-app-architecture/SKILL.md +80 -0
  67. package/skills/flutter-apply-architecture-best-practices/SKILL.md +166 -0
  68. package/skills/flutter-build-responsive-layout/SKILL.md +143 -0
  69. package/skills/flutter-building-forms/SKILL.md +125 -0
  70. package/skills/flutter-building-layouts/SKILL.md +131 -0
  71. package/skills/flutter-building-plugins/SKILL.md +209 -0
  72. package/skills/flutter-caching-data/SKILL.md +171 -0
  73. package/skills/flutter-change-notifier/SKILL.md +138 -0
  74. package/skills/flutter-embedding-native-views/SKILL.md +200 -0
  75. package/skills/flutter-errors/SKILL.md +126 -0
  76. package/skills/flutter-fix-layout-issues/SKILL.md +134 -0
  77. package/skills/flutter-handling-concurrency/SKILL.md +182 -0
  78. package/skills/flutter-implement-json-serialization/SKILL.md +157 -0
  79. package/skills/flutter-improving-accessibility/SKILL.md +113 -0
  80. package/skills/flutter-interoperating-with-native-apis/SKILL.md +130 -0
  81. package/skills/flutter-login-usecase/SKILL.md +38 -0
  82. package/skills/flutter-managing-state/SKILL.md +206 -0
  83. package/skills/flutter-project-audit/SKILL.md +66 -0
  84. package/skills/flutter-reducing-app-size/SKILL.md +103 -0
  85. package/skills/flutter-secure-token-store/SKILL.md +35 -0
  86. package/skills/flutter-setting-up-on-macos/SKILL.md +78 -0
  87. package/skills/flutter-setup-declarative-routing/SKILL.md +259 -0
  88. package/skills/flutter-setup-localization/SKILL.md +214 -0
  89. package/skills/flutter-theming-apps/SKILL.md +163 -0
  90. package/skills/flutter-use-http-package/SKILL.md +178 -0
  91. package/skills/flutter-widget-review/SKILL.md +54 -0
  92. package/skills/flutter-working-with-databases/SKILL.md +203 -0
  93. package/skills/flutterfire-configure/SKILL.md +143 -0
  94. package/skills/mobile-security-audit/SKILL.md +101 -0
  95. package/skills/mockito/SKILL.md +149 -0
  96. package/skills/mocktail/SKILL.md +122 -0
  97. package/skills/patrol-e2e-testing/SKILL.md +224 -0
  98. package/skills/provider/SKILL.md +139 -0
  99. package/skills/riverpod/SKILL.md +246 -0
  100. package/skills/testing/SKILL.md +50 -0
  101. package/stacks/android/stack.json +8 -0
  102. package/stacks/flutter/stack.json +8 -0
  103. package/stacks/ios/stack.json +8 -0
  104. package/stacks/kotlin-multiplatform/stack.json +8 -0
  105. package/stacks/react-native/stack.json +8 -0
@@ -0,0 +1,259 @@
1
+ ---
2
+ name: flutter-setup-declarative-routing
3
+ description: Configure `MaterialApp.router` using a package like `go_router` for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Tue, 21 Apr 2026 21:08:03 GMT
7
+ routing: manual
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Implementing Routing and Deep Linking
13
+
14
+ ## Contents
15
+ - [Core Concepts](#core-concepts)
16
+ - [Workflow: Initializing the Application and Router](#workflow-initializing-the-application-and-router)
17
+ - [Workflow: Configuring Platform Deep Linking](#workflow-configuring-platform-deep-linking)
18
+ - [Workflow: Implementing Nested Navigation](#workflow-implementing-nested-navigation)
19
+ - [Examples](#examples)
20
+
21
+ ## Core Concepts
22
+
23
+ Use the `go_router` package for declarative routing in Flutter. It provides a robust API for complex routing scenarios, deep linking, and nested navigation.
24
+
25
+ - **GoRouter**: The central configuration object defining the application's route tree.
26
+ - **GoRoute**: A standard route mapping a URL path to a Flutter screen.
27
+ - **ShellRoute / StatefulShellRoute**: Wraps child routes in a persistent UI shell (e.g., a `BottomNavigationBar`). `StatefulShellRoute` maintains the state of parallel navigation branches.
28
+ - **Path URL Strategy**: Removes the default `#` fragment from web URLs, essential for clean deep linking across platforms.
29
+
30
+ ## Workflow: Initializing the Application and Router
31
+
32
+ Follow this workflow to bootstrap a new Flutter application with `go_router` and configure the root routing mechanism.
33
+
34
+ ### Task Progress
35
+ - [ ] Create the Flutter application.
36
+ - [ ] Add the `go_router` dependency.
37
+ - [ ] Configure the URL strategy for web/deep linking.
38
+ - [ ] Implement the `GoRouter` configuration.
39
+ - [ ] Bind the router to `MaterialApp.router`.
40
+
41
+ ### 1. Scaffold the Application
42
+ Run the following commands to create the app and add the required routing package:
43
+ ```bash
44
+ flutter create <app-name>
45
+ cd <app-name>
46
+ flutter pub add go_router
47
+ ```
48
+
49
+ ### 2. Configure the Router
50
+ Define a top-level `GoRouter` instance. Handle authentication or state-based routing using the `redirect` parameter.
51
+
52
+ ```dart
53
+ import 'package:flutter/material.dart';
54
+ import 'package:go_router/go_router.dart';
55
+ import 'package:flutter_web_plugins/url_strategy.dart';
56
+
57
+ void main() {
58
+ // Use path URL strategy to remove the '#' from web URLs
59
+ usePathUrlStrategy();
60
+ runApp(const MyApp());
61
+ }
62
+
63
+ final GoRouter _router = GoRouter(
64
+ initialLocation: '/',
65
+ routes: [
66
+ GoRoute(
67
+ path: '/',
68
+ builder: (context, state) => const HomeScreen(),
69
+ routes: [
70
+ GoRoute(
71
+ path: 'details/:id',
72
+ builder: (context, state) => DetailsScreen(id: state.pathParameters['id']!),
73
+ ),
74
+ ],
75
+ ),
76
+ ],
77
+ errorBuilder: (context, state) => ErrorScreen(error: state.error),
78
+ );
79
+
80
+ class MyApp extends StatelessWidget {
81
+ const MyApp({super.key});
82
+
83
+ @override
84
+ Widget build(BuildContext context) {
85
+ return MaterialApp.router(
86
+ routerConfig: _router,
87
+ title: 'Routing App',
88
+ );
89
+ }
90
+ }
91
+ ```
92
+
93
+ ## Workflow: Configuring Platform Deep Linking
94
+
95
+ Configure the native platforms to intercept specific URLs and route them into the Flutter application.
96
+
97
+ ### Task Progress
98
+ - [ ] Determine target platforms (iOS, Android, or both).
99
+ - [ ] Apply conditional configuration for Android (Manifest + Asset Links).
100
+ - [ ] Apply conditional configuration for iOS (Plist + Entitlements + AASA).
101
+ - [ ] Run validator -> review errors -> fix.
102
+
103
+ ### If configuring for Android:
104
+ 1. **Modify `AndroidManifest.xml`**: Add the intent filter inside the `<activity>` tag for `.MainActivity`.
105
+ ```xml
106
+ <intent-filter android:autoVerify="true">
107
+ <action android:name="android.intent.action.VIEW" />
108
+ <category android:name="android.intent.category.DEFAULT" />
109
+ <category android:name="android.intent.category.BROWSABLE" />
110
+ <data android:scheme="http" android:host="yourdomain.com" />
111
+ <data android:scheme="https" />
112
+ </intent-filter>
113
+ ```
114
+ 2. **Host `assetlinks.json`**: Serve the following JSON at `https://yourdomain.com/.well-known/assetlinks.json`.
115
+ ```json
116
+ [{
117
+ "relation": ["delegate_permission/common.handle_all_urls"],
118
+ "target": {
119
+ "namespace": "android_app",
120
+ "package_name": "com.yourcompany.yourapp",
121
+ "sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"]
122
+ }
123
+ }]
124
+ ```
125
+
126
+ ### If configuring for iOS:
127
+ 1. **Modify `Info.plist`**: Opt-in to Flutter's default deep link handler.
128
+ *Note: If using a third-party deep linking plugin (e.g., `app_links`), set this to `NO` to prevent conflicts.*
129
+ ```xml
130
+ <key>FlutterDeepLinkingEnabled</key>
131
+ <true/>
132
+ ```
133
+ 2. **Modify `Runner.entitlements`**: Add the associated domain.
134
+ ```xml
135
+ <key>com.apple.developer.associated-domains</key>
136
+ <array>
137
+ <string>applinks:yourdomain.com</string>
138
+ </array>
139
+ ```
140
+ 3. **Host `apple-app-site-association`**: Serve the following JSON (without a `.json` extension) at `https://yourdomain.com/.well-known/apple-app-site-association`.
141
+ ```json
142
+ {
143
+ "applinks": {
144
+ "apps": [],
145
+ "details": [{
146
+ "appIDs": ["TEAM_ID.com.yourcompany.yourapp"],
147
+ "paths": ["*"],
148
+ "components": [{"/": "/*"}]
149
+ }]
150
+ }
151
+ }
152
+ ```
153
+
154
+ ### Validation Loop
155
+ Run validator -> review errors -> fix.
156
+ - **Android**: Test using ADB.
157
+ ```bash
158
+ adb shell 'am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://yourdomain.com/details/123"' com.yourcompany.yourapp
159
+ ```
160
+ - **iOS**: Test using `xcrun` on a booted simulator.
161
+ ```bash
162
+ xcrun simctl openurl booted https://yourdomain.com/details/123
163
+ ```
164
+
165
+ ## Workflow: Implementing Nested Navigation
166
+
167
+ Use `StatefulShellRoute` to implement persistent UI shells (like a bottom navigation bar) that maintain the state of their child routes.
168
+
169
+ ### Task Progress
170
+ - [ ] Define `StatefulShellRoute.indexedStack` in the `GoRouter` configuration.
171
+ - [ ] Create `StatefulShellBranch` instances for each navigation tab.
172
+ - [ ] Implement the shell widget using `StatefulNavigationShell`.
173
+
174
+ ```dart
175
+ final GoRouter _router = GoRouter(
176
+ initialLocation: '/home',
177
+ routes: [
178
+ StatefulShellRoute.indexedStack(
179
+ builder: (context, state, navigationShell) {
180
+ return ScaffoldWithNavBar(navigationShell: navigationShell);
181
+ },
182
+ branches: [
183
+ StatefulShellBranch(
184
+ routes: [
185
+ GoRoute(
186
+ path: '/home',
187
+ builder: (context, state) => const HomeScreen(),
188
+ ),
189
+ ],
190
+ ),
191
+ StatefulShellBranch(
192
+ routes: [
193
+ GoRoute(
194
+ path: '/settings',
195
+ builder: (context, state) => const SettingsScreen(),
196
+ ),
197
+ ],
198
+ ),
199
+ ],
200
+ ),
201
+ ],
202
+ );
203
+ ```
204
+
205
+ ## Examples
206
+
207
+ ### High-Fidelity Shell Widget Implementation
208
+ Implement the UI shell that consumes the `StatefulNavigationShell` to handle branch switching.
209
+
210
+ ```dart
211
+ class ScaffoldWithNavBar extends StatelessWidget {
212
+ const ScaffoldWithNavBar({
213
+ required this.navigationShell,
214
+ super.key,
215
+ });
216
+
217
+ final StatefulNavigationShell navigationShell;
218
+
219
+ void _goBranch(int index) {
220
+ navigationShell.goBranch(
221
+ index,
222
+ // Support navigating to the initial location when tapping the active tab.
223
+ initialLocation: index == navigationShell.currentIndex,
224
+ );
225
+ }
226
+
227
+ @override
228
+ Widget build(BuildContext context) {
229
+ return Scaffold(
230
+ body: navigationShell,
231
+ bottomNavigationBar: NavigationBar(
232
+ selectedIndex: navigationShell.currentIndex,
233
+ onDestinationSelected: _goBranch,
234
+ destinations: const [
235
+ NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
236
+ NavigationDestination(icon: Icon(Icons.settings), label: 'Settings'),
237
+ ],
238
+ ),
239
+ );
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### Programmatic Navigation
245
+ Use the `context.go()` and `context.push()` extension methods provided by `go_router`.
246
+
247
+ ```dart
248
+ // Replaces the current route stack with the target route (Declarative)
249
+ context.go('/details/123');
250
+
251
+ // Pushes the target route onto the existing stack (Imperative)
252
+ context.push('/details/123');
253
+
254
+ // Navigates using a named route and path parameters
255
+ context.goNamed('details', pathParameters: {'id': '123'});
256
+
257
+ // Pops the current route
258
+ context.pop();
259
+ ```
@@ -0,0 +1,214 @@
1
+ ---
2
+ name: flutter-setup-localization
3
+ description: Add `flutter_localizations` and `intl` dependencies, enable "generate true" in `pubspec.yaml`, and create an `l10n.yaml` configuration file. Use when initializing localization support for a new Flutter project.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Tue, 21 Apr 2026 21:27:35 GMT
7
+ routing: manual
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Internationalizing Flutter Applications
13
+
14
+ ## Contents
15
+ - [Core Concepts](#core-concepts)
16
+ - [Setup Workflow](#setup-workflow)
17
+ - [Implementation Workflow](#implementation-workflow)
18
+ - [Advanced Formatting](#advanced-formatting)
19
+ - [Examples](#examples)
20
+
21
+ ## Core Concepts
22
+ Flutter handles internationalization (i18n) and localization (l10n) via the `flutter_localizations` and `intl` packages. The standard approach uses App Resource Bundle (`.arb`) files to define localized strings, which are then compiled into a generated `AppLocalizations` class for type-safe access within the widget tree.
23
+
24
+ ## Setup Workflow
25
+
26
+ Copy and track this checklist when initializing internationalization in a Flutter project:
27
+
28
+ - [ ] **Task Progress**
29
+ - [ ] 1. Add dependencies to `pubspec.yaml`.
30
+ - [ ] 2. Enable the `generate` flag.
31
+ - [ ] 3. Create the `l10n.yaml` configuration file.
32
+ - [ ] 4. Configure `MaterialApp` or `CupertinoApp`.
33
+
34
+ ### 1. Add Dependencies
35
+ Add the required localization packages to the project. Execute the following commands in the terminal:
36
+ ```bash
37
+ flutter pub add flutter_localizations --sdk=flutter
38
+ flutter pub add intl:any
39
+ ```
40
+
41
+ Verify your `pubspec.yaml` includes the following under `dependencies`:
42
+ ```yaml
43
+ dependencies:
44
+ flutter:
45
+ sdk: flutter
46
+ flutter_localizations:
47
+ sdk: flutter
48
+ intl: any
49
+ ```
50
+
51
+ ### 2. Enable Code Generation
52
+ Open `pubspec.yaml` and enable the `generate` flag within the `flutter` section to automate localization tasks:
53
+ ```yaml
54
+ flutter:
55
+ generate: true
56
+ ```
57
+
58
+ ### 3. Create Configuration File
59
+ Create a new file named `l10n.yaml` in the root directory of the Flutter project. Define the input directory, template file, and output file:
60
+ ```yaml
61
+ arb-dir: lib/l10n
62
+ template-arb-file: app_en.arb
63
+ output-localization-file: app_localizations.dart
64
+ synthetic-package: true
65
+ ```
66
+
67
+ ### 4. Configure the App Entry Point
68
+ Import the generated localizations and the `flutter_localizations` library in your `main.dart`. Inject the delegates and supported locales into your `MaterialApp` or `CupertinoApp`.
69
+
70
+ ```dart
71
+ import 'package:flutter_localizations/flutter_localizations.dart';
72
+ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // Adjust path if synthetic-package is false
73
+
74
+ // ... inside build method
75
+ return MaterialApp(
76
+ localizationsDelegates: const [
77
+ AppLocalizations.delegate,
78
+ GlobalMaterialLocalizations.delegate,
79
+ GlobalWidgetsLocalizations.delegate,
80
+ GlobalCupertinoLocalizations.delegate,
81
+ ],
82
+ supportedLocales: const [
83
+ Locale('en'), // English
84
+ Locale('es'), // Spanish
85
+ ],
86
+ home: const MyHomePage(),
87
+ );
88
+ ```
89
+
90
+ ## Implementation Workflow
91
+
92
+ Follow this workflow when adding or modifying localized content.
93
+
94
+ ### 1. Define ARB Files
95
+ * **If creating NEW content:** Add the base string to the template file (`lib/l10n/app_en.arb`). Include a description for context.
96
+ * **If EDITING existing content:** Locate the key in all supported `.arb` files and update the values.
97
+
98
+ ```json
99
+ {
100
+ "helloWorld": "Hello World!",
101
+ "@helloWorld": {
102
+ "description": "The conventional newborn programmer greeting"
103
+ }
104
+ }
105
+ ```
106
+
107
+ Create corresponding files for other locales (e.g., `app_es.arb`):
108
+ ```json
109
+ {
110
+ "helloWorld": "¡Hola Mundo!"
111
+ }
112
+ ```
113
+
114
+ ### 2. Generate Localization Classes
115
+ Run the following command to trigger code generation:
116
+ ```bash
117
+ flutter pub get
118
+ ```
119
+ *Feedback Loop:* Run validator -> review terminal output for ARB syntax errors -> fix missing commas or mismatched placeholders -> re-run `flutter pub get`.
120
+
121
+ ### 3. Consume Localized Strings
122
+ Access the localized strings in your widget tree using `AppLocalizations.of(context)`. Ensure the widget calling this is a descendant of `MaterialApp`.
123
+
124
+ ```dart
125
+ Text(AppLocalizations.of(context)!.helloWorld)
126
+ ```
127
+
128
+ ## Advanced Formatting
129
+
130
+ Use placeholders for dynamic data, plurals, and conditional selects.
131
+
132
+ ### Placeholders
133
+ Define parameters within curly braces and specify their type in the metadata object.
134
+ ```json
135
+ "hello": "Hello {userName}",
136
+ "@hello": {
137
+ "description": "A message with a single parameter",
138
+ "placeholders": {
139
+ "userName": {
140
+ "type": "String",
141
+ "example": "Bob"
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### Plurals
148
+ Use the `plural` syntax to handle quantity-based string variations. The `other` case is mandatory.
149
+ ```json
150
+ "nWombats": "{count, plural, =0{no wombats} =1{1 wombat} other{{count} wombats}}",
151
+ "@nWombats": {
152
+ "description": "A plural message",
153
+ "placeholders": {
154
+ "count": {
155
+ "type": "num",
156
+ "format": "compact"
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Selects
163
+ Use the `select` syntax for conditional strings, such as gendered text.
164
+ ```json
165
+ "pronoun": "{gender, select, male{he} female{she} other{they}}",
166
+ "@pronoun": {
167
+ "description": "A gendered message",
168
+ "placeholders": {
169
+ "gender": {
170
+ "type": "String"
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ ## Examples
177
+
178
+ ### Complete `l10n.yaml`
179
+ ```yaml
180
+ arb-dir: lib/l10n
181
+ template-arb-file: app_en.arb
182
+ output-localization-file: app_localizations.dart
183
+ synthetic-package: true
184
+ use-escaping: true
185
+ ```
186
+
187
+ ### Complete Widget Implementation
188
+ ```dart
189
+ import 'package:flutter/material.dart';
190
+ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
191
+
192
+ class GreetingWidget extends StatelessWidget {
193
+ final String userName;
194
+ final int notificationCount;
195
+
196
+ const GreetingWidget({
197
+ super.key,
198
+ required this.userName,
199
+ required this.notificationCount,
200
+ });
201
+
202
+ @override
203
+ Widget build(BuildContext context) {
204
+ final l10n = AppLocalizations.of(context)!;
205
+
206
+ return Column(
207
+ children: [
208
+ Text(l10n.hello(userName)),
209
+ Text(l10n.nWombats(notificationCount)),
210
+ ],
211
+ );
212
+ }
213
+ }
214
+ ```
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: flutter-theming-apps
3
+ description: Customizes the visual appearance of a Flutter app using the theming system. Use when defining global styles, colors, or typography for an application.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Thu, 12 Mar 2026 22:14:47 GMT
7
+ routing: manual
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Implementing Flutter Theming and Adaptive Design
13
+
14
+ ## Contents
15
+ - [Core Theming Concepts](#core-theming-concepts)
16
+ - [Material 3 Guidelines](#material-3-guidelines)
17
+ - [Component Theme Normalization](#component-theme-normalization)
18
+ - [Button Styling](#button-styling)
19
+ - [Platform Idioms & Adaptive Design](#platform-idioms--adaptive-design)
20
+ - [Workflows](#workflows)
21
+ - [Examples](#examples)
22
+
23
+ ## Core Theming Concepts
24
+ Flutter applies styling in a strict hierarchy: styles applied to the specific widget -> themes that override the immediate parent theme -> the main app theme.
25
+
26
+ - Define app-wide themes using the `theme` property of `MaterialApp` with a `ThemeData` instance.
27
+ - Override themes for specific widget subtrees by wrapping them in a `Theme` widget and using `Theme.of(context).copyWith(...)`.
28
+ - **Do not** use deprecated `ThemeData` properties:
29
+ - Replace `accentColor` with `colorScheme.secondary`.
30
+ - Replace `accentTextTheme` with `textTheme` (using `colorScheme.onSecondary` for contrast).
31
+ - Replace `AppBarTheme.color` with `AppBarTheme.backgroundColor`.
32
+
33
+ ## Material 3 Guidelines
34
+ Material 3 is the default theme as of Flutter 3.16.
35
+
36
+ - **Colors:** Generate color schemes using `ColorScheme.fromSeed(seedColor: Colors.blue)`. This ensures accessible contrast ratios.
37
+ - **Elevation:** Material 3 uses `ColorScheme.surfaceTint` to indicate elevation instead of just drop shadows. To revert to M2 shadow behavior, set `surfaceTint: Colors.transparent` and define a `shadowColor`.
38
+ - **Typography:** Material 3 updates font sizes, weights, and line heights. If text wrapping breaks legacy layouts, adjust `letterSpacing` on the specific `TextStyle`.
39
+ - **Modern Components:**
40
+ - Replace `BottomNavigationBar` with `NavigationBar`.
41
+ - Replace `Drawer` with `NavigationDrawer`.
42
+ - Replace `ToggleButtons` with `SegmentedButton`.
43
+ - Use `FilledButton` for a high-emphasis button without the elevation of `ElevatedButton`.
44
+
45
+ ## Component Theme Normalization
46
+ Component themes in `ThemeData` have been normalized to use `*ThemeData` classes rather than `*Theme` widgets.
47
+
48
+ When defining `ThemeData`, strictly use the `*ThemeData` suffix for the following properties:
49
+ - `cardTheme`: Use `CardThemeData` (Not `CardTheme`)
50
+ - `dialogTheme`: Use `DialogThemeData` (Not `DialogTheme`)
51
+ - `tabBarTheme`: Use `TabBarThemeData` (Not `TabBarTheme`)
52
+ - `appBarTheme`: Use `AppBarThemeData` (Not `AppBarTheme`)
53
+ - `bottomAppBarTheme`: Use `BottomAppBarThemeData` (Not `BottomAppBarTheme`)
54
+ - `inputDecorationTheme`: Use `InputDecorationThemeData` (Not `InputDecorationTheme`)
55
+
56
+ ## Button Styling
57
+ Legacy button classes (`FlatButton`, `RaisedButton`, `OutlineButton`) are obsolete.
58
+
59
+ - Use `TextButton`, `ElevatedButton`, and `OutlinedButton`.
60
+ - Configure button appearance using a `ButtonStyle` object.
61
+ - For simple overrides based on the theme's color scheme, use the static utility method: `TextButton.styleFrom(foregroundColor: Colors.blue)`.
62
+ - For state-dependent styling (hovered, focused, pressed, disabled), use `MaterialStateProperty.resolveWith`.
63
+
64
+ ## Platform Idioms & Adaptive Design
65
+ When building adaptive apps, respect platform-specific norms to reduce cognitive load and build user trust.
66
+
67
+ - **Scrollbars:** Desktop users expect omnipresent scrollbars; mobile users expect them only during scrolling. Toggle `thumbVisibility` on the `Scrollbar` widget based on the platform.
68
+ - **Selectable Text:** Web and desktop users expect text to be selectable. Wrap text in `SelectableText` or `SelectableText.rich`.
69
+ - **Horizontal Button Order:** Windows places confirmation buttons on the left; macOS/Linux place them on the right. Use a `Row` with `TextDirection.rtl` for Windows and `TextDirection.ltr` for others.
70
+ - **Context Menus & Tooltips:** Desktop users expect hover and right-click interactions. Implement `Tooltip` for hover states and use context menu packages for right-click actions.
71
+
72
+ ## Workflows
73
+
74
+ ### Workflow: Migrating Legacy Themes to Material 3
75
+ Use this workflow when updating an older Flutter codebase.
76
+
77
+ **Task Progress:**
78
+ - [ ] 1. Remove `useMaterial3: false` from `ThemeData` (it is true by default).
79
+ - [ ] 2. Replace manual `ColorScheme` definitions with `ColorScheme.fromSeed()`.
80
+ - [ ] 3. Run validator -> review errors -> fix: Search for and replace deprecated `accentColor`, `accentColorBrightness`, `accentIconTheme`, and `accentTextTheme`.
81
+ - [ ] 4. Run validator -> review errors -> fix: Search for `AppBarTheme(color: ...)` and replace with `backgroundColor`.
82
+ - [ ] 5. Update `ThemeData` component properties to use `*ThemeData` classes (e.g., `cardTheme: CardThemeData()`).
83
+ - [ ] 6. Replace legacy buttons (`FlatButton` -> `TextButton`, `RaisedButton` -> `ElevatedButton`, `OutlineButton` -> `OutlinedButton`).
84
+ - [ ] 7. Replace legacy navigation components (`BottomNavigationBar` -> `NavigationBar`, `Drawer` -> `NavigationDrawer`).
85
+
86
+ ### Workflow: Implementing Adaptive UI Components
87
+ Use this workflow when building a widget intended for both mobile and desktop/web.
88
+
89
+ **Task Progress:**
90
+ - [ ] 1. If displaying a list/grid, wrap it in a `Scrollbar` and set `thumbVisibility: DeviceType.isDesktop`.
91
+ - [ ] 2. If displaying read-only data, use `SelectableText` instead of `Text`.
92
+ - [ ] 3. If implementing a dialog with action buttons, check the platform. If Windows, set `TextDirection.rtl` on the button `Row`.
93
+ - [ ] 4. If implementing interactive elements, wrap them in `Tooltip` widgets to support mouse hover states.
94
+
95
+ ## Examples
96
+
97
+ ### Example: Modern Material 3 ThemeData Setup
98
+ ```dart
99
+ MaterialApp(
100
+ title: 'Adaptive App',
101
+ theme: ThemeData(
102
+ colorScheme: ColorScheme.fromSeed(
103
+ seedColor: Colors.deepPurple,
104
+ brightness: Brightness.light,
105
+ ),
106
+ // Use *ThemeData classes for component normalization
107
+ appBarTheme: const AppBarThemeData(
108
+ backgroundColor: Colors.deepPurple, // Do not use 'color'
109
+ elevation: 0,
110
+ ),
111
+ cardTheme: const CardThemeData(
112
+ elevation: 2,
113
+ ),
114
+ textTheme: const TextTheme(
115
+ bodyMedium: TextStyle(letterSpacing: 0.2),
116
+ ),
117
+ ),
118
+ home: const MyHomePage(),
119
+ );
120
+ ```
121
+
122
+ ### Example: State-Dependent ButtonStyle
123
+ ```dart
124
+ TextButton(
125
+ style: ButtonStyle(
126
+ // Default color
127
+ foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
128
+ // State-dependent overlay color
129
+ overlayColor: MaterialStateProperty.resolveWith<Color?>(
130
+ (Set<MaterialState> states) {
131
+ if (states.contains(MaterialState.hovered)) {
132
+ return Colors.blue.withOpacity(0.04);
133
+ }
134
+ if (states.contains(MaterialState.focused) || states.contains(MaterialState.pressed)) {
135
+ return Colors.blue.withOpacity(0.12);
136
+ }
137
+ return null; // Defer to the widget's default.
138
+ },
139
+ ),
140
+ ),
141
+ onPressed: () {},
142
+ child: const Text('Adaptive Button'),
143
+ )
144
+ ```
145
+
146
+ ### Example: Adaptive Dialog Button Order
147
+ ```dart
148
+ Row(
149
+ // Windows expects confirmation on the left (RTL reverses the standard LTR Row)
150
+ textDirection: Platform.isWindows ? TextDirection.rtl : TextDirection.ltr,
151
+ mainAxisAlignment: MainAxisAlignment.end,
152
+ children: [
153
+ TextButton(
154
+ onPressed: () => Navigator.pop(context, false),
155
+ child: const Text('Cancel'),
156
+ ),
157
+ FilledButton(
158
+ onPressed: () => Navigator.pop(context, true),
159
+ child: const Text('Confirm'),
160
+ ),
161
+ ],
162
+ )
163
+ ```