Repository navigation
chore: migrate to material_ui and cupertino_ui - #6931
Merged
Merged
Conversation
Xcode 27 fails builds whose macOS deployment target is below 12.0. The template and client pinned 11.0, and Flutter 3.44.8 generates the FlutterMacOS pod at 10.15. Raise the Podfile platform and the Xcode project to 12.0, and let pods below 12.0 inherit the platform, as Flutter 3.47's podhelper does.
Xcode 27 fails builds whose iOS deployment target is below 15.0. The template and client pinned 13.0, and Flutter 3.44.8 generates the Flutter pod at 13.0. Raise the Podfile platform and the Xcode project to 15.0, let pods below 15.0 inherit the platform, and drop the stale MinimumOSVersion that Flutter strips from AppFrameworkInfo.plist anyway.
Raising the deployment targets is a breaking change under the compatibility policy, so add a 1.0.4 breaking-change guide and register it in the index, the sidebar and the release notes. The release notes also gain the missing 1.0.1-1.0.3 entries. The macOS and iOS publish pages now state the minimum OS version, and the changelog entry links the guide.
Raising the minimum macOS and iOS versions drops support for macOS 11 and iOS 13-14, so it ships in the 1.1.0 minor release instead of the 1.0.4 patch, together with the Flutter 3.47 bump, whose engine requires the same minimums. Move the changelog entry to 1.1.0 and the breaking-change guide from v1-0-4 to v1-1-0, and update the breaking-changes index, the sidebar and the release notes. Flet 1.0.4 becomes the last release for macOS 11 and iOS 13-14.
Flutter 3.47 adds a migration that runs on every `flutter pub get`, `flutter test` and build. It inserts an `analyzer.exclude` block into the `analysis_options.yaml` of any package that depends on Flutter. On CI, `flutter test` in packages/flet would then leave a modified checked-in file, and `dart pub publish --dry-run` fails with exit code 65. Every release job depends on that step. Add the same block the migration writes, placed after `include:` the way Flutter's own app template does it: `build/**` for packages/flet, flet_integration_test and the extension packages, plus the six platform directories for the client and the `flet build` template. The migration only checks that each pattern is present, so it leaves these files alone afterwards. The excludes are valid on older SDKs too.
Flutter 3.47 replaces several exact SDK package pins with caret ranges. The client lock picks up the versions they now require: intl 0.20.3, matcher 0.12.20, meta 1.19.0, test_api 0.7.12 and vector_math 2.4.3.
On Flutter 3.47, flutter_additional_ios_build_settings and flutter_additional_macos_build_settings delete IPHONEOS_DEPLOYMENT_TARGET below 15 and MACOSX_DEPLOYMENT_TARGET below 12 from every pod, whether or not it depends on Flutter, so each pod inherits the Pods project value. The post_install clamps added for Xcode 27 on 3.44.8 now repeat that work and can go. Verified on Xcode 27 with clean client builds (macos --debug, ios --simulator --debug): every Pods target ends up at 12.0 / 15.0 and both builds succeed without FLUTTER_XCODE_* overrides. client/ios/Podfile.lock picks up the new Podfile checksum and the Flutter pod checksum, which changes because 3.47's generated Flutter podspec declares iOS 15.0.
Flutter 3.47 makes Impeller the default renderer on macOS, Windows and Linux. The Flet desktop client already opts out on macOS (FLTEnableImpeller=false, after blank windows on Intel Macs in #3557), but apps built with `flet build` and the Windows and Linux clients would switch to Impeller with the SDK bump. Upstream still has open Impeller issues on these platforms (flutter#185394 crash on foreground on macOS, flutter#191538 flicker on Intel Macs, flutter#191353 slower on Windows, flutter#192915 flicker in Linux VMs), and Impeller hasn't been tested with Flet on real Windows/Linux hardware. Keep every desktop lane on Skia, as on Flutter 3.44: - Windows client and template runner: set_impeller_switch(Disabled). - Linux client and template runner: fl_dart_project_set_enable_impeller. - macOS apps: flet-cli adds FLTEnableImpeller=false to the Info.plist defaults, so `[tool.flet.macos.info]` or `--info-plist FLTEnableImpeller=true` still switches a built app to Impeller. FLUTTER_ENGINE_SWITCHES=--enable-impeller still enables Impeller in debug builds. Release builds ignore that variable.
On iOS, Flutter 3.47 sets VoiceOver's header trait from the heading level, not from the header flag (flutter#186916). Android already did this, so both mobile screen readers now announce a heading only when `heading_level` is set. Describe that on `Semantics.heading_level` and `Semantics.header`. Flutter 3.47 also reports `high_contrast` on Android API 34+, not only on iOS (flutter#182263).
The Dart 3.13 linter reports use_super_parameters for this constructor. It was the only new analyzer diagnostic in packages/flet on Flutter 3.47.5. The behavior is unchanged: replacementString keeps the super constructor's '' default.
Flutter 3.47.5 raised its Android dependency floors: Gradle 8.14, AGP 8.11.1 and KGP 2.2.20, the versions both Android lanes pin, are now the lowest it accepts, and each build printed three "support will soon be dropped" warnings. The next Flutter release will likely reject them. Move the client and the `flet build` template to the newest combination that is supported end to end without AGP 9: - Gradle wrapper 9.3.1, Flutter's template default. - KGP 2.3.21. KGP 2.2.x is documented only up to Gradle 8.14, and Kotlin 2.4 class files need R8 9.1.29 or later. - AGP 8.13.2, the last 8.x release. Its bundled R8 8.13.19 is the minimum Google lists for Kotlin 2.3. With AGP 8.11.1 (R8 8.11.18) and Kotlin 2.4, R8 couldn't parse Kotlin metadata and printed a warning per class whenever kotlin.Metadata was kept. Flutter 3.47.5's AGP/Gradle and AGP/KGP compatibility checks accept this combination. AGP 9 isn't usable yet: file_picker 11 and device_info_plus 12.4 fail to build with either android.builtInKotlin setting. Only the AGP warning remains. Gradle 9.1+ also runs on JDK 25, which crashed Gradle 8.14 with "IllegalArgumentException: 25.0.2". Verified: client `flutter build apk --debug` and `--release` (R8 8.13.19, no Kotlin metadata warnings), and `./gradlew assembleDebug` on JDK 25.
On Flutter 3.47, a custom build template no longer needs the Podfile post_install step: Flutter's migrators raise the deployment targets of the generated project during the build, and podhelper.rb drops lower targets from every pod. Custom templates keep building on Xcode 27, and the Podfile `platform` and project.pbxproj changes only remove that migration step. Staying on macOS 11 or iOS 13-14 needs Flet 1.0.4 or earlier, because the Flutter 3.47 engine itself requires macOS 12 and iOS 15.
… into chore/bump-flutter-3.47.5
The "Picking files with a client action" section sat between the Usage intro and its "Uploading files" and "Upload storage" subsections, so both rendered as children of the client-action section. Move it to just before Examples, where the Clipboard, Share and UrlLauncher pages put theirs. The "Pick and upload files" and "Pick text content" examples kept hand-written headings and intros, which duplicated the headings the remark plugin injects from each example's metadata, and the intros rendered above the injected heading. Move the intros into `docs_intro` and drop the hand-written headings.
`Path.QuadraticTo` defaults `w` to 1 in Python, and the serializer omits a field that equals its default, so a plain quadratic curve reaches the client without `w`. The Dart side fell back to a weight of 0. A conic with weight 0 is a straight line between its end points. Flutter 3.44 measured and dashed such conics as curves anyway, but Flutter 3.47 handles them correctly, so dashed paths built from `QuadraticTo` lost their curves (`test_draw_dashed_path_with_fill` dropped to 87.9% similarity). Fall back to 1, the same default as Python.
Kotlin Gradle plugin 2.3 compiles through the Build Tools API by default (`kotlin.compiler.runViaBuildToolsApi` defaults to true; it was false in 2.2.20). Its incremental cache stores every source path relative to the Android project. On Windows, when the pub cache and the app sit on different drives (C: and D: on GitHub's Windows runners), there is no relative path. Compiling a plugin such as battery_plus then fails with "Could not close incremental caches ... this and base files have different roots", which broke every apk-windows and aab-windows job. Set `kotlin.incremental=false` in the client and in flet-cli's default gradle.properties for generated projects. The plugin modules are small and Gradle still skips unchanged ones, so builds barely slow down. `[tool.flet.android.gradle_properties]` can turn it back on.
Desktop apps and the flet run client now use Flutter 3.47's default renderer, Impeller. The client and template runners switch to Skia when FLET_NO_IMPELLER is true at startup; release engines ignore Flutter's own engine-switch variables, and on macOS the runner replaces the private FlutterDartProject.enableImpeller getter only when asked. flet run --no-impeller (or impeller = false in pyproject) sets the variable for the client it opens. flet build/debug/test get --impeller/--no-impeller with [tool.flet(.<platform>)].impeller: the template runners bake it in on Windows and Linux, macOS gets FLTEnableImpeller=false and Android the EnableImpeller=false meta-data. Integration tests keep rendering with Skia until the goldens are regenerated.
3.47.6 fixes Windows release apps hanging while waiting on a timer (flutter/flutter#192513) and moves to Dart 3.13.5. The client lock and the generated icon lists don't change.
84 files import package:flutter/material.dart or cupertino.dart but use only widgets-level APIs: widgets, painting, animation, services and dart:ui types, which material.dart merely re-exports. Import package:flutter/widgets.dart there instead. This narrows the upcoming material_ui / cupertino_ui migration to the files that really use Material or Cupertino. Afterwards only 8 of the 19 extensions import either library. `flutter analyze` reports the same infos as before and no errors.
packages/flet/lib/src/utils/material_icons.dart and cupertino_icons.dart are generated from Flutter's icon sets and carry its spelling, including a few upstream misspellings (flourescent, no_meals_ouline, threed_rotation) that are part of the API. They were never edited since they were generated, so the hook never saw them; the material_ui migration touches their imports. Exclude them like the generated icon JSON lists, and allow the existing public LocaleExtention identifier.
Flutter 3.47 froze the Material and Cupertino libraries in the SDK and publishes them as the material_ui and cupertino_ui packages, which the SDK copies will be deprecated in favor of. The packages redeclare every Material and Cupertino type, so code has to switch as a whole. - pubspec: add material_ui ^1.6.0 and cupertino_ui ^1.1.2 and require Flutter >= 3.47. Move shimmer to ^4.0.0, which is built on material_ui. Drop flutter_localizations, which is now only used through material_ui. - Run `dart fix --apply --code=migrate_design_widgets` on lib and test (134 fixes in 118 files). - Localizations: material_ui and cupertino_ui ship their own GlobalMaterialLocalizations and GlobalCupertinoLocalizations, which clash with flutter_localizations' classes of the same names. Use material_ui's GlobalMaterialLocalizations.delegates (Cupertino, Material and widgets delegates) for the app and as the default of Locale.isSupportedByDelegates. - flet.dart no longer re-exports Icons and CupertinoIcons. Re-exporting them from either library makes the name ambiguous for code that imports the other one. Extensions import material_ui or cupertino_ui themselves. - Markdown: flutter_markdown_plus still builds on the SDK Material, so MarkdownStyleSheet.fromTheme only accepts the SDK ThemeData. Add markdownStyleSheetFromTheme(), a port of it for the material_ui theme, and always pass a full style sheet to MarkdownBody. Without one, MarkdownBody falls back to a sheet built from the SDK's default light theme, which renders dark text on dark backgrounds. `flutter analyze` reports no errors (the same infos as before), and the 91 tests pass.
Seven of the extensions use Material APIs: ads, charts, code-editor, datatable2, map, spinkit and video. None uses Cupertino. - pubspec: add material_ui ^1.6.0 and require Flutter >= 3.47. - Run `dart fix --apply --code=migrate_design_widgets` (28 fixes). - datatable2: move to data_table_2 ^3.0.0, which is built on material_ui. 2.x takes the SDK's DataCell, DataRow and CheckboxThemeData, which no longer match the types Flet passes. Delete lib/src/data_sources.dart, data_table_2's example "Dessert" data sources that came along when the extension moved into this repo and that nothing imports. - code-editor: point flutter_code_editor at the fork's new `material-ui` branch, where CodeField is built on material_ui. The SDK TextField it used before fails with "No Material widget found" under material_ui's MaterialApp. `pinyin-fix` stays on the SDK libraries for Flet 1.0.x. `dart analyze`, as CI runs it, passes for all seven.
flutter_colorpicker builds its pickers on the Flutter SDK's Material widgets. Under material_ui's MaterialApp, the ColorPicker's label dropdown and hex TextField, HueRingPicker's TextField, and SlidePicker with labels fail with "No Material widget found" or "No MaterialLocalizations found", and MaterialPicker reads the SDK's fallback theme. The package has no material_ui release (its last release is 1.1.0, May 2024). Copy its lib/ (1.1.0, MIT) into lib/src/third_party/flutter_colorpicker with its LICENSE and a README stating its origin and changes, and migrate it together with the extension: add material_ui ^1.6.0, require Flutter >= 3.47 and run `dart fix --apply --code=migrate_design_widgets` (10 fixes). The vendored code is excluded from analysis and from the typos check, as it doesn't follow this repo's lints. (The repository's .gitignore ignores `vendor/` directories, hence `third_party/`.) `dart analyze`, as CI runs it, passes.
Build template: the boot-overlay MaterialApp in lib/main.dart now comes from material_ui, like the rest of Flet. The pubspec pins material_ui 1.6.0 and cupertino_ui 1.1.2 exactly. Generated projects have no committed lock and always resolve the newest versions, and material_ui ships often: 1.6.0 already changed DropdownButtonFormField layout. Flet releases should bump the pins deliberately. Extension template: the sample control only needs widgets, so it imports package:flutter/widgets.dart. The pubspec requires Flutter >= 3.47 and adds material_ui, so new extensions start on the Material library Flet uses instead of package:flutter/material.dart.
Contributor
|
Sorry @ndonkoHenri, your pull request is larger than the review limit of 150,000 diff characters |
ndonkoHenri
added this pull request to stack #6917
October 8, 2026 17:18
… into chore/bump-flutter-3.47.5
…chore/material-ui-migration
Deploying flet-website-v2 with
|
| Latest commit: |
1bfffec
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://249e207b.flet-website-v2.pages.dev |
| Branch Preview URL: | https://chore-material-ui-migration.flet-website-v2.pages.dev |
The color pickers now depend on the material-ui branch of flet-dev/flutter_colorpicker, the 1.1.0 release moved to material_ui, the same way the code editor depends on flet-dev/flutter-code-editor. This drops the copy under lib/src/third_party and its analyzer and typos excludes.
…ployment-targets # Conflicts: # CHANGELOG.md # website/docs/updates/release-notes.md
…r-3.47.5 # Conflicts: # CHANGELOG.md # client/pubspec.lock # packages/flet/CHANGELOG.md
Flutter 3.47's AnalysisOptionsMigration writes this block on every pub get, as for the other extensions in this branch.
…tion # Conflicts: # CHANGELOG.md # client/pubspec.lock # sdk/python/.pre-commit-config.yaml # sdk/python/_typos.toml
utils/theme.dart read the SDK Theme, which is Flutter's default light theme inside Flet's material_ui app, so shadcn controls ignored the page's dark mode. time_picker.dart used the SDK TimeOfDay, which no longer matches the one control.getTimeOfDay() returns.
Flutter 3.47 shows a text field's context menu in the root overlay without the themes between the field and the Navigator. flet_shadcn_ui provides its ShadTheme only around each control, so right-clicking or long-pressing an Input, Textarea, InputOTP or TimePicker threw "ShadTheme.of() called with a context that does not contain a ShadTheme" and covered the window with an error box. Input and Textarea build shadcn_ui's menu inside the field's ShadTheme. InputOTP and TimePicker take no contextMenuBuilder, so their native menu is turned off.
Regenerating the lock after the merge had moved flutter_shaders and theme_extensions_builder_annotation, which Flutter 3.47 doesn't require.
…tion # Conflicts: # client/pubspec.lock
ndonkoHenri
removed this pull request from stack #6917
October 8, 2026 22:00
ndonkoHenri
added this pull request to stack #6934
October 8, 2026 22:01
FeodorFitsner
approved these changes
Oct 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #6916, which is stacked on #6914 (targets
flet-1.1.0); merge those first. All three ship in Flet 1.1.0.Summary
Flutter froze
package:flutter/material.dartandpackage:flutter/cupertino.dartin 3.44, and 3.47 is the first release with version 1.0 of the standalonematerial_uiandcupertino_uipackages, where development continues. The SDK libraries are scheduled for deprecation (migration guide).This PR moves all of Flet's Dart code to the new packages in one go:
fletpackage;flet buildtemplate;The packages redeclare every Material and Cupertino type, so
material_ui'sThemeDataand the SDK'sThemeDataare unrelated types. Moving everything at once keeps a Flet app from mixing the two, which fails at runtime ("No Material widget found", "No MaterialLocalizations found") or silently falls back to Flutter's default theme.This is a breaking change for extension authors whose Dart code uses Material or Cupertino. Python-only apps are not affected. The new guide, Extensions: Material and Cupertino now come from material_ui and cupertino_ui, explains who is affected and how to migrate.
Changes
dart fix --apply --code=migrate_design_widgetsacross all packages, plus the manual fixes it doesn't do (exportdirectives, localizations). Files that use no Material or Cupertino API importpackage:flutter/widgets.dartinstead.material_ui: ^1.6.0andcupertino_ui: ^1.1.2, withflutter: ">=3.47.0".flutter_localizationsis gone: localizations come frommaterial_ui'sGlobalMaterialLocalizations.delegates, which include the Cupertino and widgets delegates.flet.dartno longer re-exportsIconsandCupertinoIcons.flutter_markdown_plus'sMarkdownStyleSheet.fromThemeonly takes the SDK'sThemeData, so Flet adds a publicmarkdownStyleSheetFromTheme()port and always passes a style sheet. Without one,MarkdownBodyfalls back to the SDK's default light theme.material_ui'sSelectableText, through Flet's own copy ofLatexElementBuilder;flutter_math_forkbecomes a direct dependency. The SDKSelectableTextfallback threw "No CupertinoLocalizations found" when you right-clicked the error message.TimeOfDayis nowmaterial_ui's.material_ui: ^1.6.0in the extensions that use Material: ads, charts, code editor, color pickers, datatable2, map, shadcn-ui, spinkit and video.data_table_23.x andshimmer4.x, which are built onmaterial_ui. The datatable2 extension also drops a dead example data file.flutter_colorpickercomes from thematerial-uibranch of flet-dev/flutter_colorpicker: the 1.1.0 release with its imports moved tomaterial_ui(134 tests pass).flutter_code_editorcomes from thematerial-uibranch of flet-dev/flutter-code-editor, which is the currentpinyin-fixbranch plus the migration, including the autocomplete popup underlib/src/wip, which its analyzer excludes (287 tests pass).RichAttributionopen and close buttons are built withmaterial_ui.flet-1.1.0):utils/theme.dartreadsmaterial_ui'sTheme, so the fallbackShadThemefollows the page's dark mode; the SDKThemewould return Flutter's default light theme.TimePickerusesmaterial_ui'sTimeOfDay, whichcontrol.getTimeOfDay()returns.material_uiMaterial.Material. Without the wrapper, debug builds threw "No Material widget found" and ink effects were lost.client/pubspec.lockresolvesmaterial_ui1.6.0,cupertino_ui1.1.2 and the code editor'smaterial-uibranch.flet buildtemplate'slib/main.dartimportsmaterial_ui. Itspubspec.yamlpinsmaterial_ui: 1.6.0andcupertino_ui: 1.1.2exactly, because generated projects have no lock file.widgets.dartand declaresmaterial_ui: ^1.6.0.material_ui'sIconsandcupertino_ui'sCupertinoIcons. Names still come from the SDK's sources, because the glyphs still come from the SDK's font.user-extensions.mdsnippets importmaterial_ui.CHANGELOG.md(Breaking changes) andpackages/flet/CHANGELOG.md.implement-flet-extensionnow says to usematerial_ui/cupertino_uiand to check that the parts of a wrapped package an extension uses don't render SDK Material widgets.Behavior changes
material_ui1.6.0'sDropdownButtonFormFieldno longer stretches to a tight height. ADropdownM2with a fixedheightrenders the same pixels, but only the field itself is tappable now, not the empty space below it.Themeoverride, which made them transparent, doesn't reachmaterial_uiwidgets. This is from reading the code; it wasn't observed.flet-1.1.0and its flet-shadcn-ui extension were merged in.Testing
Environment: macOS 27 / Xcode 27.0, Flutter 3.47.5, re-checked on 3.47.6 where noted.
dart analyzeis clean for the client and for every extension that uses Material, including flet-shadcn-ui;packages/flethas only its 11 existing infos (client and core also on 3.47.6).flutter testpasses (91, also on 3.47.6).--wasm.generate_icons.py --verifyreports 0 failures, including flet-shadcn-ui's Lucide set.TimePickerandDatePickerlocalization;TimePicker/DatePickervalues round-tripping to Python;SnackBarandDropdownM2selection;RichAttributionpopup;TextFieldtyping in a fullscreen button bar.material_uiDropdownButtonFormFieldside by side;MarkdownControlwith a right-click, failing before the fix and passing after.flet build webof an app with the code editor, color pickers, datatable2 and spinkit, using the in-repo template and local packages. It resolves the exactmaterial_ui/cupertino_uipins.yarn buildpasses with no broken links or anchors.CupertinoApp.Not covered locally:
Follow-ups
MaterialUiCompatibilityBridge(it injects SDK theme and localizations for unmigrated dependencies) orBuildContext-based helper overloads.fl_chartdraws the default touch crosshair with the SDKTheme, so it ignores a customoutlinecolor. It is cosmetic and stays visible in both themes.Summary by Sourcery
Migrate Flet’s Dart ecosystem to the standalone material_ui and cupertino_ui packages ahead of Flutter SDK library deprecation.
Bug Fixes:
Enhancements:
Build:
Documentation:
Tests:
Chores: