mcpField
F
flutter-native-ui

flutter-native-ui

github.com/thesimpleappDesign & UI043 installsUpdated 10w ago
Repository

About flutter-native-ui

flutter-native-ui is a skill for building and reviewing Flutter interfaces using current Flutter and Dart guidance. It helps developers follow an app's existing design system while choosing platform-appropriate widgets, layouts, and navigation.

Key features

  1. 01Grounds UI choices in official docs
  2. 02Preserves existing themes and navigation
  3. 03Guides Material and Cupertino patterns
  4. 04Covers responsive layouts and controls
  5. 05Requires analyzer and visual verification

Use cases

  1. 01Building a screen in an existing Flutter app
  2. 02Choosing adaptive controls and navigation
  3. 03Checking empty, loading, and error states

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/thesimpleapp/flutter-app-skills --skill flutter-native-ui

After installing, type/flutter-native-uiin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
animations.md
controls.md
icons-and-media.md
layout.md
navigation.md
storage.md
theming.md
visual-effects.md

Details

From the project README

Flutter Native UI

Ground every UI choice in current Flutter and Dart docs, not React Native or Expo patterns. Check flutter --version. Official sources: docs.flutter.dev, api.flutter.dev, dart.dev, m3.material.io, pub.dev packages from flutter.dev.

If the project already has a design system, tokens, or router, extend those. Do not invent a second theme or a second navigator.

If widgets read a house ThemeExtension, a branded token file, or a *Pressable instead of Material ink, stop and follow flutter-custom-design-system. Do not "fix" that app toward stock Material 3.

References

Read only the file you need:

references/
  navigation.md      go_router, tabs, sheets, dialogs, transitions
  theming.md         ColorScheme, TextTheme, light/dark, Cupertino
  layout.md          SafeArea, MediaQuery.*Of, breakpoints, slivers
  controls.md        Adaptive constructors, buttons, fields, pickers
  animations.md      Implicit first, Hero, M3 motion, lists
  icons-and-media.md Icons.adaptive, images, camera, audio, video
  visual-effects.md  Elevation, blur, gradients
  storage.md         Preferences, secure storage, files, SQL

Design system

Pick one app chrome and stay on it.

ProductRootChrome
Cross-platform (default)MaterialApp / MaterialApp.routerMaterial 3 + .adaptive() controls
iOS-firstCupertinoApp / CupertinoApp.routerCupertino widgets + HIG spacing
Existing appWhatever it already usesDo not restyle the whole app to prove a point

Flutter auto-adapts OS behavior (scroll physics, back gesture, text editing, haptics). It does not auto-swap tab bars, app bars, or information architecture. That is an explicit choice. See platform adaptations.

Do not mix Material and Cupertino widgets on the same surface except .adaptive() constructors and Icons.adaptive.

Material 3 is the default since Flutter 3.16. Never set useMaterial3: false. Never pass useMaterial3: true as if it were an opt-in.

Imports (Flutter 3.47+)

Material and Cupertino shipped as standalone 1.0 packages: material_ui and cupertino_ui. The SDK copies still work in 3.47 and are scheduled for deprecation in the Fall 2026 stable.

  • Existing project: keep the import style already in the tree.
  • New 3.47+ app, or when asked to migrate:
flutter pub add material_ui
# only if you build Cupertino chrome:
flutter pub add cupertino_ui
dart fix --apply --code=migrate_design_widgets

That rewrites package:flutter/material.dart → package:material_ui/material_ui.dart and package:flutter/cupertino.dart → package:cupertino_ui/cupertino_ui.dart.

If pubspec.yaml does not update, run flutter pub add material_ui (and cupertino_ui) then dart fix --apply again.

Legacy package widgets that still import the SDK libraries need a bridge:

MaterialApp(
  builder: (context, child) => MaterialUiCompatibilityBridge(child: child!),
)

Localizations: localizationsDelegates: GlobalMaterialLocalizations.delegates from material_ui (includes Cupertino + Widgets). Do not keep flutter_localizations GlobalMaterialLocalizations / GlobalCupertinoLocalizations after migrating.

Build a screen

  1. Read the existing theme, router, and a nearby screen. Copy those conventions.
  2. Choose the scaffold: Scaffold + AppBar / SliverAppBar (Material) or CupertinoPageScaffold + CupertinoNavigationBar / CupertinoSliverNavigationBar (Cupertino).
  3. Put the page title in the app/nav bar, not a custom Text at the top of the body.
  4. Inset content with SafeArea around the body, not the whole Scaffold (AppBar already draws under the status bar). Nested SafeAreas collapse; do not add padding by reading MediaQuery.padding yourself.
  5. Scrollable pages: CustomScrollView + slivers, or ListView.builder. Forms: ListView / CustomScrollView, not a bare Column that overflows.
  6. Color and type come from ColorScheme.of(context) and TextTheme.of(context). No raw Colors.blue, no one-off fontSize: 13.
  7. Interactive controls get const ValueKey<String>('kebab-name').
  8. After edits: hot reload, then verify (see Verify).

Hard rules

Theme and color

  • Build schemes with ColorScheme.fromSeed. Pair theme + darkTheme + themeMode.
  • Read tokens via ColorScheme.of(context) and TextTheme.of(context) (same as Theme.of(context).colorScheme / .textTheme).
  • Use M3 roles: primary/onPrimary, surface/onSurface, surfaceContainer*, outline, error. Not primarySwatch, not accentColor.
  • Cupertino color is CupertinoColors / CupertinoDynamicColor, resolved with CupertinoDynamicColor.resolve(color, context).

Layout

  • MediaQuery.sizeOf / paddingOf / viewInsetsOf / viewPaddingOf / textScalerOf / platformBrightnessOf / highContrastOf / accessibleNavigationOf. Never MediaQuery.of(context).size (rebuilds on every MediaQuery change).
  • Row/Column/Flex spacing for gaps. Wrap spacing + runSpacing. Do not sprinkle SizedBox between every child.
  • Window size, not device type. Never Platform.isIOS to pick a phone vs tablet layout. Never OrientationBuilder at the app root. Breakpoints: compact <600, medium 600–839, expanded ≥840 (M3 window size classes).
  • Do not lock orientation. Do not use flutter_screenutil or design-px scalers.

Widgets (new code)

UseDo not use
FilledButton, FilledButton.tonal, OutlinedButton, TextButtonElevatedButton as the primary action, RaisedButton, FlatButton
NavigationBar + NavigationDestinationBottomNavigationBar
NavigationRail / NavigationDrawer on large widthsA stretched phone nav bar on desktop
SegmentedButtonToggleButtons
DropdownMenuDropdownButton / DropdownButtonFormField
MenuAnchor / MenuBarPopupMenuButton for new menus
SearchAnchor / SearchBarA homemade search TextField in the app bar
Card.filled / Card.outlinedRandom Container + BoxShadow cards
ListView.builder / sliversListView(children: hugeList)
Switch.adaptive, Slider.adaptive, Checkbox.adaptive, Radio.adaptive, CircularProgressIndicator.adaptive, RefreshIndicator.adaptive, AlertDialog.adaptive, showAdaptiveDialogPlatform-blind Material controls for those OS-native affordances

Navigation

  • New multi-screen apps: go_router + MaterialApp.router / CupertinoApp.router. Official docs do not recommend MaterialApp.routes named routes.
  • Existing Navigator.push apps: keep Navigator unless asked to migrate.
  • Tabs that must keep per-tab stacks: StatefulShellRoute.indexedStack.
  • Sheets and dialogs stay pageless (showModalBottomSheet, showAdaptiveDialog). Do not make every popup a GoRoute unless it must be deep-linkable.
  • Full-screen modal: fullscreenDialog: true (iOS present) or a GoRoute with that page flag.

Dart / widgets

  • const constructors. Small widgets over one 400-line build.
  • File names snake_case.dart. Types PascalCase. Interactive keys kebab-case strings.
  • SelectableText, or a SelectionArea ancestor, for values the user may copy.
  • Tabular numbers: fontFeatures: const [FontFeature.tabularFigures()].
  • Debug-only jump chips and prefills stay behind kDebugMode and still go through the real auth path.
  • Do not add GetX, flutter_screenutil, FontAwesome-for-chrome, or a new state-management package to ship a screen.

Do not copy Expo/RN habits

  • No StyleSheet, process.env.EXPO_OS, SafeAreaView, CSS boxShadow, or kebab-case source files.
  • No flex: 1 style maps — use Expanded / Flexible.
  • No SF Symbols via expo-image. Use Icons.adaptive / CupertinoIcons.

Verify

UI work is not done when the edit applies.

  1. Analyzer clean on the files you touched (dart analyze / flutter analyze).
  2. Hot reload the running app. Hot restart if you changed main, routes, or global theme.
  3. Look at the running frame (screenshot, widget preview, or the project's visual loop). A stale frame is not evidence.
  4. Isolated widgets: @Preview from package:flutter/widget_previews.dart (stable in 3.47). See Widget Previewer.
  5. Check the empty, loading, error, and keyboard-open states of the screen you changed — and any other route that reads the same state.

Comments

Markdown supported