ui cleanup, new themes

This commit is contained in:
Christien Rioux 2024-07-06 20:09:18 -04:00
parent 94988718e8
commit 44fe198e5d
31 changed files with 1051 additions and 407 deletions

View file

@ -5,47 +5,82 @@ import 'package:flutter_chat_ui/flutter_chat_ui.dart';
import 'scale_scheme.dart';
ChatTheme makeChatTheme(ScaleScheme scale, TextTheme textTheme) =>
ChatTheme makeChatTheme(
ScaleScheme scale, ScaleConfig scaleConfig, TextTheme textTheme) =>
DefaultChatTheme(
primaryColor: scale.primaryScale.calloutBackground,
secondaryColor: scale.secondaryScale.calloutBackground,
primaryColor: scaleConfig.preferBorders
? scale.primaryScale.calloutText
: scale.primaryScale.calloutBackground,
secondaryColor: scaleConfig.preferBorders
? scale.secondaryScale.calloutText
: scale.secondaryScale.calloutBackground,
backgroundColor: scale.grayScale.appBackground,
messageBorderRadius: scaleConfig.borderRadiusScale * 16,
bubbleBorderSide: scaleConfig.preferBorders
? BorderSide(
color: scale.primaryScale.calloutBackground,
width: 2,
)
: null,
sendButtonIcon: Image.asset(
'assets/icon-send.png',
color: scale.primaryScale.borderText,
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
package: 'flutter_chat_ui',
),
inputBackgroundColor: Colors.blue,
inputBorderRadius: BorderRadius.zero,
inputTextDecoration: InputDecoration(
filled: true,
fillColor: scale.primaryScale.elementBackground,
filled: !scaleConfig.preferBorders,
fillColor: scale.primaryScale.subtleBackground,
isDense: true,
contentPadding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
border: const OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(8))),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(8))),
disabledBorder: OutlineInputBorder(
borderSide: scaleConfig.preferBorders
? BorderSide(color: scale.grayScale.border, width: 2)
: BorderSide.none,
borderRadius: BorderRadius.all(
Radius.circular(8 * scaleConfig.borderRadiusScale))),
enabledBorder: OutlineInputBorder(
borderSide: scaleConfig.preferBorders
? BorderSide(color: scale.primaryScale.border, width: 2)
: BorderSide.none,
borderRadius: BorderRadius.all(
Radius.circular(8 * scaleConfig.borderRadiusScale))),
focusedBorder: OutlineInputBorder(
borderSide: scaleConfig.preferBorders
? BorderSide(color: scale.primaryScale.border, width: 2)
: BorderSide.none,
borderRadius: BorderRadius.all(
Radius.circular(8 * scaleConfig.borderRadiusScale))),
),
inputContainerDecoration:
BoxDecoration(color: scale.primaryScale.border),
inputPadding: const EdgeInsets.all(9),
inputTextColor: scale.primaryScale.appText,
inputContainerDecoration: BoxDecoration(
border: scaleConfig.preferBorders
? Border(
top: BorderSide(color: scale.primaryScale.border, width: 2))
: null,
color: scaleConfig.preferBorders
? scale.primaryScale.elementBackground
: scale.primaryScale.border),
inputPadding: const EdgeInsets.all(12),
inputTextColor: !scaleConfig.preferBorders
? scale.primaryScale.appText
: scale.primaryScale.border,
attachmentButtonIcon: const Icon(Icons.attach_file),
sentMessageBodyTextStyle: TextStyle(
color: scale.primaryScale.calloutText,
fontSize: 16,
fontWeight: FontWeight.w500,
height: 1.5,
sentMessageBodyTextStyle: textTheme.bodyLarge!.copyWith(
color: scaleConfig.preferBorders
? scale.primaryScale.calloutBackground
: scale.primaryScale.calloutText,
),
sentEmojiMessageTextStyle: const TextStyle(
color: Colors.white,
fontSize: 64,
),
receivedMessageBodyTextStyle: TextStyle(
color: scale.secondaryScale.calloutText,
color: scaleConfig.preferBorders
? scale.secondaryScale.calloutBackground
: scale.secondaryScale.calloutText,
fontSize: 16,
fontWeight: FontWeight.w500,
height: 1.5,

View file

@ -5,11 +5,14 @@ import 'scale_color.dart';
import 'scale_input_decorator_theme.dart';
import 'scale_scheme.dart';
ScaleScheme _contrastScale(Brightness brightness) {
final back = brightness == Brightness.light ? Colors.white : Colors.black;
final front = brightness == Brightness.light ? Colors.black : Colors.white;
ScaleColor _contrastScaleColor(
{required Brightness brightness,
required Color frontColor,
required Color backColor}) {
final back = brightness == Brightness.light ? backColor : frontColor;
final front = brightness == Brightness.light ? frontColor : backColor;
final primaryScale = ScaleColor(
return ScaleColor(
appBackground: back,
subtleBackground: back,
elementBackground: back,
@ -28,21 +31,236 @@ ScaleScheme _contrastScale(Brightness brightness) {
calloutBackground: front,
calloutText: back,
);
return ScaleScheme(
primaryScale: primaryScale,
primaryAlphaScale: primaryScale,
secondaryScale: primaryScale,
tertiaryScale: primaryScale,
grayScale: primaryScale,
errorScale: primaryScale);
}
ThemeData contrastGenerator(Brightness brightness) {
final textTheme = makeRadixTextTheme(brightness);
final scaleScheme = _contrastScale(brightness);
final colorScheme = scaleScheme.toColorScheme(brightness);
final scaleConfig = ScaleConfig(useVisualIndicators: true);
const kMonoSpaceFontDisplay = 'Source Code Pro';
const kMonoSpaceFontText = 'Source Code Pro';
TextTheme makeMonoSpaceTextTheme(Brightness brightness) =>
(brightness == Brightness.light)
? const TextTheme(
displayLarge: TextStyle(
debugLabel: 'blackMonoSpace displayLarge',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black54,
decoration: TextDecoration.none),
displayMedium: TextStyle(
debugLabel: 'blackMonoSpace displayMedium',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black54,
decoration: TextDecoration.none),
displaySmall: TextStyle(
debugLabel: 'blackMonoSpace displaySmall',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black54,
decoration: TextDecoration.none),
headlineLarge: TextStyle(
debugLabel: 'blackMonoSpace headlineLarge',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black54,
decoration: TextDecoration.none),
headlineMedium: TextStyle(
debugLabel: 'blackMonoSpace headlineMedium',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black54,
decoration: TextDecoration.none),
headlineSmall: TextStyle(
debugLabel: 'blackMonoSpace headlineSmall',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black87,
decoration: TextDecoration.none),
titleLarge: TextStyle(
debugLabel: 'blackMonoSpace titleLarge',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.black87,
decoration: TextDecoration.none),
titleMedium: TextStyle(
debugLabel: 'blackMonoSpace titleMedium',
fontFamily: kMonoSpaceFontText,
color: Colors.black87,
decoration: TextDecoration.none),
titleSmall: TextStyle(
debugLabel: 'blackMonoSpace titleSmall',
fontFamily: kMonoSpaceFontText,
color: Colors.black,
decoration: TextDecoration.none),
bodyLarge: TextStyle(
debugLabel: 'blackMonoSpace bodyLarge',
fontFamily: kMonoSpaceFontText,
color: Colors.black87,
decoration: TextDecoration.none),
bodyMedium: TextStyle(
debugLabel: 'blackMonoSpace bodyMedium',
fontFamily: kMonoSpaceFontText,
color: Colors.black87,
decoration: TextDecoration.none),
bodySmall: TextStyle(
debugLabel: 'blackMonoSpace bodySmall',
fontFamily: kMonoSpaceFontText,
color: Colors.black54,
decoration: TextDecoration.none),
labelLarge: TextStyle(
debugLabel: 'blackMonoSpace labelLarge',
fontFamily: kMonoSpaceFontText,
color: Colors.black87,
decoration: TextDecoration.none),
labelMedium: TextStyle(
debugLabel: 'blackMonoSpace labelMedium',
fontFamily: kMonoSpaceFontText,
color: Colors.black,
decoration: TextDecoration.none),
labelSmall: TextStyle(
debugLabel: 'blackMonoSpace labelSmall',
fontFamily: kMonoSpaceFontText,
color: Colors.black,
decoration: TextDecoration.none),
)
: const TextTheme(
displayLarge: TextStyle(
debugLabel: 'whiteMonoSpace displayLarge',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white70,
decoration: TextDecoration.none),
displayMedium: TextStyle(
debugLabel: 'whiteMonoSpace displayMedium',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white70,
decoration: TextDecoration.none),
displaySmall: TextStyle(
debugLabel: 'whiteMonoSpace displaySmall',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white70,
decoration: TextDecoration.none),
headlineLarge: TextStyle(
debugLabel: 'whiteMonoSpace headlineLarge',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white70,
decoration: TextDecoration.none),
headlineMedium: TextStyle(
debugLabel: 'whiteMonoSpace headlineMedium',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white70,
decoration: TextDecoration.none),
headlineSmall: TextStyle(
debugLabel: 'whiteMonoSpace headlineSmall',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white,
decoration: TextDecoration.none),
titleLarge: TextStyle(
debugLabel: 'whiteMonoSpace titleLarge',
fontFamily: kMonoSpaceFontDisplay,
color: Colors.white,
decoration: TextDecoration.none),
titleMedium: TextStyle(
debugLabel: 'whiteMonoSpace titleMedium',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
titleSmall: TextStyle(
debugLabel: 'whiteMonoSpace titleSmall',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
bodyLarge: TextStyle(
debugLabel: 'whiteMonoSpace bodyLarge',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
bodyMedium: TextStyle(
debugLabel: 'whiteMonoSpace bodyMedium',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
bodySmall: TextStyle(
debugLabel: 'whiteMonoSpace bodySmall',
fontFamily: kMonoSpaceFontText,
color: Colors.white70,
decoration: TextDecoration.none),
labelLarge: TextStyle(
debugLabel: 'whiteMonoSpace labelLarge',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
labelMedium: TextStyle(
debugLabel: 'whiteMonoSpace labelMedium',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
labelSmall: TextStyle(
debugLabel: 'whiteMonoSpace labelSmall',
fontFamily: kMonoSpaceFontText,
color: Colors.white,
decoration: TextDecoration.none),
);
ScaleScheme _contrastScaleScheme(
{required Brightness brightness,
required Color primaryFront,
required Color primaryBack,
required Color secondaryFront,
required Color secondaryBack,
required Color tertiaryFront,
required Color tertiaryBack,
required Color grayFront,
required Color grayBack,
required Color errorFront,
required Color errorBack}) =>
ScaleScheme(
primaryScale: _contrastScaleColor(
brightness: brightness,
frontColor: primaryFront,
backColor: primaryBack),
primaryAlphaScale: _contrastScaleColor(
brightness: brightness,
frontColor: primaryFront,
backColor: primaryBack),
secondaryScale: _contrastScaleColor(
brightness: brightness,
frontColor: secondaryFront,
backColor: secondaryBack),
tertiaryScale: _contrastScaleColor(
brightness: brightness,
frontColor: tertiaryFront,
backColor: tertiaryBack),
grayScale: _contrastScaleColor(
brightness: brightness, frontColor: grayFront, backColor: grayBack),
errorScale: _contrastScaleColor(
brightness: brightness,
frontColor: errorFront,
backColor: errorBack));
ThemeData contrastGenerator({
required Brightness brightness,
required ScaleConfig scaleConfig,
required Color primaryFront,
required Color primaryBack,
required Color secondaryFront,
required Color secondaryBack,
required Color tertiaryFront,
required Color tertiaryBack,
required Color grayFront,
required Color grayBack,
required Color errorFront,
required Color errorBack,
TextTheme? customTextTheme,
}) {
final textTheme = customTextTheme ?? makeRadixTextTheme(brightness);
final scaleScheme = _contrastScaleScheme(
brightness: brightness,
primaryFront: primaryFront,
primaryBack: primaryBack,
secondaryFront: secondaryFront,
secondaryBack: secondaryBack,
tertiaryFront: tertiaryFront,
tertiaryBack: tertiaryBack,
grayFront: grayFront,
grayBack: grayBack,
errorFront: errorFront,
errorBack: errorBack,
);
final colorScheme = scaleScheme.toColorScheme(
brightness,
);
final themeData = ThemeData.from(
colorScheme: colorScheme, textTheme: textTheme, useMaterial3: true);
@ -50,10 +268,11 @@ ThemeData contrastGenerator(Brightness brightness) {
bottomSheetTheme: themeData.bottomSheetTheme.copyWith(
elevation: 0,
modalElevation: 0,
shape: const RoundedRectangleBorder(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)))),
topLeft: Radius.circular(16 * scaleConfig.borderRadiusScale),
topRight:
Radius.circular(16 * scaleConfig.borderRadiusScale)))),
canvasColor: scaleScheme.primaryScale.subtleBackground,
chipTheme: themeData.chipTheme.copyWith(
backgroundColor: scaleScheme.primaryScale.elementBackground,
@ -69,13 +288,15 @@ ThemeData contrastGenerator(Brightness brightness) {
disabledForegroundColor: scaleScheme.grayScale.appText,
shape: RoundedRectangleBorder(
side: BorderSide(color: scaleScheme.primaryScale.border),
borderRadius: BorderRadius.circular(8))),
borderRadius:
BorderRadius.circular(8 * scaleConfig.borderRadiusScale))),
),
textSelectionTheme: TextSelectionThemeData(
cursorColor: scaleScheme.primaryScale.appText,
selectionColor: scaleScheme.primaryScale.appText.withAlpha(0x7F),
selectionHandleColor: scaleScheme.primaryScale.appText),
inputDecorationTheme: ScaleInputDecoratorTheme(scaleScheme, textTheme),
inputDecorationTheme:
ScaleInputDecoratorTheme(scaleScheme, scaleConfig, textTheme),
extensions: <ThemeExtension<dynamic>>[
scaleScheme,
scaleConfig,

View file

@ -604,7 +604,11 @@ ThemeData radixGenerator(Brightness brightness, RadixThemeColor themeColor) {
final radix = _radixScheme(brightness, themeColor);
final scaleScheme = radix.toScale();
final colorScheme = scaleScheme.toColorScheme(brightness);
final scaleConfig = ScaleConfig(useVisualIndicators: false);
final scaleConfig = ScaleConfig(
useVisualIndicators: false,
preferBorders: false,
borderRadiusScale: 1,
);
final themeData = ThemeData.from(
colorScheme: colorScheme, textTheme: textTheme, useMaterial3: true);
@ -654,8 +658,10 @@ ThemeData radixGenerator(Brightness brightness, RadixThemeColor themeColor) {
disabledForegroundColor: scaleScheme.grayScale.primary,
shape: RoundedRectangleBorder(
side: BorderSide(color: scaleScheme.primaryScale.border),
borderRadius: BorderRadius.circular(8))),
borderRadius:
BorderRadius.circular(8 * scaleConfig.borderRadiusScale))),
),
inputDecorationTheme: ScaleInputDecoratorTheme(scaleScheme, textTheme),
inputDecorationTheme:
ScaleInputDecoratorTheme(scaleScheme, scaleConfig, textTheme),
extensions: <ThemeExtension<dynamic>>[scaleScheme, scaleConfig]);
}

View file

@ -3,11 +3,13 @@ import 'package:flutter/material.dart';
import 'scale_scheme.dart';
class ScaleInputDecoratorTheme extends InputDecorationTheme {
ScaleInputDecoratorTheme(this._scaleScheme, this._textTheme)
ScaleInputDecoratorTheme(
this._scaleScheme, ScaleConfig scaleConfig, this._textTheme)
: super(
border: OutlineInputBorder(
borderSide: BorderSide(color: _scaleScheme.primaryScale.border),
borderRadius: BorderRadius.circular(8)),
borderRadius:
BorderRadius.circular(8 * scaleConfig.borderRadiusScale)),
contentPadding: const EdgeInsets.all(8),
labelStyle: TextStyle(
color: _scaleScheme.primaryScale.subtleText.withAlpha(127)),
@ -16,7 +18,8 @@ class ScaleInputDecoratorTheme extends InputDecorationTheme {
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: _scaleScheme.primaryScale.hoverBorder, width: 2),
borderRadius: BorderRadius.circular(8)));
borderRadius:
BorderRadius.circular(8 * scaleConfig.borderRadiusScale)));
final ScaleScheme _scaleScheme;
final TextTheme _textTheme;

View file

@ -1,3 +1,6 @@
import 'dart:ui';
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import 'scale_color.dart';
@ -97,7 +100,7 @@ class ScaleScheme extends ThemeExtension<ScaleScheme> {
onSurfaceVariant: secondaryScale.primaryText, // ?? reviewed a little
outline: primaryScale.border,
outlineVariant: secondaryScale.border,
shadow: const Color(0xFF000000),
shadow: primaryScale.primary.darken(80),
//scrim: primaryScale.background,
// inverseSurface: primaryScale.subtleText,
// onInverseSurface: primaryScale.subtleBackground,
@ -109,16 +112,24 @@ class ScaleScheme extends ThemeExtension<ScaleScheme> {
class ScaleConfig extends ThemeExtension<ScaleConfig> {
ScaleConfig({
required this.useVisualIndicators,
required this.preferBorders,
required this.borderRadiusScale,
});
final bool useVisualIndicators;
final bool preferBorders;
final double borderRadiusScale;
@override
ScaleConfig copyWith({
bool? useVisualIndicators,
bool? preferBorders,
double? borderRadiusScale,
}) =>
ScaleConfig(
useVisualIndicators: useVisualIndicators ?? this.useVisualIndicators,
preferBorders: preferBorders ?? this.preferBorders,
borderRadiusScale: borderRadiusScale ?? this.borderRadiusScale,
);
@override
@ -127,8 +138,10 @@ class ScaleConfig extends ThemeExtension<ScaleConfig> {
return this;
}
return ScaleConfig(
useVisualIndicators:
t < .5 ? useVisualIndicators : other.useVisualIndicators,
);
useVisualIndicators:
t < .5 ? useVisualIndicators : other.useVisualIndicators,
preferBorders: t < .5 ? preferBorders : other.preferBorders,
borderRadiusScale:
lerpDouble(borderRadiusScale, other.borderRadiusScale, t) ?? 1);
}
}

View file

@ -64,13 +64,13 @@ class SliderTile extends StatelessWidget {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final tileColor = scale.scale(!disabled ? tileScale : ScaleKind.gray);
final scalecfg = theme.extension<ScaleConfig>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
final borderColor = selected ? tileColor.hoverBorder : tileColor.border;
final backgroundColor = scalecfg.useVisualIndicators && !selected
final backgroundColor = scaleConfig.useVisualIndicators && !selected
? tileColor.borderText
: borderColor;
final textColor = scalecfg.useVisualIndicators && !selected
final textColor = scaleConfig.useVisualIndicators && !selected
? borderColor
: tileColor.borderText;
@ -79,10 +79,11 @@ class SliderTile extends StatelessWidget {
decoration: ShapeDecoration(
color: backgroundColor,
shape: RoundedRectangleBorder(
side: scalecfg.useVisualIndicators
side: scaleConfig.useVisualIndicators
? BorderSide(width: 2, color: borderColor, strokeAlign: 0)
: BorderSide.none,
borderRadius: BorderRadius.circular(8),
borderRadius:
BorderRadius.circular(8 * scaleConfig.borderRadiusScale),
)),
child: Slidable(
// Specify a key if the Slidable is dismissible.
@ -95,12 +96,12 @@ class SliderTile extends StatelessWidget {
.map(
(a) => SlidableAction(
onPressed: disabled ? null : a.onPressed,
backgroundColor: scalecfg.useVisualIndicators
backgroundColor: scaleConfig.useVisualIndicators
? (selected
? tileColor.borderText
: tileColor.border)
: scale.scale(a.actionScale).primary,
foregroundColor: scalecfg.useVisualIndicators
foregroundColor: scaleConfig.useVisualIndicators
? (selected
? tileColor.border
: tileColor.borderText)
@ -118,12 +119,12 @@ class SliderTile extends StatelessWidget {
.map(
(a) => SlidableAction(
onPressed: disabled ? null : a.onPressed,
backgroundColor: scalecfg.useVisualIndicators
backgroundColor: scaleConfig.useVisualIndicators
? (selected
? tileColor.borderText
: tileColor.border)
: scale.scale(a.actionScale).primary,
foregroundColor: scalecfg.useVisualIndicators
foregroundColor: scaleConfig.useVisualIndicators
? (selected
? tileColor.border
: tileColor.borderText)
@ -134,7 +135,7 @@ class SliderTile extends StatelessWidget {
)
.toList()),
child: Padding(
padding: scalecfg.useVisualIndicators
padding: scaleConfig.useVisualIndicators
? EdgeInsets.zero
: const EdgeInsets.fromLTRB(0, 2, 0, 2),
child: ListTile(

View file

@ -5,6 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import '../views/widget_helpers.dart';
import 'contrast_generator.dart';
import 'radix_generator.dart';
import 'scale_scheme.dart';
part 'theme_preference.freezed.dart';
part 'theme_preference.g.dart';
@ -37,6 +38,7 @@ enum ColorPreference {
lime,
grim,
// Accessible Colors
elite,
contrast;
factory ColorPreference.fromJson(dynamic j) =>
@ -63,7 +65,7 @@ class ThemePreferences with _$ThemePreferences {
}
extension ThemePreferencesExt on ThemePreferences {
/// Get material 'ThemeData' for existinb
/// Get material 'ThemeData' for existing theme
ThemeData themeData() {
late final Brightness brightness;
switch (brightnessPreference) {
@ -83,8 +85,60 @@ extension ThemePreferencesExt on ThemePreferences {
switch (colorPreference) {
// Special cases
case ColorPreference.contrast:
// xxx do contrastGenerator
themeData = contrastGenerator(brightness);
themeData = contrastGenerator(
brightness: brightness,
scaleConfig: ScaleConfig(
useVisualIndicators: true,
preferBorders: false,
borderRadiusScale: 1),
primaryFront: Colors.black,
primaryBack: Colors.white,
secondaryFront: Colors.black,
secondaryBack: Colors.white,
tertiaryFront: Colors.black,
tertiaryBack: Colors.white,
grayFront: Colors.black,
grayBack: Colors.white,
errorFront: Colors.black,
errorBack: Colors.white,
);
case ColorPreference.elite:
themeData = brightness == Brightness.light
? contrastGenerator(
brightness: Brightness.light,
scaleConfig: ScaleConfig(
useVisualIndicators: true,
preferBorders: true,
borderRadiusScale: 0.2),
primaryFront: const Color(0xFF000000),
primaryBack: const Color(0xFF00FF00),
secondaryFront: const Color(0xFF000000),
secondaryBack: const Color(0xFF00FFFF),
tertiaryFront: const Color(0xFF000000),
tertiaryBack: const Color(0xFFFF00FF),
grayFront: const Color(0xFF000000),
grayBack: const Color(0xFFFFFFFF),
errorFront: const Color(0xFFC0C0C0),
errorBack: const Color(0xFF0000FF),
customTextTheme: makeMonoSpaceTextTheme(Brightness.light))
: contrastGenerator(
brightness: Brightness.dark,
scaleConfig: ScaleConfig(
useVisualIndicators: true,
preferBorders: true,
borderRadiusScale: 0.5),
primaryFront: const Color(0xFF000000),
primaryBack: const Color(0xFF00FF00),
secondaryFront: const Color(0xFF000000),
secondaryBack: const Color(0xFF00FFFF),
tertiaryFront: const Color(0xFF000000),
tertiaryBack: const Color(0xFFFF00FF),
grayFront: const Color(0xFF000000),
grayBack: const Color(0xFFFFFFFF),
errorFront: const Color(0xFF0000FF),
errorBack: const Color(0xFFC0C0C0),
customTextTheme: makeMonoSpaceTextTheme(Brightness.dark),
);
// Generate from Radix
case ColorPreference.scarlet:
themeData = radixGenerator(brightness, RadixThemeColor.scarlet);

View file

@ -22,6 +22,7 @@ List<DropdownMenuItem<dynamic>> _getThemeDropdownItems() {
ColorPreference.eggplant: translate('themes.eggplant'),
ColorPreference.lime: translate('themes.lime'),
ColorPreference.grim: translate('themes.grim'),
ColorPreference.elite: translate('themes.elite'),
ColorPreference.contrast: translate('themes.contrast')
};

View file

@ -11,12 +11,14 @@ class StyledDialog extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
final textTheme = theme.textTheme;
return AlertDialog(
elevation: 0,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(16 * scaleConfig.borderRadiusScale)),
),
contentPadding: const EdgeInsets.all(4),
backgroundColor: scale.primaryScale.dialogBorder,
@ -31,12 +33,14 @@ class StyledDialog extends StatelessWidget {
decoration: ShapeDecoration(
color: scale.primaryScale.border,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16))),
borderRadius: BorderRadius.circular(
16 * scaleConfig.borderRadiusScale))),
child: DecoratedBox(
decoration: ShapeDecoration(
color: scale.primaryScale.appBackground,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12))),
borderRadius: BorderRadius.circular(
12 * scaleConfig.borderRadiusScale))),
child: child.paddingAll(0))));
}

View file

@ -0,0 +1,27 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import '../theme.dart';
class StyledScaffold extends StatelessWidget {
const StyledScaffold({required this.appBar, required this.body, super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
return clipBorder(
clipEnabled: true,
borderEnabled: scaleConfig.useVisualIndicators,
borderRadius: 16 * scaleConfig.borderRadiusScale,
borderColor: scale.primaryScale.border,
child: Scaffold(appBar: appBar, body: body, key: key))
.paddingAll(32);
}
////////////////////////////////////////////////////////////////////////////
final PreferredSizeWidget? appBar;
final Widget? body;
}

View file

@ -2,4 +2,5 @@ export 'brightness_preferences.dart';
export 'color_preferences.dart';
export 'scanner_error_widget.dart';
export 'styled_dialog.dart';
export 'styled_scaffold.dart';
export 'widget_helpers.dart';

View file

@ -132,7 +132,7 @@ void showErrorToast(BuildContext context, String message) {
contentPadding: const EdgeInsets.all(16),
primaryColor: scale.errorScale.elementBackground,
secondaryColor: scale.errorScale.calloutBackground,
borderRadius: 16,
borderRadius: 16 * scaleConfig.borderRadiusScale,
toastDuration: const Duration(seconds: 4),
animationDuration: const Duration(milliseconds: 1000),
displayBorder: scaleConfig.useVisualIndicators,
@ -152,7 +152,7 @@ void showInfoToast(BuildContext context, String message) {
contentPadding: const EdgeInsets.all(16),
primaryColor: scale.tertiaryScale.elementBackground,
secondaryColor: scale.tertiaryScale.calloutBackground,
borderRadius: 16,
borderRadius: 16 * scaleConfig.borderRadiusScale,
toastDuration: const Duration(seconds: 2),
animationDuration: const Duration(milliseconds: 500),
displayBorder: scaleConfig.useVisualIndicators,
@ -170,13 +170,15 @@ Widget styledTitleContainer({
}) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
final textTheme = theme.textTheme;
return DecoratedBox(
decoration: ShapeDecoration(
color: borderColor ?? scale.primaryScale.border,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
borderRadius:
BorderRadius.circular(16 * scaleConfig.borderRadiusScale),
)),
child: Column(children: [
Text(
@ -189,7 +191,8 @@ Widget styledTitleContainer({
color:
backgroundColor ?? scale.primaryScale.subtleBackground,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
borderRadius: BorderRadius.circular(
16 * scaleConfig.borderRadiusScale),
)),
child: child)
.paddingAll(4)
@ -207,15 +210,17 @@ Widget styledBottomSheet({
}) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
final textTheme = theme.textTheme;
return DecoratedBox(
decoration: ShapeDecoration(
color: borderColor ?? scale.primaryScale.dialogBorder,
shape: const RoundedRectangleBorder(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)))),
topLeft: Radius.circular(16 * scaleConfig.borderRadiusScale),
topRight:
Radius.circular(16 * scaleConfig.borderRadiusScale)))),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Text(
title,
@ -226,10 +231,12 @@ Widget styledBottomSheet({
decoration: ShapeDecoration(
color:
backgroundColor ?? scale.primaryScale.subtleBackground,
shape: const RoundedRectangleBorder(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)))),
topLeft: Radius.circular(
16 * scaleConfig.borderRadiusScale),
topRight: Radius.circular(
16 * scaleConfig.borderRadiusScale)))),
child: child)
.paddingLTRB(4, 4, 4, 0)
]));
@ -261,3 +268,25 @@ const grayColorFilter = ColorFilter.matrix(<double>[
1,
0,
]);
Widget clipBorder({
required bool clipEnabled,
required bool borderEnabled,
required double borderRadius,
required Color borderColor,
required Widget child,
}) =>
ClipRRect(
borderRadius: clipEnabled
? BorderRadius.circular(borderRadius)
: BorderRadius.zero,
child: DecoratedBox(
decoration: BoxDecoration(boxShadow: [
if (borderEnabled) BoxShadow(color: borderColor, spreadRadius: 2)
]),
child: ClipRRect(
borderRadius: clipEnabled
? BorderRadius.circular(borderRadius)
: BorderRadius.zero,
child: child,
)).paddingAll(clipEnabled && borderEnabled ? 2 : 0));