layrz_ui 1.0.0-prerelease.5 copy "layrz_ui: ^1.0.0-prerelease.5" to clipboard
layrz_ui: ^1.0.0-prerelease.5 copied to clipboard

A Material-free and Cupertino-free Flutter design system built on package:flutter/widgets.dart. The successor to layrz_theme.

example/lib/main.dart

import 'package:example/fonts/fonts.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import 'package:layrz_ui/layrz_ui.dart';

import 'layout.dart';
import 'src/providers/theme_mode_provider.dart';
import 'src/sections/access_paths_section.dart';
import 'src/sections/accordion_section.dart';
import 'src/sections/ai_marker_section.dart';
import 'src/sections/alerts_section.dart';
import 'src/sections/app_banner_section.dart';
import 'src/sections/badge_section.dart';
import 'src/sections/borders_section.dart';
import 'src/sections/button_group_section.dart';
import 'src/sections/buttons_section.dart';
import 'src/sections/calendar_section.dart';
import 'src/sections/cards_section.dart';
import 'src/sections/chips_section.dart';
import 'src/sections/code_section.dart';
import 'src/sections/colors_section.dart';
import 'src/sections/connection_indicator_section.dart';
import 'src/sections/context_menu_section.dart';
import 'src/sections/dialogs_section.dart';
import 'src/sections/elevation_section.dart';
import 'src/sections/file_input_section.dart';
import 'src/sections/form_section.dart';
import 'src/sections/grid_section.dart';
import 'src/sections/home_section.dart';
import 'src/sections/images_section.dart';
import 'src/sections/inputs_section.dart';
import 'src/sections/layo_section.dart';
import 'src/sections/markdown_section.dart';
import 'src/sections/menus_section.dart';
import 'src/sections/motion_section.dart';
import 'src/sections/pickers/pickers_section.dart';
import 'src/sections/progress_section.dart';
import 'src/sections/radius_section.dart';
import 'src/sections/refresh_section.dart';
import 'src/sections/responsive_modal_section.dart';
import 'src/sections/scaffold_shell_section.dart';
import 'src/sections/sheets_section.dart';
import 'src/sections/skeleton_section.dart';
import 'src/sections/snackbar_section.dart';
import 'src/sections/spacing_section.dart';
import 'src/sections/steppers_section.dart';
import 'src/sections/tab_view_section.dart';
import 'src/sections/table_section.dart';
import 'src/sections/text_section.dart';
import 'src/sections/timeline_section.dart';
import 'src/sections/tooltips_section.dart';
import 'src/sections/transitions_section.dart';
import 'src/sections/tree_view_section.dart';
import 'src/sections/workspace_tabs_section.dart';
import 'src/sections/typography_section.dart';

/// Run the showroom application with Open Sans font.
///
/// The Open Sans font is loaded before the app starts. This demonstrates
/// the correct startup shape for consumers who use a custom font that
/// requires loading (e.g., from a network source). In this case, the font
/// is bundled in assets and loaded immediately by the engine, so [load]
/// completes without I/O.
///
/// Note there is no `font.registerOnWeb()` call here: the theme constructor
/// ([LayrzThemeData.light], via [LayrzTokens.light] and [LayrzTextTheme.defaults])
/// calls it automatically once [font] reaches `ShowroomApp`'s `LayrzThemeData.light`
/// below, so DOM-rendered content (e.g. layrz_ui's web login fields) picks up the
/// font with no extra step from consumer code. `OpenSansFont` and `FiraSansFont` are
/// bundled assets, so their `registerOnWeb` is the inherited no-op; swap in
/// `NotoSansFont` (URL-based) below to see it actually register a browser
/// `@font-face`.
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final font = const OpenSansFont();
  // final font = const DoppioOneFont();
  await font.load();
  runApp(ProviderScope(child: ShowroomApp(font: font)));
}

/// Builds a [CustomTransitionPage] using [LayrzPageTransitions.fade] at the
/// design system's own page-transition duration ([LayrzPageTransitions.durationOf]).
///
/// Every showroom route's `pageBuilder` delegates to this helper so the whole
/// shell animates consistently on navigation, without repeating the same
/// three-line [CustomTransitionPage] construction at every [GoRoute].
CustomTransitionPage<void> _fadePage(BuildContext context, Widget child) => CustomTransitionPage<void>(
  child: child,
  transitionsBuilder: LayrzPageTransitions.fade,
  transitionDuration: LayrzPageTransitions.durationOf(context),
);

/// The singleton go_router instance for the showroom application.
///
/// Uses a [ShellRoute] to persist the [ShowroomLayout] shell while only
/// swapping the body content during navigation. This avoids rebuilding the
/// entire layout (rail, drawer, search, notifications) on every navigation,
/// dramatically improving performance.
///
/// Every route's `pageBuilder` returns a [CustomTransitionPage] built via the
/// [_fadePage] helper, which always uses [LayrzPageTransitions.fade] at
/// [LayrzPageTransitions.durationOf]'s duration — so the whole showroom
/// animates consistently on navigation. See the dedicated `/transitions` page
/// (built on [TransitionsSection]) to see every other builder, including
/// [LayrzPageTransitions.slide], [LayrzPageTransitions.scale],
/// [LayrzPageTransitions.rotation], and [LayrzPageTransitions.none], driven
/// interactively.
///
/// To revert to the original named-route implementation, replace [ShowroomApp.build]
/// with a [LayrzApp] constructor and restore the `initialRoute` + `routes` pattern.
final _router = GoRouter(
  initialLocation: '/home',
  routes: [
    GoRoute(
      path: '/',
      redirect: (context, state) => '/home',
    ),
    ShellRoute(
      builder: (context, state, child) => ShowroomLayout(child: child),
      routes: [
        GoRoute(
          path: '/home',
          pageBuilder: (context, state) => _fadePage(context, HomeSection()),
        ),
        GoRoute(
          path: '/buttons',
          pageBuilder: (context, state) => _fadePage(context, ButtonsSection()),
        ),
        GoRoute(
          path: '/button-group',
          pageBuilder: (context, state) => _fadePage(context, ButtonGroupSection()),
        ),
        GoRoute(
          path: '/alerts',
          pageBuilder: (context, state) => _fadePage(context, AlertsSection()),
        ),
        GoRoute(
          path: '/tooltips',
          pageBuilder: (context, state) => _fadePage(context, TooltipsSection()),
        ),
        GoRoute(
          path: '/images',
          pageBuilder: (context, state) => _fadePage(context, ImagesSection()),
        ),
        GoRoute(
          path: '/menus',
          pageBuilder: (context, state) => _fadePage(context, MenusSection()),
        ),
        GoRoute(
          path: '/chips',
          pageBuilder: (context, state) => _fadePage(context, ChipsSection()),
        ),
        GoRoute(
          path: '/text',
          pageBuilder: (context, state) => _fadePage(context, TextSection()),
        ),
        GoRoute(
          path: '/inputs',
          pageBuilder: (context, state) => _fadePage(context, InputsSection()),
        ),
        GoRoute(
          path: '/pickers',
          pageBuilder: (context, state) => _fadePage(context, PickersSection()),
        ),
        GoRoute(
          path: '/grid',
          pageBuilder: (context, state) => _fadePage(context, GridSection()),
        ),
        GoRoute(
          path: '/context-menu',
          pageBuilder: (context, state) => _fadePage(context, ContextMenuSection()),
        ),
        GoRoute(
          path: '/dialogs',
          pageBuilder: (context, state) => _fadePage(context, DialogsSection()),
        ),
        GoRoute(
          path: '/responsive-modal',
          pageBuilder: (context, state) => _fadePage(context, ResponsiveModalSection()),
        ),
        GoRoute(
          path: '/sheets',
          pageBuilder: (context, state) => _fadePage(context, SheetsSection()),
        ),
        GoRoute(
          path: '/steppers',
          pageBuilder: (context, state) => _fadePage(context, StepperSection()),
        ),
        GoRoute(
          path: '/typography',
          pageBuilder: (context, state) => _fadePage(context, TypographySection()),
        ),
        GoRoute(
          path: '/colors',
          pageBuilder: (context, state) => _fadePage(context, ColorsSection()),
        ),
        GoRoute(
          path: '/spacing',
          pageBuilder: (context, state) => _fadePage(context, SpacingSection()),
        ),
        GoRoute(
          path: '/radius',
          pageBuilder: (context, state) => _fadePage(context, RadiusSection()),
        ),
        GoRoute(
          path: '/elevation',
          pageBuilder: (context, state) => _fadePage(context, ElevationSection()),
        ),
        GoRoute(
          path: '/borders',
          pageBuilder: (context, state) => _fadePage(context, BordersSection()),
        ),
        GoRoute(
          path: '/motion',
          pageBuilder: (context, state) => _fadePage(context, MotionSection()),
        ),
        GoRoute(
          path: '/access-paths',
          pageBuilder: (context, state) => _fadePage(context, AccessPathsSection()),
        ),
        GoRoute(
          path: '/calendar',
          pageBuilder: (context, state) => _fadePage(context, CalendarSection()),
        ),
        GoRoute(
          path: '/progress',
          pageBuilder: (context, state) => _fadePage(context, ProgressSection()),
        ),
        GoRoute(
          path: '/timeline',
          pageBuilder: (context, state) => _fadePage(context, TimelineSection()),
        ),
        GoRoute(
          path: '/tree-view',
          pageBuilder: (context, state) => _fadePage(context, TreeViewSection()),
        ),
        GoRoute(
          path: '/badges',
          pageBuilder: (context, state) => _fadePage(context, BadgeSection()),
        ),
        GoRoute(
          path: '/connection-indicator',
          pageBuilder: (context, state) => _fadePage(context, ConnectionIndicatorSection()),
        ),
        GoRoute(
          path: '/transitions',
          pageBuilder: (context, state) => _fadePage(context, TransitionsSection()),
        ),
        GoRoute(
          path: '/refresh',
          pageBuilder: (context, state) => _fadePage(context, RefreshSection()),
        ),
        GoRoute(
          path: '/snackbar',
          pageBuilder: (context, state) => _fadePage(context, SnackbarSection()),
        ),
        GoRoute(
          path: '/accordion',
          pageBuilder: (context, state) => _fadePage(context, AccordionSection()),
        ),
        GoRoute(
          path: '/ai-marker',
          pageBuilder: (context, state) => _fadePage(context, AiMarkerSection()),
        ),
        GoRoute(
          path: '/skeleton',
          pageBuilder: (context, state) => _fadePage(context, SkeletonSection()),
        ),
        GoRoute(
          path: '/form',
          pageBuilder: (context, state) => _fadePage(context, FormSection()),
        ),
        GoRoute(
          path: '/file-input',
          pageBuilder: (context, state) => _fadePage(context, FileInputSection()),
        ),
        GoRoute(
          path: '/layo',
          pageBuilder: (context, state) => _fadePage(context, LayoSection()),
        ),
        GoRoute(
          path: '/markdown',
          pageBuilder: (context, state) => _fadePage(context, MarkdownSection()),
        ),
        GoRoute(
          path: '/tab-view',
          pageBuilder: (context, state) => _fadePage(context, TabViewSection()),
        ),
        GoRoute(
          path: '/app-banner',
          pageBuilder: (context, state) => _fadePage(context, AppBannerSection()),
        ),
        GoRoute(
          path: '/table',
          pageBuilder: (context, state) => _fadePage(context, TableSection()),
        ),
        GoRoute(
          path: '/workspace-tabs',
          pageBuilder: (context, state) => _fadePage(context, WorkspaceTabsSection()),
        ),
        GoRoute(
          path: '/code',
          pageBuilder: (context, state) => _fadePage(context, CodeSection()),
        ),
        GoRoute(
          path: '/cards',
          pageBuilder: (context, state) => _fadePage(context, CardsSection()),
        ),
        GoRoute(
          path: '/scaffold-shell',
          pageBuilder: (context, state) => _fadePage(context, ScaffoldShellSection()),
        ),
      ],
    ),
  ],
);

/// Root widget of the showroom application.
///
/// The theme uses the provided custom font (Open Sans from bundled assets).
/// Consumers can provide any [LayrzFont] implementation — bundled fonts like this
/// one, fonts fetched from a CDN, or fonts loaded from network sources via
/// [layrz_ui_extensions].
///
/// Uses [LayrzApp.router] with a go_router [GoRouter] configured with a [ShellRoute],
/// ensuring the application shell persists across navigation while only the body
/// content changes.
///
/// Reads [themeModeProvider] to decide which of [LayrzThemeData.light] and
/// [LayrzThemeData.dark] is active, and re-evaluates the system status/navigation
/// bar overlay style every time that mode changes.
class ShowroomApp extends ConsumerWidget {
  /// Creates a new [ShowroomApp].
  ///
  /// The [font] parameter specifies which font to use in the theme. It must be
  /// loaded before this widget is built (typically in [main] before [runApp]).
  const ShowroomApp({
    required this.font,
    super.key,
  });

  /// The custom font to use in the theme.
  final LayrzFont font;

  /// Resolves the effective [Brightness] for [mode] against the platform's
  /// current brightness, then applies the matching system overlay style —
  /// light icons over a dark effective brightness, dark icons over a light one.
  void _applySystemOverlayStyle(BuildContext context, LayrzThemeMode mode) {
    final isDark = switch (mode) {
      LayrzThemeMode.light => false,
      LayrzThemeMode.dark => true,
      LayrzThemeMode.system => MediaQuery.platformBrightnessOf(context) == Brightness.dark,
    };
    final iconBrightness = isDark ? Brightness.light : Brightness.dark;
    SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle.dark.copyWith(
        statusBarBrightness: LayrzPlatform.isIOS ? .light : iconBrightness,
        statusBarIconBrightness: LayrzPlatform.isIOS ? .light : iconBrightness,
        systemStatusBarContrastEnforced: true,
        systemNavigationBarIconBrightness: LayrzPlatform.isIOS ? .light : iconBrightness,
        systemNavigationBarContrastEnforced: true,
      ),
    );
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final mode = ref.watch(themeModeProvider);
    _applySystemOverlayStyle(context, mode);
    return LayrzApp.router(
      routerConfig: _router,
      title: kAppTitle,
      theme: LayrzThemeData.light(
        font: font,
        // primaryColor: LayrzColors.cyan,
      ),
      darkTheme: LayrzThemeData.dark(font: font),
      themeMode: mode,
    );
  }
}
0
likes
0
points
1.77k
downloads

Documentation

Documentation

Publisher

verified publisherlayrz.com

Weekly Downloads

A Material-free and Cupertino-free Flutter design system built on package:flutter/widgets.dart. The successor to layrz_theme.

Repository (GitHub)
View/report issues

Topics

#design-system #flutter-ui #widget #theming #ui

License

unknown (license)

Dependencies

desktop_drop, emojis, file_picker, flutter, flutter_material_design_icons, flutter_mdi_remap, flutter_svg, markdown, pointer_interceptor, sync_scroll_controller, timezone, web

More

Packages that depend on layrz_ui