Commit b9f04817 authored by Ian Hickson's avatar Ian Hickson

Introduce a color for selected rows in data tables

- Rename unselectedColor to unselectedWidgetColor.

- Rename selectionColor to textSelectionColor.

- Add selectedRowColor.

- Remove hintOpacity since it's not tested and has no demo clients.

- Add some docs.
parent d682c13b
...@@ -65,7 +65,7 @@ class Checkbox extends StatelessWidget { ...@@ -65,7 +65,7 @@ class Checkbox extends StatelessWidget {
return new _CheckboxRenderObjectWidget( return new _CheckboxRenderObjectWidget(
value: value, value: value,
activeColor: activeColor ?? themeData.accentColor, activeColor: activeColor ?? themeData.accentColor,
inactiveColor: onChanged != null ? themeData.unselectedColor : themeData.disabledColor, inactiveColor: onChanged != null ? themeData.unselectedWidgetColor : themeData.disabledColor,
onChanged: onChanged onChanged: onChanged
); );
} }
......
...@@ -189,8 +189,8 @@ class _InputState extends State<Input> { ...@@ -189,8 +189,8 @@ class _InputState extends State<Input> {
focusKey: focusKey, focusKey: focusKey,
style: textStyle, style: textStyle,
hideText: config.hideText, hideText: config.hideText,
cursorColor: themeData.selectionColor, cursorColor: themeData.textSelectionColor,
selectionColor: themeData.selectionColor, selectionColor: themeData.textSelectionColor,
keyboardType: config.keyboardType, keyboardType: config.keyboardType,
onChanged: onChanged, onChanged: onChanged,
onSubmitted: onSubmitted onSubmitted: onSubmitted
......
...@@ -69,7 +69,7 @@ class Radio<T> extends StatelessWidget { ...@@ -69,7 +69,7 @@ class Radio<T> extends StatelessWidget {
bool get _enabled => onChanged != null; bool get _enabled => onChanged != null;
Color _getInactiveColor(ThemeData themeData) { Color _getInactiveColor(ThemeData themeData) {
return _enabled ? themeData.unselectedColor : themeData.disabledColor; return _enabled ? themeData.unselectedWidgetColor : themeData.disabledColor;
} }
void _handleChanged(bool selected) { void _handleChanged(bool selected) {
......
...@@ -8,7 +8,23 @@ import 'colors.dart'; ...@@ -8,7 +8,23 @@ import 'colors.dart';
import 'icon_theme_data.dart'; import 'icon_theme_data.dart';
import 'typography.dart'; import 'typography.dart';
enum ThemeBrightness { dark, light } /// The contrast needs of a color.
///
/// This is used to describe the contrast needs of a theme as a whole
/// ([ThemeData.brightness]), its primary color
/// ([ThemeData.primaryColorBrightness]), and its accent color
/// ([ThemeData.accentColorBrightness]).
enum ThemeBrightness {
/// The color is dark, and will require a light text color to achieve readable contrast.
///
/// For example, the color might be dark grey, requiring white text.
dark,
/// The color is right, and will require a dark text color to achieve readable contrast.
///
/// For example, the color might be bright white, requiring black text.
light,
}
// Deriving these values is black magic. The spec claims that pressed buttons // Deriving these values is black magic. The spec claims that pressed buttons
// have a highlight of 0x66999999, but that's clearly wrong. The videos in the // have a highlight of 0x66999999, but that's clearly wrong. The videos in the
...@@ -31,6 +47,26 @@ const Color _kDarkThemeSplashColor = const Color(0x40CCCCCC); ...@@ -31,6 +47,26 @@ const Color _kDarkThemeSplashColor = const Color(0x40CCCCCC);
/// ///
/// Use this class to configure a [Theme] widget. /// Use this class to configure a [Theme] widget.
class ThemeData { class ThemeData {
/// Create a ThemeData given a set of preferred values.
///
/// Default values will be derived for arguments that are omitted.
///
/// The most useful values to give are, in order of importance:
///
/// * The desired theme [brightness].
///
/// * The primary color palette (the [primarySwatch]), chosen from
/// one of the swatches defined by the material design spec. This
/// should be one of the maps from the [Colors] class that do not
/// have "accent" in their name.
///
/// * The [accentColor], sometimes called the secondary color, and,
/// if the accent color is specified, its brightness
/// ([accentColorBrightness]), so that the right contrasting text
/// color will be used over the accent color.
///
/// See <https://www.google.com/design/spec/style/color.html> for
/// more discussion on how to pick the right colors.
factory ThemeData({ factory ThemeData({
ThemeBrightness brightness, ThemeBrightness brightness,
Map<int, Color> primarySwatch, Map<int, Color> primarySwatch,
...@@ -43,14 +79,14 @@ class ThemeData { ...@@ -43,14 +79,14 @@ class ThemeData {
Color dividerColor, Color dividerColor,
Color highlightColor, Color highlightColor,
Color splashColor, Color splashColor,
Color unselectedColor, Color selectedRowColor,
Color unselectedWidgetColor,
Color disabledColor, Color disabledColor,
Color buttonColor, Color buttonColor,
Color selectionColor, Color textSelectionColor,
Color backgroundColor, Color backgroundColor,
Color indicatorColor, Color indicatorColor,
Color hintColor, Color hintColor,
double hintOpacity,
Color errorColor, Color errorColor,
TextTheme textTheme, TextTheme textTheme,
TextTheme primaryTextTheme, TextTheme primaryTextTheme,
...@@ -68,14 +104,14 @@ class ThemeData { ...@@ -68,14 +104,14 @@ class ThemeData {
dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000); dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000);
highlightColor ??= isDark ? _kDarkThemeHighlightColor : _kLightThemeHighlightColor; highlightColor ??= isDark ? _kDarkThemeHighlightColor : _kLightThemeHighlightColor;
splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor; splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor;
unselectedColor ??= isDark ? Colors.white70 : Colors.black54; selectedRowColor ??= Colors.grey[100];
unselectedWidgetColor ??= isDark ? Colors.white70 : Colors.black54;
disabledColor ??= isDark ? Colors.white30 : Colors.black26; disabledColor ??= isDark ? Colors.white30 : Colors.black26;
buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300]; buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300];
selectionColor ??= isDark ? accentColor : primarySwatch[200]; textSelectionColor ??= isDark ? accentColor : primarySwatch[200];
backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200]; backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
indicatorColor ??= accentColor == primaryColor ? Colors.white : accentColor; indicatorColor ??= accentColor == primaryColor ? Colors.white : accentColor;
hintColor ??= isDark ? const Color(0x42FFFFFF) : const Color(0x4C000000); hintColor ??= isDark ? const Color(0x42FFFFFF) : const Color(0x4C000000);
hintOpacity ??= hintColor != null ? hintColor.alpha / 0xFF : isDark ? 0.26 : 0.30;
errorColor ??= Colors.red[700]; errorColor ??= Colors.red[700];
textTheme ??= isDark ? Typography.white : Typography.black; textTheme ??= isDark ? Typography.white : Typography.black;
primaryTextTheme ??= primaryColorBrightness == ThemeBrightness.dark ? Typography.white : Typography.black; primaryTextTheme ??= primaryColorBrightness == ThemeBrightness.dark ? Typography.white : Typography.black;
...@@ -91,14 +127,14 @@ class ThemeData { ...@@ -91,14 +127,14 @@ class ThemeData {
dividerColor: dividerColor, dividerColor: dividerColor,
highlightColor: highlightColor, highlightColor: highlightColor,
splashColor: splashColor, splashColor: splashColor,
unselectedColor: unselectedColor, selectedRowColor: selectedRowColor,
unselectedWidgetColor: unselectedWidgetColor,
disabledColor: disabledColor, disabledColor: disabledColor,
buttonColor: buttonColor, buttonColor: buttonColor,
selectionColor: selectionColor, textSelectionColor: textSelectionColor,
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
indicatorColor: indicatorColor, indicatorColor: indicatorColor,
hintColor: hintColor, hintColor: hintColor,
hintOpacity: hintOpacity,
errorColor: errorColor, errorColor: errorColor,
textTheme: textTheme, textTheme: textTheme,
primaryTextTheme: primaryTextTheme, primaryTextTheme: primaryTextTheme,
...@@ -106,6 +142,12 @@ class ThemeData { ...@@ -106,6 +142,12 @@ class ThemeData {
); );
} }
/// Create a ThemeData given a set of exact values. All the values
/// must be specified.
///
/// This will rarely be used directly. It is used by [lerp] to
/// create intermediate themes based on two themes created with the
/// [new ThemeData] constructor.
ThemeData.raw({ ThemeData.raw({
this.brightness, this.brightness,
this.primaryColor, this.primaryColor,
...@@ -117,14 +159,14 @@ class ThemeData { ...@@ -117,14 +159,14 @@ class ThemeData {
this.dividerColor, this.dividerColor,
this.highlightColor, this.highlightColor,
this.splashColor, this.splashColor,
this.unselectedColor, this.selectedRowColor,
this.unselectedWidgetColor,
this.disabledColor, this.disabledColor,
this.buttonColor, this.buttonColor,
this.selectionColor, this.textSelectionColor,
this.backgroundColor, this.backgroundColor,
this.indicatorColor, this.indicatorColor,
this.hintColor, this.hintColor,
this.hintOpacity,
this.errorColor, this.errorColor,
this.textTheme, this.textTheme,
this.primaryTextTheme, this.primaryTextTheme,
...@@ -140,22 +182,29 @@ class ThemeData { ...@@ -140,22 +182,29 @@ class ThemeData {
assert(dividerColor != null); assert(dividerColor != null);
assert(highlightColor != null); assert(highlightColor != null);
assert(splashColor != null); assert(splashColor != null);
assert(unselectedColor != null); assert(selectedRowColor != null);
assert(unselectedWidgetColor != null);
assert(disabledColor != null); assert(disabledColor != null);
assert(buttonColor != null); assert(buttonColor != null);
assert(selectionColor != null); assert(textSelectionColor != null);
assert(disabledColor != null); assert(disabledColor != null);
assert(indicatorColor != null); assert(indicatorColor != null);
assert(hintColor != null); assert(hintColor != null);
assert(hintOpacity != null);
assert(errorColor != null); assert(errorColor != null);
assert(textTheme != null); assert(textTheme != null);
assert(primaryTextTheme != null); assert(primaryTextTheme != null);
assert(primaryIconTheme != null); assert(primaryIconTheme != null);
} }
/// A default light blue theme.
factory ThemeData.light() => new ThemeData(brightness: ThemeBrightness.light); factory ThemeData.light() => new ThemeData(brightness: ThemeBrightness.light);
/// A default dark theme with a teal accent color.
factory ThemeData.dark() => new ThemeData(brightness: ThemeBrightness.dark); factory ThemeData.dark() => new ThemeData(brightness: ThemeBrightness.dark);
/// The default theme. Same as [new ThemeData.light].
///
/// This is used by [Theme.of] when no theme has been specified.
factory ThemeData.fallback() => new ThemeData.light(); factory ThemeData.fallback() => new ThemeData.light();
/// The brightness of the overall theme of the application. Used by widgets /// The brightness of the overall theme of the application. Used by widgets
...@@ -170,40 +219,70 @@ class ThemeData { ...@@ -170,40 +219,70 @@ class ThemeData {
/// dark, use Colors.white or the accentColor for a contrasting color. /// dark, use Colors.white or the accentColor for a contrasting color.
final ThemeBrightness brightness; final ThemeBrightness brightness;
/// The background colour for major parts of the app (toolbars, tab bars, etc) /// The background color for major parts of the app (toolbars, tab bars, etc)
final Color primaryColor; final Color primaryColor;
/// The brightness of the primaryColor. Used to determine the colour of text and /// The brightness of the primaryColor. Used to determine the color of text and
/// icons placed on top of the primary color (e.g. toolbar text). /// icons placed on top of the primary color (e.g. toolbar text).
final ThemeBrightness primaryColorBrightness; final ThemeBrightness primaryColorBrightness;
/// The foreground color for widgets (knobs, text, etc) /// The foreground color for widgets (knobs, text, etc)
final Color accentColor; final Color accentColor;
/// The brightness of the accentColor. Used to determine the colour of text /// The brightness of the accentColor. Used to determine the color of text
/// and icons placed on top of the accent color (e.g. the icons on a floating /// and icons placed on top of the accent color (e.g. the icons on a floating
/// action button). /// action button).
final ThemeBrightness accentColorBrightness; final ThemeBrightness accentColorBrightness;
/// The color of [Material] when it is of infinite extent, e.g. the
/// body of a [Scaffold].
final Color canvasColor; final Color canvasColor;
/// The color of [Material] when it is used as a [Card].
final Color cardColor; final Color cardColor;
/// The color of [Divider]s and [PopupMenuDivider]s, also used
/// between [ListItem]s, between rows in [DataTable]s, and so forth.
final Color dividerColor; final Color dividerColor;
/// The highlight color used during ink splash animations or to
/// indicate an item in a menu is selected.
final Color highlightColor; final Color highlightColor;
/// The color of ink splashes. See [InkWell].
final Color splashColor; final Color splashColor;
final Color unselectedColor;
/// The color used to highlight selected rows.
final Color selectedRowColor;
/// The color used for widgets in their inactive (but enabled)
/// state. For example, an unchecked checkbox. Usually contrasted
/// with the [accentColor]. See also [disabledColor].
final Color unselectedWidgetColor;
/// The color used for widgets that are inoperative, regardless of
/// their state. For example, a disabled checkbox (which may be
/// checked or unchecked).
final Color disabledColor; final Color disabledColor;
/// The default color of the [Material] used in [RaisedButton]s.
final Color buttonColor; final Color buttonColor;
final Color selectionColor;
/// The color of text selections in text fields, such as [Input].
final Color textSelectionColor;
/// A color that contrasts with the [primaryColor], e.g. used as the
/// remaining part of a progress bar.
final Color backgroundColor; final Color backgroundColor;
/// The color of the selected tab indicator in a tab strip. /// The color of the selected tab indicator in a tab strip.
final Color indicatorColor; final Color indicatorColor;
// Some users want the pre-multiplied color, others just want the opacity. /// The color to use for hint text or placeholder text, e.g. in
/// [Input] fields.
final Color hintColor; final Color hintColor;
final double hintOpacity;
/// The color to use for input validation errors. /// The color to use for input validation errors, e.g. in [Input] fields.
final Color errorColor; final Color errorColor;
/// Text with a color that contrasts with the card and canvas colors. /// Text with a color that contrasts with the card and canvas colors.
...@@ -214,6 +293,7 @@ class ThemeData { ...@@ -214,6 +293,7 @@ class ThemeData {
final IconThemeData primaryIconTheme; final IconThemeData primaryIconTheme;
/// Linearly interpolate between two themes.
static ThemeData lerp(ThemeData begin, ThemeData end, double t) { static ThemeData lerp(ThemeData begin, ThemeData end, double t) {
return new ThemeData.raw( return new ThemeData.raw(
brightness: t < 0.5 ? begin.brightness : end.brightness, brightness: t < 0.5 ? begin.brightness : end.brightness,
...@@ -224,16 +304,16 @@ class ThemeData { ...@@ -224,16 +304,16 @@ class ThemeData {
dividerColor: Color.lerp(begin.dividerColor, end.dividerColor, t), dividerColor: Color.lerp(begin.dividerColor, end.dividerColor, t),
highlightColor: Color.lerp(begin.highlightColor, end.highlightColor, t), highlightColor: Color.lerp(begin.highlightColor, end.highlightColor, t),
splashColor: Color.lerp(begin.splashColor, end.splashColor, t), splashColor: Color.lerp(begin.splashColor, end.splashColor, t),
unselectedColor: Color.lerp(begin.unselectedColor, end.unselectedColor, t), selectedRowColor: Color.lerp(begin.selectedRowColor, end.selectedRowColor, t),
unselectedWidgetColor: Color.lerp(begin.unselectedWidgetColor, end.unselectedWidgetColor, t),
disabledColor: Color.lerp(begin.disabledColor, end.disabledColor, t), disabledColor: Color.lerp(begin.disabledColor, end.disabledColor, t),
buttonColor: Color.lerp(begin.buttonColor, end.buttonColor, t), buttonColor: Color.lerp(begin.buttonColor, end.buttonColor, t),
selectionColor: Color.lerp(begin.selectionColor, end.selectionColor, t), textSelectionColor: Color.lerp(begin.textSelectionColor, end.textSelectionColor, t),
backgroundColor: Color.lerp(begin.backgroundColor, end.backgroundColor, t), backgroundColor: Color.lerp(begin.backgroundColor, end.backgroundColor, t),
accentColor: Color.lerp(begin.accentColor, end.accentColor, t), accentColor: Color.lerp(begin.accentColor, end.accentColor, t),
accentColorBrightness: t < 0.5 ? begin.accentColorBrightness : end.accentColorBrightness, accentColorBrightness: t < 0.5 ? begin.accentColorBrightness : end.accentColorBrightness,
indicatorColor: Color.lerp(begin.indicatorColor, end.indicatorColor, t), indicatorColor: Color.lerp(begin.indicatorColor, end.indicatorColor, t),
hintColor: Color.lerp(begin.hintColor, end.hintColor, t), hintColor: Color.lerp(begin.hintColor, end.hintColor, t),
hintOpacity: lerpDouble(begin.hintOpacity, end.hintOpacity, t),
errorColor: Color.lerp(begin.errorColor, end.errorColor, t), errorColor: Color.lerp(begin.errorColor, end.errorColor, t),
textTheme: TextTheme.lerp(begin.textTheme, end.textTheme, t), textTheme: TextTheme.lerp(begin.textTheme, end.textTheme, t),
primaryTextTheme: TextTheme.lerp(begin.primaryTextTheme, end.primaryTextTheme, t), primaryTextTheme: TextTheme.lerp(begin.primaryTextTheme, end.primaryTextTheme, t),
...@@ -254,16 +334,16 @@ class ThemeData { ...@@ -254,16 +334,16 @@ class ThemeData {
(otherData.dividerColor == dividerColor) && (otherData.dividerColor == dividerColor) &&
(otherData.highlightColor == highlightColor) && (otherData.highlightColor == highlightColor) &&
(otherData.splashColor == splashColor) && (otherData.splashColor == splashColor) &&
(otherData.unselectedColor == unselectedColor) && (otherData.selectedRowColor == selectedRowColor) &&
(otherData.unselectedWidgetColor == unselectedWidgetColor) &&
(otherData.disabledColor == disabledColor) && (otherData.disabledColor == disabledColor) &&
(otherData.buttonColor == buttonColor) && (otherData.buttonColor == buttonColor) &&
(otherData.selectionColor == selectionColor) && (otherData.textSelectionColor == textSelectionColor) &&
(otherData.backgroundColor == backgroundColor) && (otherData.backgroundColor == backgroundColor) &&
(otherData.accentColor == accentColor) && (otherData.accentColor == accentColor) &&
(otherData.accentColorBrightness == accentColorBrightness) && (otherData.accentColorBrightness == accentColorBrightness) &&
(otherData.indicatorColor == indicatorColor) && (otherData.indicatorColor == indicatorColor) &&
(otherData.hintColor == hintColor) && (otherData.hintColor == hintColor) &&
(otherData.hintOpacity == hintOpacity) &&
(otherData.errorColor == errorColor) && (otherData.errorColor == errorColor) &&
(otherData.textTheme == textTheme) && (otherData.textTheme == textTheme) &&
(otherData.primaryTextTheme == primaryTextTheme) && (otherData.primaryTextTheme == primaryTextTheme) &&
...@@ -281,17 +361,17 @@ class ThemeData { ...@@ -281,17 +361,17 @@ class ThemeData {
dividerColor, dividerColor,
highlightColor, highlightColor,
splashColor, splashColor,
unselectedColor, selectedRowColor,
unselectedWidgetColor,
disabledColor, disabledColor,
buttonColor, buttonColor,
selectionColor, textSelectionColor,
backgroundColor, backgroundColor,
accentColor, accentColor,
accentColorBrightness, accentColorBrightness,
hashValues( // Too many values. hashValues( // Too many values.
indicatorColor, indicatorColor,
hintColor, hintColor,
hintOpacity,
errorColor, errorColor,
textTheme, textTheme,
primaryTextTheme, primaryTextTheme,
......
...@@ -147,7 +147,7 @@ class _TwoLevelSublistState extends State<TwoLevelSublist> { ...@@ -147,7 +147,7 @@ class _TwoLevelSublistState extends State<TwoLevelSublist> {
..begin = theme.textTheme.subhead.color ..begin = theme.textTheme.subhead.color
..end = theme.accentColor; ..end = theme.accentColor;
_iconColor _iconColor
..begin = theme.unselectedColor ..begin = theme.unselectedWidgetColor
..end = theme.accentColor; ..end = theme.accentColor;
return new AnimatedBuilder( return new AnimatedBuilder(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment