Implement dashboard row sideways scrolling
This commit is contained in:
parent
683f979bc7
commit
af66381f5f
@ -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">
|
||||||
|
<div class="dashboard-tile-row-title-row">
|
||||||
<h2>{self.title}</h2>
|
<h2>{self.title}</h2>
|
||||||
<ul>
|
<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>
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user