diff --git a/CHANGELOG.md b/CHANGELOG.md index df452e589..c786ca520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ Date format: DD/MM/YYYY +## [next] + +- Reworked the theme api ([#39](https://github.com/bdlukaa/fluent_ui/pull/39)): + - Removed the theme extension (`context.theme`). Use `FluentTheme.of(context)` instead + - `ButtonState` is now a class that can receive a value. It now allows lerping between values, making `AnimatedFluentTheme` possible. + + Here's an example of how to migrate your code: + + *Before*: `cursor: (_) => SystemMouseCursors.click,`\ + *Now*: `cursor: ButtonState.all(SystemMouseCursors.click),` + + - All theme datas and `AccentColor` have now a lerp method, in order to make `AnimatedFluentTheme` possible. + - Implemented `AnimatedFluentTheme`, in order to replace `AnimateContainer`s all around the library + - Dedicated theme for each theme data ([#37](https://github.com/bdlukaa/fluent_ui/issues/37)): + - IconTheme + - ButtonTheme + - RadioButtonTheme + - CheckboxTheme + - FocusTheme + - SplitButtonTheme + - ToggleButtonTheme + - ToggleSwitchTheme + - NavigationPaneTheme + - InfoBarTheme + - TooltipTheme + - DividerTheme + - ScrollbarTheme + - `DividerThemeData` now has `verticalMargin` and `horizontalMargin` instead of an axis callback. + - Updated button colors. + - Removed `animationDuration` and `animationCurve` from theme datas (except from `NavigationPaneThemeData`). + - Renamed `copyWith` to `merge` on theme datas (except from `ThemeData`) + - Fixed typo `standart` -> `standard` + ## [2.0.1] - [21/05/2021] - Minimal flutter version is now 2.2 @@ -294,7 +327,7 @@ This version provides the fix for [#5](https://github.com/bdlukaa/fluent_ui/issu - **NEW** `Style.fastAnimationDuration` (Defaults to 150ms) - **NEW** `Style.mediumAnimationDuration` (Defaults to 300ms) - **NEW** `Style.slowAnimationDuration` (Defaults to 500ms) - - Default `animationCurve` is now `Curves.easeInOut` (standart) instead of `Curves.linear` + - Default `animationCurve` is now `Curves.easeInOut` (standard) instead of `Curves.linear` - **BREAKING** Removed `Style.animationDuration` - Refactored Navigation Panel diff --git a/README.md b/README.md index 524f45532..1ca6cd86a 100644 --- a/README.md +++ b/README.md @@ -305,13 +305,11 @@ focusTheme: FocusStyle( ), ``` -To customize it to a single widget, wrap the widget in a `FluentTheme` widget, and change the options you want: +To customize it to a single widget, wrap the widget in a `FocusTheme` widget, and change the options you want: ```dart -FluentTheme( - theme: context.theme?.copyWith(ThemeData( - focusStyle: ..., // set your FocusStyle here - )), +FocusTheme( + data: FocusThemeData(...), child: Button( text: Text('Custom Focus Button'), onPressed: () {}, @@ -577,7 +575,7 @@ SplitButtonBar( text: Container( height: 24, width: 24, - color: context.theme.accentColor, + color: FluentTheme.of(context).accentColor, ), onPressed: () {}, ), diff --git a/example/lib/main.dart b/example/lib/main.dart index 467edebe5..6d244e5d6 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -201,8 +201,8 @@ class WindowButtons extends StatelessWidget { iconNormal: theme.inactiveColor, iconMouseDown: theme.inactiveColor, iconMouseOver: theme.inactiveColor, - mouseOver: ButtonThemeData.buttonColor(theme, [ButtonStates.hovering]), - mouseDown: ButtonThemeData.buttonColor(theme, [ButtonStates.pressing]), + mouseOver: ButtonThemeData.buttonColor(theme, {ButtonStates.hovering}), + mouseDown: ButtonThemeData.buttonColor(theme, {ButtonStates.pressing}), ); final closeButtonColors = WindowButtonColors( mouseOver: Colors.red, diff --git a/example/lib/screens/colors.dart b/example/lib/screens/colors.dart index 322f08d94..beae5b9fe 100644 --- a/example/lib/screens/colors.dart +++ b/example/lib/screens/colors.dart @@ -21,6 +21,12 @@ class ColorsPage extends StatelessWidget { @override Widget build(BuildContext context) { + const Divider divider = const Divider( + style: const DividerThemeData( + verticalMargin: const EdgeInsets.all(10), + horizontalMargin: const EdgeInsets.all(10), + ), + ); return ScaffoldPage( header: PageHeader(title: Text('Colors Showcase')), content: ListView( @@ -41,8 +47,7 @@ class ColorsPage extends StatelessWidget { }).toList(), ), ), - Divider( - style: DividerThemeData(margin: (axis) => EdgeInsets.all(10))), + divider, InfoLabel( label: 'Info Colors', child: Wrap( @@ -59,8 +64,7 @@ class ColorsPage extends StatelessWidget { ], ), ), - Divider( - style: DividerThemeData(margin: (axis) => EdgeInsets.all(10))), + divider, InfoLabel( label: 'All Shades', child: diff --git a/example/lib/screens/inputs.dart b/example/lib/screens/inputs.dart index 77bb08184..781a7fcd2 100644 --- a/example/lib/screens/inputs.dart +++ b/example/lib/screens/inputs.dart @@ -133,13 +133,13 @@ class _InputsPageState extends State { actions: [ Button( child: Text('Delete'), - autofocus: true, onPressed: () { // Delete file here }, ), Button( child: Text('Cancel'), + autofocus: true, onPressed: () => Navigator.pop(context), ), ], @@ -161,7 +161,7 @@ class _InputsPageState extends State { child: Container( color: states.isDisabled ? FluentTheme.of(context).accentColor.darker - : context.theme.accentColor, + : FluentTheme.of(context).accentColor, height: 24, width: 24, ), @@ -172,11 +172,7 @@ class _InputsPageState extends State { Button( child: SizedBox( height: splitButtonHeight, - child: Icon( - Icons.keyboard_arrow_down, - color: - disabled ? FluentTheme.of(context).disabledColor : null, - ), + child: Icon(Icons.keyboard_arrow_down), ), onPressed: disabled ? null : () {}, style: ButtonThemeData(padding: EdgeInsets.all(6)), diff --git a/example/lib/screens/others.dart b/example/lib/screens/others.dart index 857914ee1..55b645c69 100644 --- a/example/lib/screens/others.dart +++ b/example/lib/screens/others.dart @@ -59,7 +59,8 @@ class _OthersState extends State { opacity: 1.0, elevation: 4.0, child: Column(children: [ - Text('Surfaces', style: context.theme.typography.subtitle), + Text('Surfaces', + style: FluentTheme.of(context).typography.subtitle), Wrap(spacing: 10, runSpacing: 10, children: [ Tooltip( message: 'This is a tooltip', @@ -181,7 +182,8 @@ class _OthersState extends State { Container( height: 400, decoration: BoxDecoration( - border: Border.all(color: context.theme.accentColor, width: 1.0), + border: Border.all( + color: FluentTheme.of(context).accentColor, width: 1.0), ), child: TabView( currentIndex: currentIndex, diff --git a/example/lib/screens/settings.dart b/example/lib/screens/settings.dart index 79aebca0f..775a3a1bb 100644 --- a/example/lib/screens/settings.dart +++ b/example/lib/screens/settings.dart @@ -34,7 +34,7 @@ class Settings extends StatelessWidget { ), ]; final border = Border.all(color: Colors.grey[100], width: 0.5); - if (context.theme.brightness == Brightness.light) { + if (FluentTheme.of(context).brightness == Brightness.light) { return BoxDecoration( color: Colors.white, borderRadius: radius, @@ -60,7 +60,8 @@ class Settings extends StatelessWidget { ), controller: controller, children: [ - Text('Theme mode', style: context.theme.typography.subtitle), + Text('Theme mode', + style: FluentTheme.of(context).typography.subtitle), ...List.generate(ThemeMode.values.length, (index) { final mode = ThemeMode.values[index]; return RadioListTile( @@ -82,12 +83,12 @@ class Settings extends StatelessWidget { Text( 'ThemeMode.system may not work because MediaQuery.of(context).brightness is not implemented on windows yet.' '\nWe must wait until Flutter Desktop stable release', - style: context.theme.typography.caption, + style: FluentTheme.of(context).typography.caption, ), Text( 'Navigation Pane Display Mode', - style: context.theme.typography.subtitle, + style: FluentTheme.of(context).typography.subtitle, ), ...List.generate(PaneDisplayMode.values.length, (index) { final mode = PaneDisplayMode.values[index]; @@ -104,7 +105,8 @@ class Settings extends StatelessWidget { ), ); }), - Text('Accent Color', style: context.theme.typography.subtitle), + Text('Accent Color', + style: FluentTheme.of(context).typography.subtitle), Wrap(children: [ Tooltip( style: tooltipThemeData, diff --git a/lib/fluent_ui.dart b/lib/fluent_ui.dart index a8d6b9800..ad0fb1b3a 100644 --- a/lib/fluent_ui.dart +++ b/lib/fluent_ui.dart @@ -1,7 +1,6 @@ library fluent_ui; -export 'package:flutter/widgets.dart' - hide Icon, IconTheme, TextBox, IconThemeData; +export 'package:flutter/widgets.dart' hide TextBox; export 'package:flutter/material.dart' show Brightness, @@ -17,7 +16,8 @@ export 'package:flutter/material.dart' SelectableDayPredicate, DatePickerMode, ReorderableListView, - ReorderableDragStartListener; + ReorderableDragStartListener, + kThemeAnimationDuration; export 'src/app.dart'; export 'src/localization.dart'; @@ -49,7 +49,6 @@ export 'src/controls/surfaces/list_tile.dart'; export 'src/controls/surfaces/progress_indicators.dart'; export 'src/controls/surfaces/tooltip.dart'; -export 'src/controls/utils/icon.dart'; export 'src/controls/utils/divider.dart'; export 'src/controls/utils/scrollbar.dart'; diff --git a/lib/src/app.dart b/lib/src/app.dart index 155eb2728..40ef55c9a 100644 --- a/lib/src/app.dart +++ b/lib/src/app.dart @@ -405,9 +405,8 @@ class _FluentAppState extends State { Widget _builder(BuildContext context, Widget? child) { if (child == null) return SizedBox(); - final theme = this.theme(context); - return FluentTheme( - data: theme, + return AnimatedFluentTheme( + data: theme(context), child: child, ); } diff --git a/lib/src/controls/form/auto_suggest_box.dart b/lib/src/controls/form/auto_suggest_box.dart index e04ccd0aa..76136aa13 100644 --- a/lib/src/controls/form/auto_suggest_box.dart +++ b/lib/src/controls/form/auto_suggest_box.dart @@ -162,7 +162,8 @@ class _AutoSuggestBoxState extends State> { widget.onSelected?.call(value); focusNode.unfocus(); }, - title: Text('$value', style: context.maybeTheme?.typography.body), + title: + Text('$value', style: FluentTheme.maybeOf(context)?.typography.body), ); } @@ -180,12 +181,12 @@ class _AutoSuggestBoxState extends State> { child: Acrylic( width: box.size.width, decoration: BoxDecoration( - color: context.theme.acrylicBackgroundColor, + color: FluentTheme.of(context).acrylicBackgroundColor, borderRadius: BorderRadius.vertical( bottom: Radius.circular(4.0), ), border: Border.all( - color: context.theme.scaffoldBackgroundColor, + color: FluentTheme.of(context).scaffoldBackgroundColor, width: 0.8, ), ), @@ -206,8 +207,8 @@ class _AutoSuggestBoxState extends State> { ); } return AnimatedSwitcher( - duration: context.theme.fastAnimationDuration, - switchInCurve: context.theme.animationCurve, + duration: FluentTheme.of(context).fastAnimationDuration, + switchInCurve: FluentTheme.of(context).animationCurve, transitionBuilder: (child, animation) { if (child is ListView) { return child; diff --git a/lib/src/controls/form/combo_box.dart b/lib/src/controls/form/combo_box.dart index de95f7f4c..513ffa20b 100644 --- a/lib/src/controls/form/combo_box.dart +++ b/lib/src/controls/form/combo_box.dart @@ -11,7 +11,7 @@ import 'pickers/pickers.dart'; const Duration _kComboboxMenuDuration = Duration(milliseconds: 300); const double _kMenuItemHeight = kPickerHeight; -const EdgeInsets _kMenuItemPadding = EdgeInsets.symmetric(horizontal: 16.0); +const EdgeInsets _kMenuItemPadding = EdgeInsets.symmetric(horizontal: 12.0); const EdgeInsetsGeometry _kAlignedButtonPadding = EdgeInsets.only( top: 4.0, bottom: 4.0, @@ -1364,13 +1364,8 @@ class _ComboboxState extends State> with WidgetsBindingObserver { Expanded(child: innerItemsWidget) else innerItemsWidget, - FluentTheme( - data: context.theme.copyWith( - iconTheme: IconThemeData( - color: _iconColor, - size: widget.iconSize, - ), - ), + IconTheme( + data: IconThemeData(color: _iconColor, size: widget.iconSize), child: widget.icon ?? defaultIcon, ), ], @@ -1390,8 +1385,8 @@ class _ComboboxState extends State> with WidgetsBindingObserver { return Container( decoration: kPickerDecorationBuilder(context, () { if (_showHighlight) - return [ButtonStates.focused]; - else if (states.isFocused) return []; + return {ButtonStates.focused}; + else if (states.isFocused) return {}; return states; }()), child: result, diff --git a/lib/src/controls/form/pickers/date_picker.dart b/lib/src/controls/form/pickers/date_picker.dart index bb4cd97b0..6ede769b4 100644 --- a/lib/src/controls/form/pickers/date_picker.dart +++ b/lib/src/controls/form/pickers/date_picker.dart @@ -180,7 +180,7 @@ class _DatePickerState extends State { Widget picker = HoverButton( autofocus: widget.autofocus, focusNode: widget.focusNode, - cursor: (_) => widget.cursor, + cursor: ButtonState.all(widget.cursor), onPressed: () async { await popupKey.currentState?.openPopup(); _monthController?.dispose(); @@ -192,17 +192,18 @@ class _DatePickerState extends State { initControllers(); }, builder: (context, state) { - if (state.isDisabled) state = []; + if (state.isDisabled) state = {}; final divider = Divider( direction: Axis.vertical, style: DividerThemeData( - margin: (_) => EdgeInsets.zero, + verticalMargin: EdgeInsets.zero, + horizontalMargin: EdgeInsets.zero, thickness: 0.6, ), ); return AnimatedContainer( - duration: context.theme.fastAnimationDuration, - curve: context.theme.animationCurve, + duration: FluentTheme.of(context).fastAnimationDuration, + curve: FluentTheme.of(context).animationCurve, height: kPickerHeight, decoration: kPickerDecorationBuilder(context, state), child: Row(children: [ @@ -333,7 +334,10 @@ class __DatePickerContentPopUpState extends State<_DatePickerContentPopUp> { assert(debugCheckHasFluentTheme(context)); final divider = Divider( direction: Axis.vertical, - style: DividerThemeData(margin: (_) => EdgeInsets.zero), + style: DividerThemeData( + verticalMargin: EdgeInsets.zero, + horizontalMargin: EdgeInsets.zero, + ), ); return Acrylic( height: widget.height, @@ -350,7 +354,8 @@ class __DatePickerContentPopUpState extends State<_DatePickerContentPopUp> { alignment: Alignment.center, height: kOneLineTileHeight, child: ListTile( - tileColor: context.theme.accentColor.resolveFrom(context), + tileColor: + FluentTheme.of(context).accentColor.resolveFrom(context), ), ), ), @@ -538,7 +543,12 @@ class __DatePickerContentPopUpState extends State<_DatePickerContentPopUp> { ]), ]), ), - Divider(style: DividerThemeData(margin: (_) => EdgeInsets.zero)), + Divider( + style: DividerThemeData( + verticalMargin: EdgeInsets.zero, + horizontalMargin: EdgeInsets.zero, + ), + ), YesNoPickerControl( onChanged: () { Navigator.pop(context); diff --git a/lib/src/controls/form/pickers/pickers.dart b/lib/src/controls/form/pickers/pickers.dart index e873ef31e..b1c21701d 100644 --- a/lib/src/controls/form/pickers/pickers.dart +++ b/lib/src/controls/form/pickers/pickers.dart @@ -12,20 +12,20 @@ const kPopupHeight = kOneLineTileHeight * 10; BoxDecoration kPickerBackgroundDecoration(BuildContext context) => BoxDecoration( - color: context.theme.acrylicBackgroundColor, + color: FluentTheme.of(context).acrylicBackgroundColor, borderRadius: BorderRadius.circular(4.0), border: Border.all( - color: context.theme.scaffoldBackgroundColor, + color: FluentTheme.of(context).scaffoldBackgroundColor, width: 0.6, ), ); TextStyle? kPickerPopupTextStyle(BuildContext context) { - return context.theme.typography.body?.copyWith(fontSize: 16); + return FluentTheme.of(context).typography.body?.copyWith(fontSize: 16); } Decoration kPickerDecorationBuilder( - BuildContext context, List states) { + BuildContext context, Set states) { assert(debugCheckHasFluentTheme(context)); return BoxDecoration( borderRadius: BorderRadius.circular(4.0), @@ -33,11 +33,11 @@ Decoration kPickerDecorationBuilder( color: () { late Color color; if (states.isHovering) { - color = context.theme.inactiveColor; + color = FluentTheme.of(context).inactiveColor; } else if (states.isDisabled) { - color = context.theme.disabledColor; + color = FluentTheme.of(context).disabledColor; } else { - color = context.theme.inactiveColor.withOpacity(0.75); + color = FluentTheme.of(context).inactiveColor.withOpacity(0.75); } return color; }(), @@ -45,9 +45,9 @@ Decoration kPickerDecorationBuilder( ), color: () { if (states.isPressing) - return context.theme.disabledColor.withOpacity(0.2); + return FluentTheme.of(context).disabledColor.withOpacity(0.2); else if (states.isFocused) { - return context.theme.disabledColor.withOpacity(0.2); + return FluentTheme.of(context).disabledColor.withOpacity(0.2); } }(), ); @@ -70,40 +70,44 @@ class YesNoPickerControl extends StatelessWidget { ButtonThemeData style(BorderRadiusGeometry radius) { return ButtonThemeData( margin: EdgeInsets.zero, - decoration: (state) => BoxDecoration( - color: ButtonThemeData.uncheckedInputColor(context.theme, state), - borderRadius: radius, - ), + decoration: ButtonState.resolveWith((states) => BoxDecoration( + color: ButtonThemeData.uncheckedInputColor( + FluentTheme.of(context), states), + borderRadius: radius, + )), scaleFactor: 1.0, ); } - return Row(children: [ - Expanded( - child: SizedBox( - height: kOneLineTileHeight, - child: Button( - child: Icon(Icons.check), - onPressed: onChanged, - style: style(BorderRadius.only( - bottomLeft: Radius.circular(4.0), - )), + return FocusTheme( + data: FocusThemeData(renderOutside: false), + child: Row(children: [ + Expanded( + child: SizedBox( + height: kOneLineTileHeight, + child: Button( + child: Icon(Icons.check), + onPressed: onChanged, + style: style(BorderRadius.only( + bottomLeft: Radius.circular(4.0), + )), + ), ), ), - ), - Expanded( - child: SizedBox( - height: kOneLineTileHeight, - child: Button( - child: Icon(Icons.close), - onPressed: onCancel, - style: style(BorderRadius.only( - bottomRight: Radius.circular(4.0), - )), + Expanded( + child: SizedBox( + height: kOneLineTileHeight, + child: Button( + child: Icon(Icons.close), + onPressed: onCancel, + style: style(BorderRadius.only( + bottomRight: Radius.circular(4.0), + )), + ), ), ), - ), - ]); + ]), + ); } } @@ -122,47 +126,45 @@ class PickerNavigatorIndicator extends StatelessWidget { @override Widget build(BuildContext context) { assert(debugCheckHasFluentTheme(context)); - final style = ButtonThemeData( - padding: EdgeInsets.all(2.0), - margin: EdgeInsets.zero, - scaleFactor: 1.0, - decoration: (state) { - return BoxDecoration( - borderRadius: BorderRadius.circular(4.0), - color: ButtonThemeData.buttonColor(context.theme, state), - ); - }, - ); return HoverButton( onPressed: () {}, builder: (context, state) { - final isHovering = - state.isHovering || state.isPressing || state.isFocused; - return Stack(children: [ - child, - if (isHovering) - Positioned( - top: 0, - left: 0, - right: 0, - child: Button( - child: Center(child: Icon(Icons.keyboard_arrow_up, size: 14)), - onPressed: onBackward, - style: style, - ), - ), - if (isHovering) - Positioned( - bottom: 0, - left: 0, - right: 0, - child: Button( - child: Center(child: Icon(Icons.keyboard_arrow_down, size: 14)), - onPressed: onForward, - style: style, - ), - ), - ]); + final show = state.isHovering || state.isPressing || state.isFocused; + return ButtonTheme.merge( + data: ButtonThemeData( + padding: const EdgeInsets.all(2.0), + margin: EdgeInsets.zero, + scaleFactor: 1.0, + ), + child: FocusTheme( + data: FocusThemeData(renderOutside: false), + child: Stack(children: [ + child, + if (show) + Positioned( + top: 0, + left: 0, + right: 0, + child: Button( + child: + Center(child: Icon(Icons.keyboard_arrow_up, size: 14)), + onPressed: onBackward, + ), + ), + if (show) + Positioned( + bottom: 0, + left: 0, + right: 0, + child: Button( + child: Center( + child: Icon(Icons.keyboard_arrow_down, size: 14)), + onPressed: onForward, + ), + ), + ]), + ), + ); }, ); } @@ -175,8 +177,8 @@ void navigateSides( int amount, ) { assert(debugCheckHasFluentTheme(context)); - final duration = context.theme.fasterAnimationDuration; - final curve = context.theme.animationCurve; + final duration = FluentTheme.of(context).fasterAnimationDuration; + final curve = FluentTheme.of(context).animationCurve; if (forward) { final currentItem = controller.selectedItem; int to = currentItem + 1; diff --git a/lib/src/controls/form/pickers/time_picker.dart b/lib/src/controls/form/pickers/time_picker.dart index 061447ebf..8e519c220 100644 --- a/lib/src/controls/form/pickers/time_picker.dart +++ b/lib/src/controls/form/pickers/time_picker.dart @@ -151,7 +151,7 @@ class _TimePickerState extends State { Widget picker = HoverButton( focusNode: widget.focusNode, autofocus: widget.autofocus, - cursor: (_) => widget.cursor, + cursor: ButtonState.all(widget.cursor), onPressed: () async { await popupKey.currentState?.openPopup(); _hourController?.dispose(); @@ -166,13 +166,14 @@ class _TimePickerState extends State { final divider = Divider( direction: Axis.vertical, style: DividerThemeData( - margin: (_) => EdgeInsets.zero, + verticalMargin: EdgeInsets.zero, + horizontalMargin: EdgeInsets.zero, thickness: 0.6, ), ); return AnimatedContainer( - duration: context.theme.fastAnimationDuration, - curve: context.theme.animationCurve, + duration: FluentTheme.of(context).fastAnimationDuration, + curve: FluentTheme.of(context).animationCurve, height: kPickerHeight, decoration: kPickerDecorationBuilder(context, state), child: Row(children: [ @@ -289,10 +290,13 @@ class __TimePickerContentPopupState extends State<_TimePickerContentPopup> { assert(debugCheckHasFluentTheme(context)); final divider = Divider( direction: Axis.vertical, - style: DividerThemeData(margin: (_) => EdgeInsets.zero), + style: DividerThemeData( + verticalMargin: EdgeInsets.zero, + horizontalMargin: EdgeInsets.zero, + ), ); - final duration = context.theme.fasterAnimationDuration; - final curve = context.theme.animationCurve; + final duration = FluentTheme.of(context).fasterAnimationDuration; + final curve = FluentTheme.of(context).animationCurve; final hoursAmount = widget.use24Format ? 24 : 12; return Acrylic( height: widget.height, @@ -309,7 +313,8 @@ class __TimePickerContentPopupState extends State<_TimePickerContentPopup> { alignment: Alignment.center, height: kOneLineTileHeight, child: ListTile( - tileColor: context.theme.accentColor.resolveFrom(context), + tileColor: + FluentTheme.of(context).accentColor.resolveFrom(context), ), ), ), @@ -492,7 +497,12 @@ class __TimePickerContentPopupState extends State<_TimePickerContentPopup> { ]), ]), ), - Divider(style: DividerThemeData(margin: (_) => EdgeInsets.zero)), + Divider( + style: DividerThemeData( + verticalMargin: EdgeInsets.zero, + horizontalMargin: EdgeInsets.zero, + ), + ), YesNoPickerControl( onChanged: () { Navigator.pop(context); diff --git a/lib/src/controls/form/text_box.dart b/lib/src/controls/form/text_box.dart index c312f7886..060452ed4 100644 --- a/lib/src/controls/form/text_box.dart +++ b/lib/src/controls/form/text_box.dart @@ -611,22 +611,23 @@ class _TextBoxState extends State } final TextStyle textStyle = TextStyle( - color: context.theme.inactiveColor, + color: FluentTheme.of(context).inactiveColor, ); + final Brightness keyboardAppearance = + widget.keyboardAppearance ?? FluentTheme.of(context).brightness; + final Color cursorColor = FluentTheme.of(context).inactiveColor; + final Color disabledColor = FluentTheme.of(context).disabledColor; + final Color? decorationColor = widget.decoration.color; + final TextStyle placeholderStyle = widget.placeholderStyle ?? textStyle.copyWith( - color: context.theme.disabledColor, + color: !enabled + ? (decorationColor ?? disabledColor).basedOnLuminance() + : disabledColor, fontWeight: FontWeight.w400, ); - final Brightness keyboardAppearance = - widget.keyboardAppearance ?? context.theme.brightness; - final Color cursorColor = context.theme.inactiveColor; - final Color? disabledColor = context.theme.disabledColor; - - final Color? decorationColor = widget.decoration.color; - final BoxBorder? border = widget.decoration.border; Border? resolvedBorder = border as Border?; if (border is Border) { @@ -637,8 +638,8 @@ class _TextBoxState extends State style: enabled ? BorderStyle.solid : BorderStyle.none, width: (showActiveBorder ? 1 : null), color: (showActiveBorder - ? context.theme.accentColor - : context.theme.inactiveColor), + ? FluentTheme.of(context).accentColor + : FluentTheme.of(context).inactiveColor), ); } @@ -657,7 +658,8 @@ class _TextBoxState extends State color: enabled ? decorationColor : (decorationColor ?? disabledColor), ); - final Color selectionColor = context.theme.accentColor.withOpacity(0.2); + final Color selectionColor = + FluentTheme.of(context).accentColor.withOpacity(0.2); final Widget paddedEditable = Padding( padding: widget.padding, @@ -703,7 +705,7 @@ class _TextBoxState extends State cursorOffset: cursorOffset, paintCursorAboveText: false, autocorrectionTextRectColor: selectionColor, - backgroundCursorColor: context.theme.disabledColor, + backgroundCursorColor: disabledColor, selectionHeightStyle: widget.selectionHeightStyle, selectionWidthStyle: widget.selectionWidthStyle, scrollPadding: widget.scrollPadding, @@ -733,12 +735,10 @@ class _TextBoxState extends State child: IgnorePointer( ignoring: !enabled, child: AnimatedContainer( - duration: context.theme.mediumAnimationDuration, - curve: context.theme.animationCurve, + duration: FluentTheme.of(context).mediumAnimationDuration, + curve: FluentTheme.of(context).animationCurve, decoration: effectiveDecoration, - constraints: BoxConstraints( - minHeight: widget.minHeight ?? 0, - ), + constraints: BoxConstraints(minHeight: widget.minHeight ?? 0), child: _selectionGestureDetectorBuilder.buildGestureDetector( behavior: HitTestBehavior.translucent, child: Align( @@ -769,22 +769,22 @@ class _TextBoxState extends State }, ); - return FluentTheme( - data: context.theme.copyWith( - buttonTheme: ButtonThemeData( - margin: EdgeInsets.zero, - ).copyWith(widget.iconButtonThemeData), - iconTheme: IconThemeData(size: 18), + return ButtonTheme.merge( + data: ButtonThemeData( + margin: EdgeInsets.zero, + ).merge(widget.iconButtonThemeData), + child: IconTheme( + data: const IconThemeData(size: 18), + child: () { + if (widget.header != null) + return InfoLabel( + child: listener, + label: widget.header!, + labelStyle: widget.headerStyle, + ); + return listener; + }(), ), - child: () { - if (widget.header != null) - return InfoLabel( - child: listener, - label: widget.header!, - labelStyle: widget.headerStyle, - ); - return listener; - }(), ); } } diff --git a/lib/src/controls/inputs/button.dart b/lib/src/controls/inputs/button.dart index dceef285b..f348e02bf 100644 --- a/lib/src/controls/inputs/button.dart +++ b/lib/src/controls/inputs/button.dart @@ -1,3 +1,5 @@ +import 'dart:ui' show lerpDouble; + import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter/foundation.dart'; @@ -5,6 +7,9 @@ import 'package:flutter/rendering.dart'; import '../utils/hover_button.dart'; +/// The scale factor used by default on [Button] +const kButtonDefaultScaleFactor = 0.95; + enum _ButtonType { def, icon, toggle } /// A button gives the user a way to trigger an immediate action @@ -158,9 +163,7 @@ class _ButtonState extends State