Moon Design System for Flutter

repository·main·Indexed 43 days ago

https://github.com/coingaming/moon_flutter

A Flutter-based design system providing a collection of UI components and theming capabilities. It includes specialized widgets such as MoonAccordion for expandable content, MoonAlert for notifications, and MoonAuthCode for OTP inputs, as well as MoonSquircleRadius for superellipse corner shapes and a comprehensive MoonTheme system for customizing colors and typography.

Tokens
9.7K
Snippets
28
Records
38
Agent score
52%

What's inside Moon Design System

  1. Customize iOS launch screen assets

    main

    To change the image displayed during the app's launch on iOS, you can replace the existing image files in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.

    Alternatively, you can manage these assets using Xcode:

    1. Open the iOS project in Xcode by running open ios/Runner.xcworkspace from your terminal.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog to replace the launch images.
    open ios/Runner.xcworkspace
  2. Apply Moon Design System theming and overrides

    main

    To customize the look and feel of Moon widgets, you can declare a MoonTokens variable and override specific values for colors or typography. You then inject this into your Flutter application by adding a MoonTheme extension to your ThemeData.

    1. Customize Tokens

    Use MoonTokens.light.copyWith to override colors and typography. For typography, you can use .apply() to modify font families, weights, or font variations.

    2. Override Specific Widget Themes

    If you need to target a specific widget (e.g., an Accordion), you can use MoonAccordionTheme within the MoonTheme.copyWith method to override its specific token set.

    3. Apply the Theme

    Pass the configured ThemeData to the theme property of your MaterialApp.

    // 1. Declare tokens and override values
    final lightTokens = MoonTokens.light.copyWith(
      colors: MoonColors.light.copyWith(
        piccolo: Colors.blue,
        textPrimary: Colors.amber,
      ),
      typography: MoonTypography.typography.copyWith(
        heading: MoonTypography.typography.heading.apply(
          fontFamily: "DMSans",
          fontWeightDelta: -1,
          fontVariations: [const FontVariation('wght', 500)],
        ),
      ),
    );
    
    // 2. Override specific widget theming (optional)
    final lightTheme = ThemeData.light().copyWith(
      extensions: <ThemeExtension<dynamic>>[
        MoonTheme(tokens: lightTokens).copyWith(
          accordionTheme: MoonAccordionTheme(tokens: lightTokens).copyWith(
            colors: MoonAccordionTheme(tokens: lightTokens).colors.copyWith(
                  backgroundColor: Colors.green,
                ),
          ),
        ),
      ],
    );
    
    // 3. Apply the declared theme
    return MaterialApp(
          title: 'Moon Design System example',
          theme: lightTheme,
          home: const HomePage(),
     );
  3. Use MoonBottomSheet for custom bottom sheet implementations

    main

    The MoonBottomSheet widget is the underlying component for Moon Design bottom sheets. While it is rarely used directly, it provides full control over drag behavior, expansion, and animation.

    Note: For most standard use cases, you should prefer using showMoonModalBottomSheet instead of instantiating MoonBottomSheet manually.

    Key properties:

    • enableDrag: Enables vertical dragging and swipe-to-dismiss.
    • isExpanded: If true, the sheet expands to full available width/height; if false, it resizes to fit content.
    • onClosing: A callback triggered when the closing process begins.
    • shouldClose: An optional Future<bool> callback used to intercept dismissal. If it returns false, the bottom sheet remains open. This is useful for preventing dismissal when user input is pending (e.g., form validation).
    • animationController: An AnimationController that drives the entrance and exit transitions.
    • scrollController: A ScrollController used to manage content scrolling within the sheet.
    // Example of the manual setup required for MoonBottomSheet
    final controller = MoonBottomSheet.createAnimationController(vsync, duration);
    final scrollController = ScrollController();
    
    MoonBottomSheet(
      animationController: controller,
      scrollController: scrollController,
      onClosing: () => print('Closing...'),
      shouldClose: () async {
        // Logic to decide if dismissal is allowed
        return true;
      },
      child: MyContentWidget(),
    );
  4. Configure text obscuring and peeking

    main

    For sensitive authentication codes, you can obscure the input text.

    • obscureText: Set to true to replace characters with the obscuringCharacter (defaults to •).
    • peekWhenObscuring: If true, the typed character will be briefly visible before being obscured.
    • peekDuration: Controls how long the character remains visible during a 'peek'.
    • obscuringCharacter: The specific character used for masking.
    • obscuringWidget: Allows you to provide a custom widget (like an icon) to replace the text when obscured.
  5. Configure MoonCheckbox tri-state behavior

    main

    When tristate is set to true, the value property can be true, false, or null.

    When a tri-state checkbox is tapped, the onChanged callback is invoked, and the value cycles through the following sequence:

    1. If current value is false $\rightarrow$ becomes true.
    2. If current value is true $\rightarrow$ becomes null (mixed state).
    3. If current value is null $\rightarrow$ becomes false.

    If tristate is false (default), the value must not be null.

    // Example of a tri-state checkbox
    MoonCheckbox(
      tristate: true,
      value: _myNullableBool, // can be true, false, or null
      onChanged: (bool? newValue) {
        setState(() => _myNullableBool = newValue);
      },
    );
  6. Configure MoonChipSize

    main

    The MoonChipSize enum allows you to quickly switch between two predefined size scales for the MoonChip widget. These sizes automatically adjust internal properties like padding, height, text style, and icon size based on the MoonTheme.

    • MoonChipSize.sm: Small size.
    • MoonChipSize.md: Medium size (default).

    If a specific size is not provided, the widget defaults to MoonChipSize.md or falls back to the theme's configured size.

    MoonChip(
      chipSize: MoonChipSize.sm,
      label: Text('Small Chip'),
    )
  7. Use MoonBaseControl for custom control behavior

    main

    MoonBaseControl is a base class used to implement common control behaviors in the Moon Design System. It handles focus, hover, press, and long-press states, as well as visual effects like pulse, scale, and focus highlights.

    When building a custom control, you can provide either a child or a builder. If you use the builder, you gain access to the current interaction states (isEnabled, isHovered, isFocused, isPressed), allowing you to style your widget dynamically based on user interaction.

    Key Interaction States via Builder:

    • isEnabled: True if onTap or onLongPress is provided.
    • isHovered: True when the mouse/pointer is over the control.
    • isFocused: True when the control has primary focus.
    • isPressed: True during a tap or long-press interaction.
    MoonBaseControl(
      onTap: () => print('Tapped!'),
      builder: (context, isEnabled, isHovered, isFocused, isPressed) {
        return Container(
          color: isPressed ? Colors.blue : Colors.grey,
          child: Text('Interactive Control'),
        );
      },
    );
  8. Manage MoonAccordion expansion state and grouping

    main

    To implement accordion groups (where expanding one item collapses others), use the identity value pattern:

    1. Assign a unique value to identityValue for each accordion instance.
    2. Pass the same value to groupIdentityValue for all accordions in that group.
    3. Use onExpansionChanged to react to state changes.

    Additionally, use initiallyExpanded to set the starting state, or maintainState (boolean) to determine if the children should be removed from the widget tree when the accordion is collapsed.

    MoonAccordion<String>(
      identityValue: 'section_1',
      groupIdentityValue: 'my_group',
      initiallyExpanded: true,
      maintainState: true,
      label: Text('Section 1'),
      children: [Text('Content')],
      onExpansionChanged: (value) => print('New active ID: $value'),
    );
  9. How MoonCarousel item indices work in loop mode

    main

    When loop is set to true, the itemBuilder provides two different indices to help you manage data and UI:

    1. itemIndex: The
  10. Use the MoonCarousel widget

    main

    The MoonCarousel widget is used to scroll through a collection of items. It supports horizontal and vertical scrolling, automatic playback (autoplay), infinite looping, and item centering.

    Key features:

    • Looping: When loop is true, the carousel provides two indices to the itemBuilder: itemIndex (the modded index for UI purposes) and realIndex (the actual index in the data set, essential for logic like jumping to a specific item).
    • Centering: If isCentered is true, the selected item is automatically aligned to the center of the viewport. This ignores the anchor property.
    • Anchoring: If isCentered is false, the anchor property (0.0 to 1.0) determines where the selected item is positioned in the viewport (0.0 is start, 1.0 is end).
    • Autoplay: Can be enabled via autoPlay. You can customize the delay, transition duration, and curve.
    MoonCarousel(
      itemCount: 10,
      itemExtent: 200.0,
      loop: true,
      onIndexChanged: (index) => print('Selected: $index'),
      itemBuilder: (context, itemIndex, realIndex) {
        return Container(
          width: 200.0,
          color: Colors.blue,
          child: Text('Item $realIndex'),
        );
      },
    );
  11. Align expanded content in MoonAccordion

    main

    The MoonAccordion provides two distinct alignment properties for the expanded content area:

    1. expandedAlignment: Controls the alignment of the entire content Column within the accordion's width. Defaults to Alignment.topCenter.
    2. expandedCrossAxisAlignment: Controls how individual children are aligned relative to each other within the Column. Defaults to CrossAxisAlignment.center.

    Note: expandedCrossAxisAlignment cannot be set to CrossAxisAlignment.baseline.

  12. Use the MoonCheckbox widget

    main

    MoonCheckbox is a widget used for binary or tri-state selection. It allows users to toggle between checked, unchecked, and (optionally) an indeterminate state.

    Key Features

    • Tri-state support: By setting tristate: true, the checkbox can accept a null value, which is visually represented by a dash (mixed state).
    • Customizable Colors: You can override activeColor, inactiveColor, borderColor, and checkColor directly on the widget or via the MoonTheme.
    • Tap Target: The tapAreaSizeValue property allows you to adjust the interactive area (defaults to 40).
    MoonCheckbox(
      value: _isChecked,
      tristate: false,
      onChanged: (bool? newValue) {
        setState(() {
          _isChecked = newValue;
        });
      },
    );