Skip to content

Commit

Permalink
feat: add button groups
Browse files Browse the repository at this point in the history
  • Loading branch information
CalliEve committed Jun 24, 2024
1 parent 9e7b32b commit 2a68123
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 13 deletions.
31 changes: 22 additions & 9 deletions src/components/atoms/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,42 @@ use leptos::{
*,
};

type OnButtonClick = Box<dyn Fn(MouseEvent) + 'static>;

/// A clickable button html element.
#[component]
pub fn Button<F>(
pub fn Button(
/// The text displayed on the button.
text: &'static str,
/// Gets called when the button is clicked.
on_click: F,
on_click: OnButtonClick,
/// If false the button is filled-in with one color, else just the border
/// outline is shown.
#[prop(optional)]
outlined: bool,
) -> impl IntoView
where
F: Fn(MouseEvent) + 'static,
{
let mut class = "inline-block rounded px-6 py-2 text-base font-semibold uppercase leading-normal shadow-primary-3 dark:shadow-neutral-950 hover:shadow-blue-900 dark:hover:shadow-neutral-900".to_owned();
/// If the button should be colored red (is blue otherwise).
#[prop(optional)]
danger: bool,
) -> impl IntoView {
let color = if danger { "red" } else { "blue" };

let base = if danger { 600 } else { 400 };
let base_hover = base + 100;
let base_active = base + 200;
let dark = base + 200;
let dark_hover = dark + 100;
let dark_active = dark + 200;

let mut class = "inline-block rounded px-4 py-1.5 text-sm font-semibold uppercase leading-snug shadow-neutral-800 dark:shadow-neutral-950 hover:shadow-blue-900 dark:hover:shadow-neutral-900".to_owned();

if outlined {
class += " border-solid border-4 text-blue-400 border-blue-400 hover:text-blue-500 hover:border-blue-500 active:text-blue-600 active:border-blue-600 dark:text-blue-500 dark:border-blue-500 dark:hover:text-blue-600 dark:hover:border-blue-600 dark:active:text-blue-700 dark:active:border-blue-700";
class += &format!(" border-solid border-4 text-{color}-{base} border-{color}-{base} hover:text-{color}-{base_hover} hover:border-{color}-{base_hover} active:text-{color}-{base_active} active:border-{color}-{base_active} dark:text-{color}-{dark} dark:border-{color}-{dark} dark:hover:text-{color}-{dark_hover} dark:hover:border-{color}-{dark_hover} dark:active:text-{color}-{dark_active} dark:active:border-{color}-{dark_active}");
} else {
class += " text-white bg-blue-400 hover:bg-blue-500 active:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 dark:active:bg-blue-800";
class += &format!(" text-white bg-{color}-{base} hover:bg-{color}-{base_hover} active:bg-{color}-{base_active} dark:bg-{color}-{dark} dark:hover:bg-{color}-{dark_hover} dark:active:bg-{color}-{dark_active}");
}

class = class.replace("1000", "950");

view! {
<button
type="button"
Expand Down
25 changes: 25 additions & 0 deletions src/components/atoms/button_group.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Contains the [`ButtonGroup`] component.
use leptos::*;

use super::button::ButtonProps;

/// A group of buttons
#[component]
pub fn ButtonGroup(
/// These will be transformed into [`Button`] elements.
children: Vec<ButtonProps>,
) -> impl IntoView {
let class = "max-w-full flex align-center gap-px [&>*]:flex-1 \
[&>*:not(:first-child):not(:last-child)]:ml-0 \
[&>*:not(:first-child):not(:last-child)]:rounded-none \
[&>*:not(:only-child):first-child]:rounded-r-none \
[&>*:not(:only-child):last-child]:rounded-l-none \
[&>*:not(:only-child):last-child]:ml-0";

view! {
<div class=class>
{children}
</div>
}
}
7 changes: 6 additions & 1 deletion src/components/atoms/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
//! Contains small components that do not contain child components.
mod button;
mod button_group;
mod number_input;

pub use button::Button;
pub use button::{
Button,
ButtonProps,
};
pub use button_group::ButtonGroup;
pub use number_input::NumberInput;
2 changes: 1 addition & 1 deletion src/components/molecules/file_modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ where
</div>
// footer
<div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
<Button text="Upload File" on_click=move |_| get_file(&input_ref.get().unwrap(), on_submit)/>
<Button text="Upload File" on_click=Box::new(move |_| get_file(&input_ref.get().unwrap(), on_submit))/>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/organisms/navbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn Navbar() -> impl IntoView {
<div class="ms-2">
<a class="text-2xl font-extrabold text-black dark:text-white" href="#">Metro Map Editor</a>
</div>
<Button text="Upload file" outlined=true on_click=move |_| set_show_file_modal(true)/>
<Button text="Upload file" outlined=true on_click=Box::new(move |_| set_show_file_modal(true))/>
</div>
</nav>
<FileModal
Expand Down
14 changes: 13 additions & 1 deletion src/components/organisms/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use crate::{
components::{
atoms::{
Button,
ButtonGroup,
ButtonProps,
NumberInput,
},
MapState,
Expand All @@ -26,14 +28,24 @@ pub fn Sidebar() -> impl IntoView {
view! {
<div id="sidebar" class="h-full w-full flex flex-col gap-y-4 bg-zinc-100 py-2 shadow-right shadow-dark-mild dark:shadow-black dark:bg-neutral-750 text-black dark:text-white px-2">
<Button
on_click=move |_| map_state.update(|state| state.set_map(testmap()))
on_click=Box::new(move |_| map_state.update(|state| state.set_map(testmap())))
text="reset map" />
<NumberInput
text="Set grid size"
min=2.0
max=f64::from(u32::MAX)
value=move || f64::from(map_state.get().get_square_size())
on_input=move |n| map_state.update(|state| state.set_square_size(n.abs() as u32))/>
<ButtonGroup
children={vec![
ButtonProps::builder().text("Add Station").on_click(Box::new(|_| {})).build(),
ButtonProps::builder().text("Remove Station").on_click(Box::new(|_| {})).danger(true).build(),
]}/>
<ButtonGroup
children={vec![
ButtonProps::builder().text("Add Line").on_click(Box::new(|_| {})).build(),
ButtonProps::builder().text("Remove Line").on_click(Box::new(|_| {})).danger(true).build(),
]}/>
</div>
}
}
Expand Down
8 changes: 8 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ["*.html", "./src/**/*.rs"],
},
safelist: ["border", "text", "bg"]
.flatMap((s) => ["red", "blue"].map((c) => `${s}-${c}`))
.flatMap((s) =>
["400", "500", "600", "700", "800", "900", "950"].map((n) => `${s}-${n}`)
)
.flatMap((s) => ["", "hover:", "active:"].map((m) => `${m}${s}`))
.flatMap((s) => ["", "dark:"].map((m) => `${m}${s}`)),
theme: {
extend: {
boxShadow: {
Expand Down

0 comments on commit 2a68123

Please sign in to comment.