mirror of
https://github.com/danbulant/cushy
synced 2026-06-20 15:01:11 +00:00
Diverging from material
Introducing two new colors: - ColorTheme::color_dim, for dimmed/disabled primary colors - SurfaceTheme::opaque_widget, for buttons. In material design, a button's background color uses the Highest Container role, which seems incorrect because then buttons wouldn't have a different color when placed inside of the highest level container. Rather than remove a container level, I added one more tone using the neutral variant. Other changes are just gut feelings to have a slightly richer dark theme. I feel like material is a little muddy in dark mode.
This commit is contained in:
parent
b3bef345a5
commit
849710dbb1
5 changed files with 57 additions and 17 deletions
|
|
@ -187,13 +187,13 @@ fn surface_theme(theme: Dynamic<SurfaceTheme>) -> impl MakeWidget {
|
|||
Stack::columns(
|
||||
swatch(color.clone(), "Surface", on_color.clone())
|
||||
.and(swatch(
|
||||
theme.map_each(|theme| theme.dim_color),
|
||||
"Dim Surface",
|
||||
theme.map_each(|theme| theme.bright_color),
|
||||
"Bright Surface",
|
||||
on_color.clone(),
|
||||
))
|
||||
.and(swatch(
|
||||
theme.map_each(|theme| theme.bright_color),
|
||||
"Bright Surface",
|
||||
theme.map_each(|theme| theme.dim_color),
|
||||
"Dim Surface",
|
||||
on_color.clone(),
|
||||
)),
|
||||
)
|
||||
|
|
@ -245,6 +245,11 @@ fn surface_theme(theme: Dynamic<SurfaceTheme>) -> impl MakeWidget {
|
|||
theme.map_each(|theme| theme.outline_variant),
|
||||
"Outline Variant",
|
||||
color,
|
||||
))
|
||||
.and(swatch(
|
||||
theme.map_each(|theme| theme.opaque_widget),
|
||||
"Opaque Widget",
|
||||
on_color,
|
||||
)),
|
||||
)
|
||||
.expand(),
|
||||
|
|
@ -255,11 +260,17 @@ fn surface_theme(theme: Dynamic<SurfaceTheme>) -> impl MakeWidget {
|
|||
|
||||
fn color_theme(theme: Dynamic<ColorTheme>, label: &str) -> impl MakeWidget {
|
||||
let color = theme.map_each(|theme| theme.color);
|
||||
let dim_color = theme.map_each(|theme| theme.color_dim);
|
||||
let on_color = theme.map_each(|theme| theme.on_color);
|
||||
let container = theme.map_each(|theme| theme.container);
|
||||
let on_container = theme.map_each(|theme| theme.on_container);
|
||||
Stack::rows(
|
||||
swatch(color.clone(), label, on_color.clone())
|
||||
.and(swatch(
|
||||
dim_color.clone(),
|
||||
&format!("{label} Dim"),
|
||||
on_color.clone(),
|
||||
))
|
||||
.and(swatch(
|
||||
on_color.clone(),
|
||||
&format!("On {label}"),
|
||||
|
|
|
|||
|
|
@ -990,6 +990,9 @@ pub struct SurfaceTheme {
|
|||
/// The background color for highest-level container widgets.
|
||||
pub highest_container: Color,
|
||||
|
||||
/// The default background color for widgets that are opaque.
|
||||
pub opaque_widget: Color,
|
||||
|
||||
/// The default text/content color.
|
||||
pub on_color: Color,
|
||||
/// A variation of the text/content color that is de-emphasized.
|
||||
|
|
@ -1006,13 +1009,14 @@ impl SurfaceTheme {
|
|||
#[must_use]
|
||||
pub fn light_from_sources(neutral: ColorSource, neutral_variant: ColorSource) -> Self {
|
||||
Self {
|
||||
color: neutral.color(98),
|
||||
dim_color: neutral_variant.color(70),
|
||||
bright_color: neutral.color(100),
|
||||
lowest_container: neutral.color(100),
|
||||
low_container: neutral.color(96),
|
||||
container: neutral.color(95),
|
||||
high_container: neutral.color(90),
|
||||
color: neutral.color(97),
|
||||
dim_color: neutral.color(70),
|
||||
bright_color: neutral.color(99),
|
||||
opaque_widget: neutral_variant.color(75),
|
||||
lowest_container: neutral.color(95),
|
||||
low_container: neutral.color(92),
|
||||
container: neutral.color(90),
|
||||
high_container: neutral.color(85),
|
||||
highest_container: neutral.color(80),
|
||||
on_color: neutral.color(10),
|
||||
on_color_variant: neutral_variant.color(30),
|
||||
|
|
@ -1027,8 +1031,9 @@ impl SurfaceTheme {
|
|||
pub fn dark_from_sources(neutral: ColorSource, neutral_variant: ColorSource) -> Self {
|
||||
Self {
|
||||
color: neutral.color(10),
|
||||
dim_color: neutral_variant.color(2),
|
||||
dim_color: neutral.color(2),
|
||||
bright_color: neutral.color(11),
|
||||
opaque_widget: neutral_variant.color(40),
|
||||
lowest_container: neutral.color(15),
|
||||
low_container: neutral.color(20),
|
||||
container: neutral.color(25),
|
||||
|
|
@ -1047,6 +1052,8 @@ impl SurfaceTheme {
|
|||
pub struct ColorTheme {
|
||||
/// The primary color, used for high-emphasis content.
|
||||
pub color: Color,
|
||||
/// The primary color, dimmed for de-emphasized or disabled content.
|
||||
pub color_dim: Color,
|
||||
/// The color for content that sits atop the primary color.
|
||||
pub on_color: Color,
|
||||
/// The backgrond color for containers.
|
||||
|
|
@ -1061,6 +1068,7 @@ impl ColorTheme {
|
|||
pub fn light_from_source(source: ColorSource) -> Self {
|
||||
Self {
|
||||
color: source.color(40),
|
||||
color_dim: source.color(30),
|
||||
on_color: source.color(100),
|
||||
container: source.color(90),
|
||||
on_container: source.color(10),
|
||||
|
|
@ -1071,10 +1079,11 @@ impl ColorTheme {
|
|||
#[must_use]
|
||||
pub fn dark_from_source(source: ColorSource) -> Self {
|
||||
Self {
|
||||
color: source.color(80),
|
||||
color: source.color(70),
|
||||
color_dim: source.color(60),
|
||||
on_color: source.color(10),
|
||||
container: source.color(30),
|
||||
on_container: source.color(80),
|
||||
on_container: source.color(90),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -476,3 +476,22 @@ impl ComponentDefinition for DisabledOutlineColor {
|
|||
context.theme().surface.outline_variant
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`Color`] to be used as a background color for widgets that render an
|
||||
/// opaque background.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
pub struct OpaqueWidgetColor;
|
||||
|
||||
impl NamedComponent for OpaqueWidgetColor {
|
||||
fn name(&self) -> Cow<'_, ComponentName> {
|
||||
Cow::Owned(ComponentName::named::<Global>("opaque_color"))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentDefinition for OpaqueWidgetColor {
|
||||
type ComponentType = Color;
|
||||
|
||||
fn default_value(&self, context: &WidgetContext<'_, '_>) -> Color {
|
||||
context.theme().surface.opaque_widget
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::animation::{AnimationHandle, AnimationTarget, Spawn};
|
|||
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext, WidgetContext};
|
||||
use crate::names::Name;
|
||||
use crate::styles::components::{
|
||||
AutoFocusableControls, Easing, IntrinsicPadding, SurfaceColor, TextColor,
|
||||
AutoFocusableControls, Easing, IntrinsicPadding, OpaqueWidgetColor, SurfaceColor, TextColor,
|
||||
};
|
||||
use crate::styles::{ColorExt, ComponentGroup, Styles};
|
||||
use crate::utils::ModifiersExt;
|
||||
|
|
@ -323,7 +323,7 @@ impl ComponentGroup for Button {
|
|||
define_components! {
|
||||
Button {
|
||||
/// The background color of the button.
|
||||
ButtonBackground(Color, "background_color", .surface.highest_container) // TODO highest_container seems wrong, but it's what material uses. Perhaps we should add another color so that buttons don't blend with the highest container level.
|
||||
ButtonBackground(Color, "background_color", |context| context.query_style(&OpaqueWidgetColor))
|
||||
/// The background color of the button when it is active (depressed).
|
||||
ButtonActiveBackground(Color, "active_background_color", .surface.color)
|
||||
/// The background color of the button when the mouse cursor is hovering over
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use kludgine::{Color, Origin};
|
|||
|
||||
use crate::animation::{LinearInterpolate, PercentBetween};
|
||||
use crate::context::{EventContext, GraphicsContext, LayoutContext, WidgetContext};
|
||||
use crate::styles::components::OpaqueWidgetColor;
|
||||
use crate::styles::{ComponentDefinition, ComponentName, Dimension, Group, NamedComponent};
|
||||
use crate::value::{Dynamic, IntoDynamic, IntoValue, Value};
|
||||
use crate::widget::{EventHandling, Widget, HANDLED};
|
||||
|
|
@ -406,7 +407,7 @@ impl ComponentDefinition for InactiveTrackColor {
|
|||
type ComponentType = Color;
|
||||
|
||||
fn default_value(&self, context: &WidgetContext<'_, '_>) -> Self::ComponentType {
|
||||
context.theme().surface.highest_container // TODO this is the same as ButtonBackground. This should be abstracted into its own component both can depend on.
|
||||
context.query_style(&OpaqueWidgetColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue