Skip to content

Instantly share code, notes, and snippets.

@hawkkiller
Last active November 5, 2022 23:07
Show Gist options
  • Save hawkkiller/b44bdd71ab007965f2d50c53d9eabcc9 to your computer and use it in GitHub Desktop.
Save hawkkiller/b44bdd71ab007965f2d50c53d9eabcc9 to your computer and use it in GitHub Desktop.

General Purpose

part 'theme.g.dart';

@ThemeGen(name: 'Light')
class _$AppThemeLight {}

@ThemeGen(name: 'Dark')
class _$AppThemeDark {}

@ThemeGenExtension(parent: _$AppThemeLight, name: 'AppColors')
class _$LightColors {
    // fields must be static const
    static const background = Color(0xFFEEEEEE);
    static const primary = Color(0xFFFFFFFF);
}

@ThemeGenExtension(parent: _$AppThemeDark, name: 'AppColors')
class _$DarkColors {
    // fields must be static const
    static const background = Color(0xFFEEEEED);
    static const primary = Color(0xFFFFFFFF);
}

@ThemeGenExtension(parent: _$AppThemeLight, name: 'FontStyles')
class _$LightFontStyles {
    // fields must be static const
    static const h1 = FontStyle(...);
    static const h2 = FontStyle(...);
}

@ThemeGenExtension(parent: _$AppThemeDark, name: 'FontStyles')
class _$DarkFontStyles {
    // fields must be static const
    static const h1 = FontStyle(...);
    static const h2 = FontStyle(...);
}

will generate

class AppTheme {
    static const lightExtensions = [
        AppColors.light(),
        FontStyles.light(),
    ];
    static const darkExtensions = [
        AppColors.dark(),
        FontStyles.dark(),
    ];
}

class AppColors extends ThemeExtension<AppColors> {
    AppColors({
        required this.background,
        required this.primary,
    });

    final Color background;
    final Color primary;

    factory AppColors.light({
        Color? background,
        Color? primary,
    }) => AppColors(
            background: background ?? _$LightColors.background,
            primary: primary ?? _$LightColors.primary,
        );

    factory AppColors.dark({
        Color? background,
        Color? primary,
    }) => AppColors(
            background: background ?? _$DarkColors.background,
            primary: primary ?? _$DarkColors.primary,
        );

    copywith.. 

    hashcode.. 

    operator==..

    toString..
    
    lerp
}

class FontStyles extends ThemeExtension<FontStyles> {
    FontStyles({
        required this.h1,
        required this.h2,
    });

    final FontStyle h1;
    final FontStyle h2;

    factory FontStyles.light({
        FontStyle? h1,
        FontStyle? h2,
    }) => FontStyles(
            h1: h1 ?? _$LightFontStyles.h1,
            h2: h2 ?? _$LightFontStyles.h2,
        );

    factory FontStyles.dark({
        FontStyle? h1,
        FontStyle? h2,
    }) => FontStyles(
            h1: h1 ?? _$DarkFontStyles.h1,
            h2: h2 ?? _$DarkFontStyles.h2,
        );

    copywith.. 

    hashcode.. 

    operator==..

    toString..
    
    lerp
}
@hawkkiller
Copy link
Author

image

@zs-dima
Copy link

zs-dima commented Oct 9, 2022

Purpose

@theme(
  colors: AppColorsLight,
  fonts: AppFontStylesLight,
  custom: [AppSizes, AppPaddingsLight...],
)
abstract class $AppThemeLight {}

@theme(
  colors: AppColorsDark,
  fonts: AppFontStylesDark,
  custom: [AppSizes, AppPaddingsDark...],
)
abstract class $AppThemeDark {}

class AppColorsLight {
  static const primary = Colors.white;
}

class AppFontStylesLight {
  static h1(AppColors colors) {
    return TextStyle(
      color: colors.primary,
    );
  }
}

@zs-dima
Copy link

zs-dima commented Oct 9, 2022

Alternative

@theme(
  name: 'Light', // Optional
  styles: [
    AppColorsLight,
    AppFontStylesLight,
    AppSizes,
    AppPaddingsLight,
    * * *
  ],
)
abstract class $AppThemeLight {}

@zs-dima
Copy link

zs-dima commented Oct 9, 2022

Think about adaptive themes - AppSizes/AppPaddings could depend on screen width for example:

final width = MediaQuery.of(context).size.width;
if (width < 600) return _themeSmall(colors);
if (width < 1024) return _themeMedium(colors);
return _themeLarge(colors);

Maybe pass context to the AppSizes/AppPaddings/etc styles if it is possible:

@theme(
  styles: [
    AppColorsLight,
    AppFontStylesLargeLight,
    AppSizesLarge,
    AppPaddingsLarge,
    * * *
  ],
  adaptive: {
    1024: [
       AppColorsLight,
       AppFontStylesMediumLight,
       AppSizesMedium,
       AppPaddingsMedium,
       * * *
    ],
    600: [
       AppColorsLight,
       AppFontStylesSmallLight,
       AppSizesSmall,
       AppPaddingsSmall,
       * * *
    ], 
  },
)
abstract class $AppThemeLight {}

@zs-dima
Copy link

zs-dima commented Nov 4, 2022

@theme(
  colors: _appColorsLight,
  styles: {
    AppFontStyles,
    AppSizesLarge,
    AppPaddingsLarge,
    * * *
  },
  adaptive: {
    1024: [
       AppSizesMedium,
       AppPaddingsMedium,
       * * *
    ],
    600: [
       AppFontStylesSmallLight,
       AppSizesSmall,
       AppPaddingsSmall,
       * * *
    ], 
)
abstract class $AppThemeLight {}

@theme(
  colors: _appColorsDark,
)
abstract class $AppThemeDark {}


const _appColorsLight = {
  #primary: Colors.white,
  #secondary: Colors.white,
};

const _appColorsDark = {
  #primary: Colors.black,
  #secondary: Colors.black,
};

class AppFontStyles : DefaultFontStyles {
  @override
  TextStyle display(AppColors colors) => TextStyle(color: colors.primary);

  @override
  TextStyle label(AppColors colors) => TextStyle(color: colors.primary);

  TextStyle customStyle(AppColors colors) => TextStyle(color: colors.primary);
}

@purplenoodlesoop
Copy link

Насчет интерфейсов были мысли немного по-другому применить.

class DarkPaddingsDefinition extends CustomExtension<double> {
  const DarkPaddingsDefinition();
  
  @override
  ExtensionData<double> get data => {#small: 4};
}

class DarkTheme extends $ThemeDefinition {
  @override
  ColorsDefinition get color => {#primary: Colors.white};
  
  @override
  StylesDefinition styles(DarkColors colors) => {#h1: TextStyle(color: colors.primary)};
  
  @override
  CustomDefinition get custom => const {#paddings: DarkPaddingsDefinition()};
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment