From 939cbe5451fec4d872b42730a3e0e81c76c5347b Mon Sep 17 00:00:00 2001 From: Hixie Date: Thu, 1 Oct 2015 09:28:40 -0700 Subject: [PATCH] Have Flat buttons set their default text styles. Also, have dialog buttons use the accent colour. Also, generally rationalise some of this stuff to match Material better. --- examples/stocks/lib/stock_home.dart | 23 ++++++++ examples/stocks/lib/stock_menu.dart | 13 +++++ sky/packages/sky/lib/src/material/colors.dart | 16 ++++-- .../sky/lib/src/material/theme_data.dart | 15 ++++- .../sky/lib/src/material/typography.dart | 22 ++++---- .../sky/lib/src/widgets/date_picker.dart | 4 +- sky/packages/sky/lib/src/widgets/dialog.dart | 10 +++- .../sky/lib/src/widgets/flat_button.dart | 8 ++- .../sky/lib/src/widgets/framework.dart | 4 +- .../sky/lib/src/widgets/material.dart | 6 +- .../sky/lib/src/widgets/material_button.dart | 55 ++++++++++++++++++- .../sky/lib/src/widgets/raised_button.dart | 20 +++++-- 12 files changed, 161 insertions(+), 35 deletions(-) diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index 106f457a961..5d3bbcf7907 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart @@ -83,6 +83,29 @@ class StockHomeState extends State { ), new DrawerItem( icon: 'action/account_balance', + onPressed: () { + showDialog(config.navigator, (NavigatorState navigator) { + return new Dialog( + title: new Text('Not Implemented'), + content: new Text('This feature has not yet been implemented.'), + actions: [ + new FlatButton( + child: new Text('USE IT'), + enabled: false, + onPressed: () { + navigator.pop(false); + } + ), + new FlatButton( + child: new Text('OH WELL'), + onPressed: () { + navigator.pop(false); + } + ), + ] + ); + }); + }, child: new Text('Account Balance') ), new DrawerItem( diff --git a/examples/stocks/lib/stock_menu.dart b/examples/stocks/lib/stock_menu.dart index d5c1f95884c..c55e6465892 100644 --- a/examples/stocks/lib/stock_menu.dart +++ b/examples/stocks/lib/stock_menu.dart @@ -60,6 +60,19 @@ Future showStockMenu(NavigatorState navigator, { bool autorefresh, ValueChanged title: new Text('Not Implemented'), content: new Text('This feature has not yet been implemented.'), actions: [ + new FlatButton( + child: new Row([ + new Icon( + type: 'device/dvr', + size: 18 + ), + new Container( + width: 8.0 + ), + new Text('DUMP APP TO CONSOLE'), + ]), + onPressed: () { debugDumpApp(); } + ), new FlatButton( child: new Text('OH WELL'), onPressed: () { diff --git a/sky/packages/sky/lib/src/material/colors.dart b/sky/packages/sky/lib/src/material/colors.dart index b1af32f31e5..bde576a1df0 100644 --- a/sky/packages/sky/lib/src/material/colors.dart +++ b/sky/packages/sky/lib/src/material/colors.dart @@ -9,13 +9,17 @@ import 'dart:sky' show Color; class Colors { Colors._(); - static const white = const Color(0xFFFFFFFF); - static const black = const Color(0xFF000000); static const transparent = const Color(0x00000000); - static const white54 = const Color(0x8AFFFFFF); - static const white87 = const Color(0xDDFFFFFF); - static const black54 = const Color(0x8A000000); + + static const black = const Color(0xFF000000); static const black87 = const Color(0xDD000000); + static const black54 = const Color(0x8A000000); + static const black26 = const Color(0x42000000); // text of disabled flat button in light theme + static const black12 = const Color(0x1F000000); // background of disabled raised buttons in light theme + static const white = const Color(0xFFFFFFFF); + static const white70 = const Color(0xB3FFFFFF); + static const white30 = const Color(0x4DFFFFFF); // text of disabled flat button in dark theme + static const white12 = const Color(0x1FFFFFFF); // background of disabled raised buttons in dark theme static const Map red = const { 50: const Color(0xFFFFEBEE), @@ -355,7 +359,7 @@ class Colors { 100: const Color(0xFFF5F5F5), 200: const Color(0xFFEEEEEE), 300: const Color(0xFFE0E0E0), - 350: const Color(0xFFD6D6D6), // only for raised button while pressed or disabled + 350: const Color(0xFFD6D6D6), // only for raised button while pressed in Light theme 400: const Color(0xFFBDBDBD), 500: const Color(0xFF9E9E9E), 600: const Color(0xFF757575), diff --git a/sky/packages/sky/lib/src/material/theme_data.dart b/sky/packages/sky/lib/src/material/theme_data.dart index 4c45b163704..be3092fce6f 100644 --- a/sky/packages/sky/lib/src/material/theme_data.dart +++ b/sky/packages/sky/lib/src/material/theme_data.dart @@ -59,7 +59,11 @@ class ThemeData { factory ThemeData.dark() => new ThemeData(brightness: ThemeBrightness.dark); factory ThemeData.fallback() => new ThemeData.light(); + /// The brightness of the overall theme of the application. Used by widgets + /// like buttons to determine what color to pick when not using the primary or + /// accent color. final ThemeBrightness brightness; + final Map primarySwatch; final Color canvasColor; final Color cardColor; @@ -70,14 +74,21 @@ class ThemeData { final double hintOpacity; final TextTheme text; - Color _primaryColor; + /// The background colour for major parts of the app (toolbars, tab bars, etc) Color get primaryColor => _primaryColor; + Color _primaryColor; + /// The brightness of the primaryColor. Used to determine the colour of text and + /// icons placed on top of the primary color (e.g. toolbar text). final ThemeBrightness primaryColorBrightness; - Color _accentColor; + /// The foreground color for widgets (knobs, text, etc) Color get accentColor => _accentColor; + Color _accentColor; + /// The brightness of the accentColor. Used to determine the colour of text + /// and icons placed on top of the accent color (e.g. the icons on a floating + /// action button). final ThemeBrightness accentColorBrightness; bool operator==(Object other) { diff --git a/sky/packages/sky/lib/src/material/typography.dart b/sky/packages/sky/lib/src/material/typography.dart index 37a26268522..599a273b993 100644 --- a/sky/packages/sky/lib/src/material/typography.dart +++ b/sky/packages/sky/lib/src/material/typography.dart @@ -28,17 +28,17 @@ class TextTheme { button = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic); const TextTheme._white() - : display4 = const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.white54, textBaseline: TextBaseline.alphabetic), - display3 = const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, color: Colors.white54, textBaseline: TextBaseline.alphabetic), - display2 = const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.white54, height: 48.0 / 45.0, textBaseline: TextBaseline.alphabetic), - display1 = const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, color: Colors.white54, height: 40.0 / 34.0, textBaseline: TextBaseline.alphabetic), - headline = const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.white87, height: 32.0 / 24.0, textBaseline: TextBaseline.alphabetic), - title = const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w500, color: Colors.white87, height: 28.0 / 20.0, textBaseline: TextBaseline.alphabetic), - subhead = const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white87, height: 24.0 / 16.0, textBaseline: TextBaseline.alphabetic), - body2 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white87, height: 24.0 / 14.0, textBaseline: TextBaseline.alphabetic), - body1 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.white87, height: 20.0 / 14.0, textBaseline: TextBaseline.alphabetic), - caption = const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white54, textBaseline: TextBaseline.alphabetic), - button = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white87, textBaseline: TextBaseline.alphabetic); + : display4 = const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.white70, textBaseline: TextBaseline.alphabetic), + display3 = const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic), + display2 = const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.white70, height: 48.0 / 45.0, textBaseline: TextBaseline.alphabetic), + display1 = const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, color: Colors.white70, height: 40.0 / 34.0, textBaseline: TextBaseline.alphabetic), + headline = const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.white, height: 32.0 / 24.0, textBaseline: TextBaseline.alphabetic), + title = const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w500, color: Colors.white, height: 28.0 / 20.0, textBaseline: TextBaseline.alphabetic), + subhead = const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white, height: 24.0 / 16.0, textBaseline: TextBaseline.alphabetic), + body2 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white, height: 24.0 / 14.0, textBaseline: TextBaseline.alphabetic), + body1 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.white, height: 20.0 / 14.0, textBaseline: TextBaseline.alphabetic), + caption = const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic), + button = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white, textBaseline: TextBaseline.alphabetic); final TextStyle display4; final TextStyle display3; diff --git a/sky/packages/sky/lib/src/widgets/date_picker.dart b/sky/packages/sky/lib/src/widgets/date_picker.dart index 56f4ed7fb32..5f428d65e37 100644 --- a/sky/packages/sky/lib/src/widgets/date_picker.dart +++ b/sky/packages/sky/lib/src/widgets/date_picker.dart @@ -135,8 +135,8 @@ class _DatePickerHeader extends StatelessComponent { break; case ThemeBrightness.dark: headerTheme = Typography.white; - dayColor = mode == DatePickerMode.day ? Colors.white87 : Colors.white54; - yearColor = mode == DatePickerMode.year ? Colors.white87 : Colors.white54; + dayColor = mode == DatePickerMode.day ? Colors.white : Colors.white70; + yearColor = mode == DatePickerMode.year ? Colors.white : Colors.white70; break; } TextStyle dayStyle = headerTheme.display3.copyWith(color: dayColor, height: 1.0, fontSize: 100.0); diff --git a/sky/packages/sky/lib/src/widgets/dialog.dart b/sky/packages/sky/lib/src/widgets/dialog.dart index 88b44ade598..202db68580e 100644 --- a/sky/packages/sky/lib/src/widgets/dialog.dart +++ b/sky/packages/sky/lib/src/widgets/dialog.dart @@ -12,6 +12,7 @@ import 'package:sky/src/widgets/focus.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/gesture_detector.dart'; import 'package:sky/src/widgets/material.dart'; +import 'package:sky/src/widgets/material_button.dart'; import 'package:sky/src/widgets/navigator.dart'; import 'package:sky/src/widgets/scrollable.dart'; import 'package:sky/src/widgets/theme.dart'; @@ -95,9 +96,12 @@ class Dialog extends StatelessComponent { } if (actions != null) { - dialogBody.add(new Container( - child: new Row(actions, - justifyContent: FlexJustifyContent.end + dialogBody.add(new ButtonTheme( + color: ButtonColor.accent, + child: new Container( + child: new Row(actions, + justifyContent: FlexJustifyContent.end + ) ) )); } diff --git a/sky/packages/sky/lib/src/widgets/flat_button.dart b/sky/packages/sky/lib/src/widgets/flat_button.dart index 164b087f590..238879bfba6 100644 --- a/sky/packages/sky/lib/src/widgets/flat_button.dart +++ b/sky/packages/sky/lib/src/widgets/flat_button.dart @@ -24,6 +24,9 @@ class FlatButton extends MaterialButton { } class _FlatButtonState extends MaterialButtonState { + + int get level => 0; + Color getColor(BuildContext context) { if (!config.enabled || !highlight) return null; @@ -35,5 +38,8 @@ class _FlatButtonState extends MaterialButtonState { } } - int get level => 0; + ThemeBrightness getColorBrightness(BuildContext context) { + return Theme.of(context).brightness; + } + } diff --git a/sky/packages/sky/lib/src/widgets/framework.dart b/sky/packages/sky/lib/src/widgets/framework.dart index dd36a8600ba..e1fc342b19d 100644 --- a/sky/packages/sky/lib/src/widgets/framework.dart +++ b/sky/packages/sky/lib/src/widgets/framework.dart @@ -192,7 +192,7 @@ abstract class Widget { if (data.isEmpty) return '$name'; return '$name(${data.join("; ")})'; - } + } void debugFillDescription(List description) { } } @@ -798,7 +798,7 @@ abstract class Element implements BuildContext { String toString() { final List data = []; debugFillDescription(data); - final String name = widget != null ? '$widget' : '[$runtimeType]'; + final String name = widget != null ? '${widget.runtimeType}' : '[$runtimeType]'; return '$name(${data.join("; ")})'; } diff --git a/sky/packages/sky/lib/src/widgets/material.dart b/sky/packages/sky/lib/src/widgets/material.dart index 138994cfd75..4f42d63abd3 100644 --- a/sky/packages/sky/lib/src/widgets/material.dart +++ b/sky/packages/sky/lib/src/widgets/material.dart @@ -25,7 +25,8 @@ class Material extends StatelessComponent { this.child, this.type: MaterialType.card, this.level: 0, - this.color + this.color, + this.textStyle }) : super(key: key) { assert(level != null); } @@ -34,6 +35,7 @@ class Material extends StatelessComponent { final MaterialType type; final int level; final Color color; + final TextStyle textStyle; Color _getBackgroundColor(BuildContext context) { if (color != null) @@ -52,7 +54,7 @@ class Material extends StatelessComponent { Widget contents = child; if (child != null) { contents = new DefaultTextStyle( - style: Theme.of(context).text.body1, + style: textStyle ?? Theme.of(context).text.body1, child: contents ); if (_kEdges[type] != null) { diff --git a/sky/packages/sky/lib/src/widgets/material_button.dart b/sky/packages/sky/lib/src/widgets/material_button.dart index 4a21d4ebe82..cd01b0df435 100644 --- a/sky/packages/sky/lib/src/widgets/material_button.dart +++ b/sky/packages/sky/lib/src/widgets/material_button.dart @@ -3,17 +3,42 @@ // found in the LICENSE file. import 'package:sky/gestures.dart'; +import 'package:sky/material.dart'; import 'package:sky/src/widgets/basic.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/ink_well.dart'; import 'package:sky/src/widgets/material.dart'; +import 'package:sky/src/widgets/theme.dart'; +enum ButtonColor { normal, accent } + +class ButtonTheme extends InheritedWidget { + ButtonTheme({ + Key key, + this.color, + Widget child + }) : super(key: key, child: child) { + assert(child != null); + } + + final ButtonColor color; + + static ButtonColor of(BuildContext context) { + ButtonTheme result = context.inheritedWidgetOfType(ButtonTheme); + return result?.color ?? ButtonColor.normal; + } + + bool updateShouldNotify(ButtonTheme old) => color != old.color; +} + +/// Base class for buttons in the Material theme. /// Rather than using this class directly, please use FlatButton or RaisedButton. abstract class MaterialButton extends StatefulComponent { MaterialButton({ Key key, this.child, this.enabled: true, + this.textColor, this.onPressed }) : super(key: key) { assert(enabled != null); @@ -21,15 +46,40 @@ abstract class MaterialButton extends StatefulComponent { final Widget child; final bool enabled; + final ButtonColor textColor; final GestureTapCallback onPressed; } abstract class MaterialButtonState extends State { bool highlight = false; - Color getColor(BuildContext context); int get level; + Color getColor(BuildContext context); + ThemeBrightness getColorBrightness(BuildContext context); + + Color getTextColor(BuildContext context) { + if (config.enabled) { + switch (config.textColor ?? ButtonTheme.of(context)) { + case ButtonColor.accent: + return Theme.of(context).accentColor; + case ButtonColor.normal: + switch (getColorBrightness(context)) { + case ThemeBrightness.light: + return Colors.black87; + case ThemeBrightness.dark: + return Colors.white; + } + } + } + switch (getColorBrightness(context)) { + case ThemeBrightness.light: + return Colors.black26; + case ThemeBrightness.dark: + return Colors.white30; + } + } + void _handleHighlightChanged(bool value) { setState(() { highlight = value; @@ -41,7 +91,7 @@ abstract class MaterialButtonState extends State { padding: new EdgeDims.symmetric(horizontal: 8.0), child: new Center( shrinkWrap: ShrinkWrap.width, - child: config.child // TODO(ianh): figure out a way to compell the child to have gray text when disabled... + child: config.child ) ); return new Container( @@ -52,6 +102,7 @@ abstract class MaterialButtonState extends State { type: MaterialType.button, level: level, color: getColor(context), + textStyle: Theme.of(context).text.button.copyWith(color: getTextColor(context)), child: new InkWell( onTap: config.enabled ? config.onPressed : null, onHighlightChanged: config.enabled ? _handleHighlightChanged : null, diff --git a/sky/packages/sky/lib/src/widgets/raised_button.dart b/sky/packages/sky/lib/src/widgets/raised_button.dart index 6d5e5487c23..b6db80487a8 100644 --- a/sky/packages/sky/lib/src/widgets/raised_button.dart +++ b/sky/packages/sky/lib/src/widgets/raised_button.dart @@ -26,6 +26,9 @@ class RaisedButton extends MaterialButton { } class _RaisedButtonState extends MaterialButtonState { + + int get level => config.enabled ? (highlight ? 2 : 1) : 0; + Color getColor(BuildContext context) { if (config.enabled) { switch (Theme.of(context).brightness) { @@ -36,16 +39,25 @@ class _RaisedButtonState extends MaterialButtonState { return Colors.grey[300]; break; case ThemeBrightness.dark: + Map swatch = Theme.of(context).primarySwatch ?? Colors.blue; if (highlight) - return Theme.of(context).primarySwatch[700]; + return swatch[700]; else - return Theme.of(context).primarySwatch[600]; + return swatch[600]; break; } } else { - return Colors.grey[350]; + switch (Theme.of(context).brightness) { + case ThemeBrightness.light: + return Colors.black12; + case ThemeBrightness.dark: + return Colors.white12; + } } } - int get level => config.enabled ? (highlight ? 2 : 1) : 0; + ThemeBrightness getColorBrightness(BuildContext context) { + return Theme.of(context).brightness; + } + }