use crate::ext::ColorExt;
use crate::widget::text_input::{Appearance, StyleSheet};
use iced_core::Color;
#[derive(Default)]
pub enum TextInput {
#[default]
Default,
EditableText,
ExpandableSearch,
Search,
Inline,
Custom {
active: Box<dyn Fn(&crate::Theme) -> Appearance>,
error: Box<dyn Fn(&crate::Theme) -> Appearance>,
hovered: Box<dyn Fn(&crate::Theme) -> Appearance>,
focused: Box<dyn Fn(&crate::Theme) -> Appearance>,
disabled: Box<dyn Fn(&crate::Theme) -> Appearance>,
},
}
impl StyleSheet for crate::Theme {
type Style = TextInput;
fn active(&self, style: &Self::Style) -> Appearance {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.component.base.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: None,
border_color: container.component.divider.into(),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::EditableText => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::ExpandableSearch => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_xl.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search => Appearance {
background: background.into(),
border_radius: corner.radius_xl.into(),
border_width: 2.0,
border_offset: None,
border_color: container.component.divider.into(),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Inline => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Custom { active, .. } => active(self),
}
}
fn error(&self, style: &Self::Style) -> Appearance {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.component.base.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: Some(2.0),
border_color: Color::from(palette.destructive_color()),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search | TextInput::ExpandableSearch => Appearance {
background: background.into(),
border_radius: corner.radius_xl.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::EditableText | TextInput::Inline => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Custom { error, .. } => error(self),
}
}
fn hovered(&self, style: &Self::Style) -> Appearance {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.component.base.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: None,
border_color: palette.accent.base.into(),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search => Appearance {
background: background.into(),
border_radius: corner.radius_xl.into(),
border_offset: None,
border_width: 2.0,
border_color: palette.accent.base.into(),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::ExpandableSearch => Appearance {
background: background.into(),
border_radius: corner.radius_xl.into(),
border_offset: None,
border_width: 0.0,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::EditableText => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Inline => Appearance {
background: Color::from(container.component.hover).into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Custom { hovered, .. } => hovered(self),
}
}
fn focused(&self, style: &Self::Style) -> Appearance {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.component.base.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: Some(2.0),
border_color: palette.accent.base.into(),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search | TextInput::ExpandableSearch => Appearance {
background: background.into(),
border_radius: corner.radius_xl.into(),
border_width: 2.0,
border_offset: Some(2.0),
border_color: palette.accent.base.into(),
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::EditableText => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Inline => Appearance {
background: Color::TRANSPARENT.into(),
border_radius: corner.radius_0.into(),
border_width: 0.0,
border_offset: None,
border_color: Color::TRANSPARENT,
icon_color: None,
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Custom { focused, .. } => focused(self),
}
}
fn disabled(&self, style: &Self::Style) -> Appearance {
if let TextInput::Custom { disabled, .. } = style {
return disabled(self);
}
self.active(style)
}
}