Implement dashboard row sideways scrolling

This commit is contained in:
Ethan Girouard 2024-05-11 15:23:49 -04:00
parent 683f979bc7
commit af66381f5f
Signed by: eta357
GPG Key ID: 7BCDC36DFD11C146
2 changed files with 90 additions and 2 deletions

View File

@ -1,7 +1,9 @@
use leptos::html::Ul;
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::components::dashboard_tile::DashboardTile; use crate::components::dashboard_tile::DashboardTile;
use leptos_icons::*;
/// A row of dashboard tiles, with a title /// A row of dashboard tiles, with a title
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -21,10 +23,65 @@ impl DashboardRow {
impl IntoView for DashboardRow { impl IntoView for DashboardRow {
fn into_view(self) -> View { fn into_view(self) -> View {
let list_ref = create_node_ref::<Ul>();
// Scroll functions attempt to align the left edge of the scroll area with the left edge of a tile
// This is done by scrolling to the nearest multiple of the tile width, plus some for padding
let scroll_left = move |_| {
if let Some(scroll_element) = list_ref.get() {
let client_width = scroll_element.client_width() as f64;
let current_pos = scroll_element.scroll_left() as f64;
let desired_pos = current_pos - client_width;
if let Some(first_tile) = scroll_element.first_element_child() {
let tile_width = first_tile.client_width() as f64;
let scroll_pos = desired_pos + (tile_width - (desired_pos % tile_width)) + 15.0;
scroll_element.scroll_to_with_x_and_y(scroll_pos, 0.0);
} else {
warn!("Could not get first tile to scroll left");
// Fall back to scrolling by the client width if we can't get the tile width
scroll_element.scroll_to_with_x_and_y(desired_pos, 0.0);
}
} else {
warn!("Could not get scroll element to scroll left");
}
};
let scroll_right = move |_| {
if let Some(scroll_element) = list_ref.get() {
let client_width = scroll_element.client_width() as f64;
let current_pos = scroll_element.scroll_left() as f64;
let desired_pos = current_pos + client_width;
if let Some(first_tile) = scroll_element.first_element_child() {
let tile_width = first_tile.client_width() as f64;
let scroll_pos = desired_pos - (desired_pos % tile_width) + 15.0;
scroll_element.scroll_to_with_x_and_y(scroll_pos, 0.0);
} else {
warn!("Could not get first tile to scroll right");
// Fall back to scrolling by the client width if we can't get the tile width
scroll_element.scroll_to_with_x_and_y(desired_pos, 0.0);
}
} else {
warn!("Could not get scroll element to scroll right");
}
};
view! { view! {
<div class="dashboard-tile-row"> <div class="dashboard-tile-row">
<h2>{self.title}</h2> <div class="dashboard-tile-row-title-row">
<ul> <h2>{self.title}</h2>
<div class="dashboard-tile-row-scroll-btn">
<button on:click=scroll_left tabindex=-1>
<Icon class="dashboard-tile-row-scroll" icon=icondata::FiChevronLeft />
</button>
<button on:click=scroll_right tabindex=-1>
<Icon class="dashboard-tile-row-scroll" icon=icondata::FiChevronRight />
</button>
</div>
</div>
<ul _ref={list_ref}>
{self.tiles.into_iter().map(|tile_info| { {self.tiles.into_iter().map(|tile_info| {
view! { view! {
<li> <li>

View File

@ -1,6 +1,37 @@
.dashboard-tile-row { .dashboard-tile-row {
.dashboard-tile-row-title-row {
display: flex;
.dashboard-tile-row-scroll-btn {
margin-left: auto;
margin-top: auto;
margin-bottom: auto;
button {
background-color: transparent;
border: none;
.dashboard-tile-row-scroll {
color: $text-controls-color;
width: 2.5rem;
height: 2.5rem;
}
.dashboard-tile-row-scroll:hover {
color: $controls-hover-color;
}
.dashboard-tile-row-scroll:active {
color: $controls-click-color;
}
}
}
}
ul { ul {
display: flex; display: flex;
overflow-x: hidden;
scroll-behavior: smooth;
li { li {
list-style-type: none; list-style-type: none;