diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/custom_widget.rs | 5 | ||||
| -rw-r--r-- | examples/geometry.rs | 3 | ||||
| -rw-r--r-- | examples/pokedex.rs | 31 | ||||
| -rw-r--r-- | examples/progress_bar.rs | 22 | ||||
| -rw-r--r-- | examples/stopwatch.rs | 46 | ||||
| -rw-r--r-- | examples/styling.rs | 514 | ||||
| -rw-r--r-- | examples/todos.rs | 98 | ||||
| -rw-r--r-- | examples/tour.rs | 61 | 
8 files changed, 698 insertions, 82 deletions
diff --git a/examples/custom_widget.rs b/examples/custom_widget.rs index c0038cd9..0a570745 100644 --- a/examples/custom_widget.rs +++ b/examples/custom_widget.rs @@ -13,7 +13,7 @@ mod circle {          layout, Background, Color, Element, Hasher, Layout, Length,          MouseCursor, Point, Size, Widget,      }; -    use iced_wgpu::{Primitive, Renderer}; +    use iced_wgpu::{Defaults, Primitive, Renderer};      pub struct Circle {          radius: u16, @@ -54,6 +54,7 @@ mod circle {          fn draw(              &self,              _renderer: &mut Renderer, +            _defaults: &Defaults,              layout: Layout<'_>,              _cursor_position: Point,          ) -> (Primitive, MouseCursor) { @@ -62,6 +63,8 @@ mod circle {                      bounds: layout.bounds(),                      background: Background::Color(Color::BLACK),                      border_radius: self.radius, +                    border_width: 0, +                    border_color: Color::TRANSPARENT,                  },                  MouseCursor::OutOfBounds,              ) diff --git a/examples/geometry.rs b/examples/geometry.rs index ae6c9ca0..9d5fd611 100644 --- a/examples/geometry.rs +++ b/examples/geometry.rs @@ -16,7 +16,7 @@ mod rainbow {      };      use iced_wgpu::{          triangle::{Mesh2D, Vertex2D}, -        Primitive, Renderer, +        Defaults, Primitive, Renderer,      };      pub struct Rainbow; @@ -51,6 +51,7 @@ mod rainbow {          fn draw(              &self,              _renderer: &mut Renderer, +            _defaults: &Defaults,              layout: Layout<'_>,              cursor_position: Point,          ) -> (Primitive, MouseCursor) { diff --git a/examples/pokedex.rs b/examples/pokedex.rs index f44b6163..7326f94f 100644 --- a/examples/pokedex.rs +++ b/examples/pokedex.rs @@ -1,6 +1,6 @@  use iced::{ -    button, image, Align, Application, Button, Color, Column, Command, -    Container, Element, Image, Length, Row, Settings, Text, +    button, image, Align, Application, Button, Column, Command, Container, +    Element, Image, Length, Row, Settings, Text,  };  pub fn main() { @@ -214,8 +214,29 @@ impl From<surf::Exception> for Error {  }  fn button<'a>(state: &'a mut button::State, text: &str) -> Button<'a, Message> { -    Button::new(state, Text::new(text).color(Color::WHITE)) -        .background(Color::from_rgb(0.11, 0.42, 0.87)) -        .border_radius(10) +    Button::new(state, Text::new(text))          .padding(10) +        .style(style::Button::Primary) +} + +mod style { +    use iced::{button, Background, Color, Vector}; + +    pub enum Button { +        Primary, +    } + +    impl button::StyleSheet for Button { +        fn active(&self) -> button::Style { +            button::Style { +                background: Some(Background::Color(match self { +                    Button::Primary => Color::from_rgb(0.11, 0.42, 0.87), +                })), +                border_radius: 12, +                shadow_offset: Vector::new(1.0, 1.0), +                text_color: Color::WHITE, +                ..button::Style::default() +            } +        } +    }  } diff --git a/examples/progress_bar.rs b/examples/progress_bar.rs index 525019b4..43b09928 100644 --- a/examples/progress_bar.rs +++ b/examples/progress_bar.rs @@ -1,16 +1,7 @@ -use iced::{ -    settings::Window, slider, Background, Color, Column, Element, Length, -    ProgressBar, Sandbox, Settings, Slider, -}; +use iced::{slider, Column, Element, ProgressBar, Sandbox, Settings, Slider};  pub fn main() { -    Progress::run(Settings { -        window: Window { -            size: (700, 300), -            resizable: true, -            decorations: true, -        }, -    }) +    Progress::run(Settings::default())  }  #[derive(Default)] @@ -44,14 +35,7 @@ impl Sandbox for Progress {      fn view(&mut self) -> Element<Message> {          Column::new()              .padding(20) -            .push( -                ProgressBar::new(0.0..=100.0, self.value) -                    .background(Background::Color(Color::from_rgb( -                        0.6, 0.6, 0.6, -                    ))) -                    .active_color(Color::from_rgb(0.0, 0.95, 0.0)) -                    .height(Length::Units(30)), -            ) +            .push(ProgressBar::new(0.0..=100.0, self.value))              .push(Slider::new(                  &mut self.progress_bar_slider,                  0.0..=100.0, diff --git a/examples/stopwatch.rs b/examples/stopwatch.rs index f4d485e2..c9a61ee9 100644 --- a/examples/stopwatch.rs +++ b/examples/stopwatch.rs @@ -1,7 +1,6 @@  use iced::{ -    button, Align, Application, Background, Button, Color, Column, Command, -    Container, Element, HorizontalAlignment, Length, Row, Settings, -    Subscription, Text, +    button, Align, Application, Button, Column, Command, Container, Element, +    HorizontalAlignment, Length, Row, Settings, Subscription, Text,  };  use std::time::{Duration, Instant}; @@ -98,30 +97,29 @@ impl Application for Stopwatch {          ))          .size(40); -        let button = |state, label, color: [f32; 3]| { +        let button = |state, label, style| {              Button::new(                  state,                  Text::new(label) -                    .color(Color::WHITE)                      .horizontal_alignment(HorizontalAlignment::Center),              )              .min_width(80) -            .background(Background::Color(color.into())) -            .border_radius(10)              .padding(10) +            .style(style)          };          let toggle_button = {              let (label, color) = match self.state { -                State::Idle => ("Start", [0.11, 0.42, 0.87]), -                State::Ticking { .. } => ("Stop", [0.9, 0.4, 0.4]), +                State::Idle => ("Start", style::Button::Primary), +                State::Ticking { .. } => ("Stop", style::Button::Destructive),              };              button(&mut self.toggle, label, color).on_press(Message::Toggle)          }; -        let reset_button = button(&mut self.reset, "Reset", [0.7, 0.7, 0.7]) -            .on_press(Message::Reset); +        let reset_button = +            button(&mut self.reset, "Reset", style::Button::Secondary) +                .on_press(Message::Reset);          let controls = Row::new()              .spacing(20) @@ -177,3 +175,29 @@ mod time {          }      }  } + +mod style { +    use iced::{button, Background, Color, Vector}; + +    pub enum Button { +        Primary, +        Secondary, +        Destructive, +    } + +    impl button::StyleSheet for Button { +        fn active(&self) -> button::Style { +            button::Style { +                background: Some(Background::Color(match self { +                    Button::Primary => Color::from_rgb(0.11, 0.42, 0.87), +                    Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5), +                    Button::Destructive => Color::from_rgb(0.8, 0.2, 0.2), +                })), +                border_radius: 12, +                shadow_offset: Vector::new(1.0, 1.0), +                text_color: Color::WHITE, +                ..button::Style::default() +            } +        } +    } +} diff --git a/examples/styling.rs b/examples/styling.rs new file mode 100644 index 00000000..50095ec7 --- /dev/null +++ b/examples/styling.rs @@ -0,0 +1,514 @@ +use iced::{ +    button, scrollable, slider, text_input, Align, Button, Checkbox, Column, +    Container, Element, Length, ProgressBar, Radio, Row, Sandbox, Scrollable, +    Settings, Slider, Space, Text, TextInput, +}; + +pub fn main() { +    Styling::run(Settings::default()) +} + +#[derive(Default)] +struct Styling { +    theme: style::Theme, +    scroll: scrollable::State, +    input: text_input::State, +    input_value: String, +    button: button::State, +    slider: slider::State, +    slider_value: f32, +    toggle_value: bool, +} + +#[derive(Debug, Clone)] +enum Message { +    ThemeChanged(style::Theme), +    InputChanged(String), +    ButtonPressed, +    SliderChanged(f32), +    CheckboxToggled(bool), +} + +impl Sandbox for Styling { +    type Message = Message; + +    fn new() -> Self { +        Styling::default() +    } + +    fn title(&self) -> String { +        String::from("Styling - Iced") +    } + +    fn update(&mut self, message: Message) { +        match message { +            Message::ThemeChanged(theme) => self.theme = theme, +            Message::InputChanged(value) => self.input_value = value, +            Message::ButtonPressed => (), +            Message::SliderChanged(value) => self.slider_value = value, +            Message::CheckboxToggled(value) => self.toggle_value = value, +        } +    } + +    fn view(&mut self) -> Element<Message> { +        let choose_theme = style::Theme::ALL.iter().fold( +            Column::new().spacing(10).push(Text::new("Choose a theme:")), +            |column, theme| { +                column.push( +                    Radio::new( +                        *theme, +                        &format!("{:?}", theme), +                        Some(self.theme), +                        Message::ThemeChanged, +                    ) +                    .style(self.theme), +                ) +            }, +        ); + +        let text_input = TextInput::new( +            &mut self.input, +            "Type something...", +            &self.input_value, +            Message::InputChanged, +        ) +        .padding(10) +        .size(20) +        .style(self.theme); + +        let button = Button::new(&mut self.button, Text::new("Submit")) +            .padding(10) +            .on_press(Message::ButtonPressed) +            .style(self.theme); + +        let slider = Slider::new( +            &mut self.slider, +            0.0..=100.0, +            self.slider_value, +            Message::SliderChanged, +        ) +        .style(self.theme); + +        let progress_bar = +            ProgressBar::new(0.0..=100.0, self.slider_value).style(self.theme); + +        let scrollable = Scrollable::new(&mut self.scroll) +            .height(Length::Units(100)) +            .style(self.theme) +            .push(Text::new("Scroll me!")) +            .push(Space::with_height(Length::Units(800))) +            .push(Text::new("You did it!")); + +        let checkbox = Checkbox::new( +            self.toggle_value, +            "Toggle me!", +            Message::CheckboxToggled, +        ) +        .style(self.theme); + +        let content = Column::new() +            .spacing(20) +            .padding(20) +            .max_width(600) +            .push(choose_theme) +            .push(Row::new().spacing(10).push(text_input).push(button)) +            .push(slider) +            .push(progress_bar) +            .push( +                Row::new() +                    .spacing(10) +                    .align_items(Align::Center) +                    .push(scrollable) +                    .push(checkbox), +            ); + +        Container::new(content) +            .width(Length::Fill) +            .height(Length::Fill) +            .center_x() +            .center_y() +            .style(self.theme) +            .into() +    } +} + +mod style { +    use iced::{ +        button, checkbox, container, progress_bar, radio, scrollable, slider, +        text_input, +    }; + +    #[derive(Debug, Clone, Copy, PartialEq, Eq)] +    pub enum Theme { +        Light, +        Dark, +    } + +    impl Theme { +        pub const ALL: [Theme; 2] = [Theme::Light, Theme::Dark]; +    } + +    impl Default for Theme { +        fn default() -> Theme { +            Theme::Light +        } +    } + +    impl From<Theme> for Box<dyn container::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::Container.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn radio::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::Radio.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn text_input::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::TextInput.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn button::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => light::Button.into(), +                Theme::Dark => dark::Button.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn scrollable::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::Scrollable.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn slider::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::Slider.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn progress_bar::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::ProgressBar.into(), +            } +        } +    } + +    impl From<Theme> for Box<dyn checkbox::StyleSheet> { +        fn from(theme: Theme) -> Self { +            match theme { +                Theme::Light => Default::default(), +                Theme::Dark => dark::Checkbox.into(), +            } +        } +    } + +    mod light { +        use iced::{button, Background, Color, Vector}; + +        pub struct Button; + +        impl button::StyleSheet for Button { +            fn active(&self) -> button::Style { +                button::Style { +                    background: Some(Background::Color(Color::from_rgb( +                        0.11, 0.42, 0.87, +                    ))), +                    border_radius: 12, +                    shadow_offset: Vector::new(1.0, 1.0), +                    text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE), +                    ..button::Style::default() +                } +            } + +            fn hovered(&self) -> button::Style { +                button::Style { +                    text_color: Color::WHITE, +                    shadow_offset: Vector::new(1.0, 2.0), +                    ..self.active() +                } +            } +        } +    } + +    mod dark { +        use iced::{ +            button, checkbox, container, progress_bar, radio, scrollable, +            slider, text_input, Background, Color, +        }; + +        const SURFACE: Color = Color::from_rgb( +            0x40 as f32 / 255.0, +            0x44 as f32 / 255.0, +            0x4B as f32 / 255.0, +        ); + +        const ACCENT: Color = Color::from_rgb( +            0x6F as f32 / 255.0, +            0xFF as f32 / 255.0, +            0xE9 as f32 / 255.0, +        ); + +        const ACTIVE: Color = Color::from_rgb( +            0x72 as f32 / 255.0, +            0x89 as f32 / 255.0, +            0xDA as f32 / 255.0, +        ); + +        const HOVERED: Color = Color::from_rgb( +            0x67 as f32 / 255.0, +            0x7B as f32 / 255.0, +            0xC4 as f32 / 255.0, +        ); + +        pub struct Container; + +        impl container::StyleSheet for Container { +            fn style(&self) -> container::Style { +                container::Style { +                    background: Some(Background::Color(Color::from_rgb8( +                        0x36, 0x39, 0x3F, +                    ))), +                    text_color: Some(Color::WHITE), +                    ..container::Style::default() +                } +            } +        } + +        pub struct Radio; + +        impl radio::StyleSheet for Radio { +            fn active(&self) -> radio::Style { +                radio::Style { +                    background: Background::Color(SURFACE), +                    dot_color: ACTIVE, +                    border_width: 1, +                    border_color: ACTIVE, +                } +            } + +            fn hovered(&self) -> radio::Style { +                radio::Style { +                    background: Background::Color(Color { a: 0.5, ..SURFACE }), +                    ..self.active() +                } +            } +        } + +        pub struct TextInput; + +        impl text_input::StyleSheet for TextInput { +            fn active(&self) -> text_input::Style { +                text_input::Style { +                    background: Background::Color(SURFACE), +                    border_radius: 2, +                    border_width: 0, +                    border_color: Color::TRANSPARENT, +                } +            } + +            fn focused(&self) -> text_input::Style { +                text_input::Style { +                    border_width: 1, +                    border_color: ACCENT, +                    ..self.active() +                } +            } + +            fn hovered(&self) -> text_input::Style { +                text_input::Style { +                    border_width: 1, +                    border_color: Color { a: 0.3, ..ACCENT }, +                    ..self.focused() +                } +            } + +            fn placeholder_color(&self) -> Color { +                Color::from_rgb(0.4, 0.4, 0.4) +            } + +            fn value_color(&self) -> Color { +                Color::WHITE +            } +        } + +        pub struct Button; + +        impl button::StyleSheet for Button { +            fn active(&self) -> button::Style { +                button::Style { +                    background: Some(Background::Color(ACTIVE)), +                    border_radius: 3, +                    text_color: Color::WHITE, +                    ..button::Style::default() +                } +            } + +            fn hovered(&self) -> button::Style { +                button::Style { +                    background: Some(Background::Color(HOVERED)), +                    text_color: Color::WHITE, +                    ..self.active() +                } +            } + +            fn pressed(&self) -> button::Style { +                button::Style { +                    border_width: 1, +                    border_color: Color::WHITE, +                    ..self.hovered() +                } +            } +        } + +        pub struct Scrollable; + +        impl scrollable::StyleSheet for Scrollable { +            fn active(&self) -> scrollable::Scrollbar { +                scrollable::Scrollbar { +                    background: Some(Background::Color(SURFACE)), +                    border_radius: 2, +                    border_width: 0, +                    border_color: Color::TRANSPARENT, +                    scroller: scrollable::Scroller { +                        color: ACTIVE, +                        border_radius: 2, +                        border_width: 0, +                        border_color: Color::TRANSPARENT, +                    }, +                } +            } + +            fn hovered(&self) -> scrollable::Scrollbar { +                let active = self.active(); + +                scrollable::Scrollbar { +                    background: Some(Background::Color(Color { +                        a: 0.5, +                        ..SURFACE +                    })), +                    scroller: scrollable::Scroller { +                        color: HOVERED, +                        ..active.scroller +                    }, +                    ..active +                } +            } + +            fn dragging(&self) -> scrollable::Scrollbar { +                let hovered = self.hovered(); + +                scrollable::Scrollbar { +                    scroller: scrollable::Scroller { +                        color: Color::from_rgb(0.85, 0.85, 0.85), +                        ..hovered.scroller +                    }, +                    ..hovered +                } +            } +        } + +        pub struct Slider; + +        impl slider::StyleSheet for Slider { +            fn active(&self) -> slider::Style { +                slider::Style { +                    rail_colors: (ACTIVE, Color { a: 0.1, ..ACTIVE }), +                    handle: slider::Handle { +                        shape: slider::HandleShape::Circle { radius: 9 }, +                        color: ACTIVE, +                        border_width: 0, +                        border_color: Color::TRANSPARENT, +                    }, +                } +            } + +            fn hovered(&self) -> slider::Style { +                let active = self.active(); + +                slider::Style { +                    handle: slider::Handle { +                        color: HOVERED, +                        ..active.handle +                    }, +                    ..active +                } +            } + +            fn dragging(&self) -> slider::Style { +                let active = self.active(); + +                slider::Style { +                    handle: slider::Handle { +                        color: Color::from_rgb(0.85, 0.85, 0.85), +                        ..active.handle +                    }, +                    ..active +                } +            } +        } + +        pub struct ProgressBar; + +        impl progress_bar::StyleSheet for ProgressBar { +            fn style(&self) -> progress_bar::Style { +                progress_bar::Style { +                    background: Background::Color(SURFACE), +                    bar: Background::Color(ACTIVE), +                    border_radius: 10, +                } +            } +        } + +        pub struct Checkbox; + +        impl checkbox::StyleSheet for Checkbox { +            fn active(&self, is_checked: bool) -> checkbox::Style { +                checkbox::Style { +                    background: Background::Color(if is_checked { +                        ACTIVE +                    } else { +                        SURFACE +                    }), +                    checkmark_color: Color::WHITE, +                    border_radius: 2, +                    border_width: 1, +                    border_color: ACTIVE, +                } +            } + +            fn hovered(&self, is_checked: bool) -> checkbox::Style { +                checkbox::Style { +                    background: Background::Color(Color { +                        a: 0.8, +                        ..if is_checked { ACTIVE } else { SURFACE } +                    }), +                    ..self.active(is_checked) +                } +            } +        } +    } +} diff --git a/examples/todos.rs b/examples/todos.rs index f5f2f459..4166f75a 100644 --- a/examples/todos.rs +++ b/examples/todos.rs @@ -1,7 +1,7 @@  use iced::{      button, scrollable, text_input, Align, Application, Button, Checkbox, -    Color, Column, Command, Container, Element, Font, HorizontalAlignment, -    Length, Row, Scrollable, Settings, Text, TextInput, +    Column, Command, Container, Element, Font, HorizontalAlignment, Length, +    Row, Scrollable, Settings, Text, TextInput,  };  use serde::{Deserialize, Serialize}; @@ -293,12 +293,10 @@ impl Task {                      .align_items(Align::Center)                      .push(checkbox)                      .push( -                        Button::new( -                            edit_button, -                            edit_icon().color([0.5, 0.5, 0.5]), -                        ) -                        .on_press(TaskMessage::Edit) -                        .padding(10), +                        Button::new(edit_button, edit_icon()) +                            .on_press(TaskMessage::Edit) +                            .padding(10) +                            .style(style::Button::Icon),                      )                      .into()              } @@ -324,13 +322,12 @@ impl Task {                              delete_button,                              Row::new()                                  .spacing(10) -                                .push(delete_icon().color(Color::WHITE)) -                                .push(Text::new("Delete").color(Color::WHITE)), +                                .push(delete_icon()) +                                .push(Text::new("Delete")),                          )                          .on_press(TaskMessage::Delete)                          .padding(10) -                        .border_radius(5) -                        .background(Color::from_rgb(0.8, 0.2, 0.2)), +                        .style(style::Button::Destructive),                      )                      .into()              } @@ -357,17 +354,12 @@ impl Controls {          let filter_button = |state, label, filter, current_filter| {              let label = Text::new(label).size(16); -            let button = if filter == current_filter { -                Button::new(state, label.color(Color::WHITE)) -                    .background(Color::from_rgb(0.2, 0.2, 0.7)) -            } else { -                Button::new(state, label) -            }; - -            button -                .on_press(Message::FilterChanged(filter)) -                .padding(8) -                .border_radius(10) +            let button = +                Button::new(state, label).style(style::Button::Filter { +                    selected: filter == current_filter, +                }); + +            button.on_press(Message::FilterChanged(filter)).padding(8)          };          Row::new() @@ -560,3 +552,63 @@ impl SavedState {          Ok(())      }  } + +mod style { +    use iced::{button, Background, Color, Vector}; + +    pub enum Button { +        Filter { selected: bool }, +        Icon, +        Destructive, +    } + +    impl button::StyleSheet for Button { +        fn active(&self) -> button::Style { +            match self { +                Button::Filter { selected } => { +                    if *selected { +                        button::Style { +                            background: Some(Background::Color( +                                Color::from_rgb(0.2, 0.2, 0.7), +                            )), +                            border_radius: 10, +                            text_color: Color::WHITE, +                            ..button::Style::default() +                        } +                    } else { +                        button::Style::default() +                    } +                } +                Button::Icon => button::Style { +                    text_color: Color::from_rgb(0.5, 0.5, 0.5), +                    ..button::Style::default() +                }, +                Button::Destructive => button::Style { +                    background: Some(Background::Color(Color::from_rgb( +                        0.8, 0.2, 0.2, +                    ))), +                    border_radius: 5, +                    text_color: Color::WHITE, +                    shadow_offset: Vector::new(1.0, 1.0), +                    ..button::Style::default() +                }, +            } +        } + +        fn hovered(&self) -> button::Style { +            let active = self.active(); + +            button::Style { +                text_color: match self { +                    Button::Icon => Color::from_rgb(0.2, 0.2, 0.7), +                    Button::Filter { selected } if !selected => { +                        Color::from_rgb(0.2, 0.2, 0.7) +                    } +                    _ => active.text_color, +                }, +                shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0), +                ..active +            } +        } +    } +} diff --git a/examples/tour.rs b/examples/tour.rs index 7fe8f4da..b0ee4d96 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -62,8 +62,9 @@ impl Sandbox for Tour {          if steps.has_previous() {              controls = controls.push( -                secondary_button(back_button, "Back") -                    .on_press(Message::BackPressed), +                button(back_button, "Back") +                    .on_press(Message::BackPressed) +                    .style(style::Button::Secondary),              );          } @@ -71,8 +72,9 @@ impl Sandbox for Tour {          if steps.can_continue() {              controls = controls.push( -                primary_button(next_button, "Next") -                    .on_press(Message::NextPressed), +                button(next_button, "Next") +                    .on_press(Message::NextPressed) +                    .style(style::Button::Primary),              );          } @@ -698,29 +700,12 @@ fn button<'a, Message>(  ) -> Button<'a, Message> {      Button::new(          state, -        Text::new(label) -            .color(Color::WHITE) -            .horizontal_alignment(HorizontalAlignment::Center), +        Text::new(label).horizontal_alignment(HorizontalAlignment::Center),      )      .padding(12) -    .border_radius(12)      .min_width(100)  } -fn primary_button<'a, Message>( -    state: &'a mut button::State, -    label: &str, -) -> Button<'a, Message> { -    button(state, label).background(Color::from_rgb(0.11, 0.42, 0.87)) -} - -fn secondary_button<'a, Message>( -    state: &'a mut button::State, -    label: &str, -) -> Button<'a, Message> { -    button(state, label).background(Color::from_rgb(0.4, 0.4, 0.4)) -} -  #[derive(Debug, Clone, Copy, PartialEq, Eq)]  pub enum Language {      Rust, @@ -763,6 +748,38 @@ pub enum Layout {      Column,  } +mod style { +    use iced::{button, Background, Color, Vector}; + +    pub enum Button { +        Primary, +        Secondary, +    } + +    impl button::StyleSheet for Button { +        fn active(&self) -> button::Style { +            button::Style { +                background: Some(Background::Color(match self { +                    Button::Primary => Color::from_rgb(0.11, 0.42, 0.87), +                    Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5), +                })), +                border_radius: 12, +                shadow_offset: Vector::new(1.0, 1.0), +                text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE), +                ..button::Style::default() +            } +        } + +        fn hovered(&self) -> button::Style { +            button::Style { +                text_color: Color::WHITE, +                shadow_offset: Vector::new(1.0, 2.0), +                ..self.active() +            } +        } +    } +} +  // This should be gracefully handled by Iced in the future. Probably using our  // own proc macro, or maybe the whole process is streamlined by `wasm-pack` at  // some point.  | 
