// Copyright 2023 System76 // SPDX-License-Identifier: MPL-2.0 //! Contains stylesheet implementation for [`cosmic::widget::text_input`]. 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 Appearance>, error: Box Appearance>, hovered: Box Appearance>, focused: Box Appearance>, disabled: Box 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) } }