Iteo/theme_tailor

[Feature request] Custom override `ThemeExtension` Widget

definev opened this issue · 1 comments

Like other kind of ThemeData. eg: IconTheme, ChipTheme, etc.

we can create a widget for override ThemeExtension.

part of '../icon_button.dart';

@Tailor(
  encoders: [
    FiveTonedSaveDayColorThemeEncoder(),
    DoubleOrNullTailorEncoder(),
    EdgeInsetsOrNullTailorEncoder(),
  ],
)
@tailorMixin
class PrimaryIconButtonTheme extends ThemeExtension<PrimaryIconButtonTheme> with _$PrimaryIconButtonThemeTailorMixin {
  const PrimaryIconButtonTheme({
    required this.color,
    required this.radius,
    required this.padding,
    required this.size,
  });

  static final defaultPrimaryIconButtonTheme = PrimaryIconButtonTheme(
    color: SaveDayColors.defaultSaveDayColors.yellow,
    radius: null,
    padding: null,
    size: ButtonSize.s,
  );

  @override
  final FiveTonedSaveDayColor color;

  @override
  final double? radius;

  @override
  final EdgeInsets? padding;

  @override
  final ButtonSize size;
}

The generated code might look like this. I don't know what the most optimal way to do it is. Just my naive approach.

class PrimaryIconButtonThemeOverride extends StatelessWidget {
  const PrimaryIconButtonThemeOverride({
    super.key,
    required this.data,
    required this.child,
  });

  final PrimaryIconButtonTheme data;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final extensions = {...theme.extensions}..[PrimaryIconButtonTheme] = data;

    return Theme(
      data: theme.copyWith(extensions: extensions.values),
      child: child,
    );
  }
}

class AnimatedPrimaryIconButtonThemeOverride extends StatelessWidget {
  const AnimatedPrimaryIconButtonThemeOverride({
    super.key,
    required this.data,
    required this.child,
  });

  final PrimaryIconButtonTheme data;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final extensions = {...theme.extensions}..[PrimaryIconButtonTheme] = data;

    return AnimatedTheme(
      data: theme.copyWith(extensions: extensions.values),
      child: child,
    );
  }
}
Rongix commented

Hello, thanks for suggestion. I think it can be solved by the snipped below; Therefore I think it should not be added to the currently available packages for generator / annotation. I hope it helps!

class ThemeExtensionOverride extends StatelessWidget {
  const ThemeExtensionOverride({
    required this.themeExtensionOverride,
    required this.child,
    super.key,
  });

  final ThemeExtension themeExtensionOverride;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return AnimatedTheme(
      data: Theme.of(context).copyWith(
        extensions: {
          ...Theme.of(context).extensions.values,
          themeExtensionOverride
        },
      ),
      child: child,
    );
  }
}

And you could use it like that:

@TailorMixinComponent()
class MixedTheme2 extends ThemeExtension<MixedTheme2>
    with _$MixedTheme2TailorMixin {
  const MixedTheme2({
    required this.foreground,
  });

  final Color foreground;
}

final newOverridenTheme = const ThemeExtensionOverride(
  themeExtensionOverride: MixedTheme2(foreground: Colors.pink),
  child: SizedBox.shrink(),
);