gradient
This commit is contained in:
@@ -1,26 +1,37 @@
|
||||
use super::icons::Icon;
|
||||
use crate::components::outlined_box::OutlinedBox;
|
||||
use crate::gradient::Gradient;
|
||||
use leptos::prelude::*;
|
||||
use web_sys::MouseEvent;
|
||||
|
||||
#[component]
|
||||
pub fn Button(
|
||||
#[prop(optional)]
|
||||
#[prop(into)]
|
||||
icon: MaybeProp<Icon>,
|
||||
#[prop(into, optional)] icon: MaybeProp<Icon>,
|
||||
|
||||
#[prop(into)] text: Signal<String>,
|
||||
|
||||
#[prop(optional)] color: Gradient,
|
||||
|
||||
onclick: impl FnMut(MouseEvent) + 'static,
|
||||
) -> impl IntoView {
|
||||
let icon_view = icon.get().map(|i| {
|
||||
let icon_view = i.into_view();
|
||||
view! { <div class="self-center mx-5 my-2.5 text-pink-500 rounded-sm">{icon_view}</div> }
|
||||
let mut classes = "self-center mx-5 my-2.5 text-pink-500 rounded-sm".to_string();
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_text());
|
||||
|
||||
view! { <div class=classes>{icon_view}</div> }
|
||||
});
|
||||
|
||||
let separator = icon
|
||||
.get()
|
||||
.is_some()
|
||||
.then(|| view! { <div class="w-0.5 bg-gradient-to-br from-pink-500 to-orange-400" /> });
|
||||
let separator = icon.get().is_some().then(|| {
|
||||
let mut classes = "w-0.5 bg-gradient-to-br min-w-0.5".to_string();
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_from());
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_to());
|
||||
|
||||
view! { <div class=classes /> }
|
||||
});
|
||||
|
||||
let text_view = view! { <div class="self-center mx-5 my-2.5 uppercase w-full text-lg font-thin">{text.get()}</div> };
|
||||
|
||||
@@ -28,12 +39,11 @@ pub fn Button(
|
||||
<button
|
||||
on:click=onclick
|
||||
type="button"
|
||||
class="p-0.5 mb-2 bg-gradient-to-br from-pink-500 to-orange-400 rounded-lg me-2 hover:brightness-125 active:brightness-90"
|
||||
class="mb-2 me-2 hover:brightness-125 active:brightness-90"
|
||||
>
|
||||
<div class="flex items-stretch py-1.5 bg-gray-900 rounded-md">
|
||||
{icon_view} {separator} {text_view}
|
||||
|
||||
</div>
|
||||
<OutlinedBox color>
|
||||
<div class="flex items-stretch">{icon_view} {separator} {text_view}</div>
|
||||
</OutlinedBox>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
50
crates/ascend/src/components/checkbox.rs
Normal file
50
crates/ascend/src/components/checkbox.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use crate::components::icons;
|
||||
use crate::components::outlined_box::OutlinedBox;
|
||||
use crate::gradient::Gradient;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Checkbox(checked: RwSignal<bool>, #[prop(into)] text: Signal<String>, #[prop(optional)] color: Gradient) -> impl IntoView {
|
||||
let unique_id = Oco::from(format!("checkbox-{}", uuid::Uuid::new_v4()));
|
||||
|
||||
let checkbox_view = view! {
|
||||
<div class="self-center text-white bg-white rounded-sm aspect-square mx-5 my-2.5">
|
||||
<span class=("text-gray-950", move || checked.get())>
|
||||
<icons::Check />
|
||||
</span>
|
||||
</div>
|
||||
};
|
||||
|
||||
let separator = {
|
||||
let mut classes = "w-0.5 bg-gradient-to-br min-w-0.5".to_string();
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_from());
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_to());
|
||||
view! { <div class=classes /> }
|
||||
};
|
||||
|
||||
let text_view = view! {
|
||||
<div class="self-center mx-5 my-2.5 uppercase w-full text-lg font-thin">
|
||||
{move || text.get()}
|
||||
</div>
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class="inline-block mb-2 me-2 hover:brightness-125 active:brightness-90">
|
||||
<input
|
||||
type="checkbox"
|
||||
id=unique_id.clone()
|
||||
value=""
|
||||
class="hidden peer"
|
||||
required=""
|
||||
bind:checked=checked
|
||||
/>
|
||||
<label for=unique_id class="cursor-pointer">
|
||||
<OutlinedBox color>
|
||||
<div class="flex">{checkbox_view} {separator} {text_view}</div>
|
||||
</OutlinedBox>
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,8 @@ pub fn Check() -> impl IntoView {
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
d="M19.916 4.626a.75.75 0 0 1 .208 1.04l-9 13.5a.75.75 0 0 1-1.154.114l-6-6a.75.75 0 0 1 1.06-1.06l5.353 5.353 8.493-12.74a.75.75 0 0 1 1.04-.207Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
|
||||
17
crates/ascend/src/components/outlined_box.rs
Normal file
17
crates/ascend/src/components/outlined_box.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use crate::gradient::Gradient;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn OutlinedBox(children: Children, color: Gradient) -> impl IntoView {
|
||||
let mut classes = "p-0.5 bg-gradient-to-br rounded-lg".to_string();
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_from());
|
||||
classes.push(' ');
|
||||
classes.push_str(color.class_to());
|
||||
|
||||
view! {
|
||||
<div class=classes>
|
||||
<div class="py-1.5 bg-gray-900 rounded-md">{children()}</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
32
crates/ascend/src/gradient.rs
Normal file
32
crates/ascend/src/gradient.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Gradient {
|
||||
#[default]
|
||||
PinkOrange,
|
||||
CyanBlue,
|
||||
TealLime,
|
||||
}
|
||||
impl Gradient {
|
||||
pub fn class_from(&self) -> &str {
|
||||
match self {
|
||||
Gradient::PinkOrange => "from-pink-500",
|
||||
Gradient::CyanBlue => "from-cyan-500",
|
||||
Gradient::TealLime => "from-teal-300",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn class_to(&self) -> &str {
|
||||
match self {
|
||||
Gradient::PinkOrange => "to-orange-400",
|
||||
Gradient::CyanBlue => "to-blue-500",
|
||||
Gradient::TealLime => "to-lime-300",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn class_text(&self) -> &str {
|
||||
match self {
|
||||
Gradient::PinkOrange => "text-pink-500",
|
||||
Gradient::CyanBlue => "text-cyan-500",
|
||||
Gradient::TealLime => "text-teal-300",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,16 @@ pub mod components {
|
||||
|
||||
pub mod attempt;
|
||||
pub mod button;
|
||||
pub mod checkbox;
|
||||
pub mod header;
|
||||
pub mod icons;
|
||||
pub mod outlined_box;
|
||||
pub mod problem;
|
||||
pub mod problem_info;
|
||||
}
|
||||
|
||||
pub mod gradient;
|
||||
|
||||
pub mod resources;
|
||||
|
||||
pub mod codec;
|
||||
|
||||
@@ -19,7 +19,6 @@ pub use v3::UserInteraction;
|
||||
|
||||
pub mod v3 {
|
||||
use super::v2;
|
||||
use chrono::NaiveDate;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::BTreeMap;
|
||||
@@ -31,7 +30,7 @@ pub mod v3 {
|
||||
pub problem_uid: v2::ProblemUid,
|
||||
|
||||
/// Dates on which this problem was attempted, and how it went
|
||||
pub attempted_on: BTreeMap<NaiveDate, Attempt>,
|
||||
pub attempted_on: BTreeMap<chrono::DateTime<chrono::Utc>, Attempt>,
|
||||
|
||||
/// Is among favorite problems
|
||||
pub is_favorite: bool,
|
||||
@@ -50,7 +49,7 @@ pub mod v3 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn best_attempt(&self) -> Option<(NaiveDate, Attempt)> {
|
||||
pub fn best_attempt(&self) -> Option<(chrono::DateTime<chrono::Utc>, Attempt)> {
|
||||
self.attempted_on
|
||||
.iter()
|
||||
.max_by_key(|(_date, attempt)| *attempt)
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
// | |
|
||||
// | |
|
||||
// +--------------------------------------+
|
||||
//
|
||||
|
||||
// +---------------------------+
|
||||
// | Next Problem |
|
||||
// +---------------------------+
|
||||
//
|
||||
|
||||
// +--------------- Problem --------------+
|
||||
// | Name: ... |
|
||||
// | Method: ... |
|
||||
@@ -24,7 +24,7 @@
|
||||
// + ------- + + ------ -+ +---------+
|
||||
// | Flash | | Top | | Attempt |
|
||||
// + ------- + + ------ -+ +---------+
|
||||
//
|
||||
|
||||
// +---------- <Latest attempt> ----------+
|
||||
// | Today: <Attempt> |
|
||||
// | 14 days ago: <Attempt> |
|
||||
@@ -33,11 +33,12 @@
|
||||
use crate::components::ProblemInfo;
|
||||
use crate::components::attempt::Attempt;
|
||||
use crate::components::button::Button;
|
||||
use crate::components::checkbox::Checkbox;
|
||||
use crate::components::header::HeaderItem;
|
||||
use crate::components::header::HeaderItems;
|
||||
use crate::components::header::StyledHeader;
|
||||
use crate::components::icons;
|
||||
use crate::components::icons::Icon;
|
||||
use crate::gradient::Gradient;
|
||||
use crate::models;
|
||||
use crate::models::HoldRole;
|
||||
use leptos::Params;
|
||||
@@ -161,6 +162,20 @@ pub fn Wall() -> impl IntoView {
|
||||
<div>{grid}</div>
|
||||
|
||||
<div>
|
||||
<div class="flex">
|
||||
<Checkbox
|
||||
checked=ui_is_flash
|
||||
text="Flash"
|
||||
color=Gradient::CyanBlue
|
||||
/>
|
||||
<Checkbox
|
||||
checked=ui_is_climbed
|
||||
text="Top"
|
||||
color=Gradient::TealLime
|
||||
/>
|
||||
<Checkbox checked=ui_is_favorite text="Attempt" />
|
||||
</div>
|
||||
|
||||
<Button
|
||||
icon=Icon::ArrowPath
|
||||
text="Next problem"
|
||||
@@ -182,84 +197,6 @@ pub fn Wall() -> impl IntoView {
|
||||
|
||||
<div class="m-4" />
|
||||
|
||||
<div class="inline-flex overflow-hidden relative justify-center items-center p-0.5 mb-2 text-sm font-medium text-white bg-gradient-to-br from-cyan-500 to-blue-500 rounded-lg me-2 group hover:brightness-125">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="flash-option"
|
||||
value=""
|
||||
class="hidden peer"
|
||||
required=""
|
||||
bind:checked=ui_is_flash
|
||||
/>
|
||||
<label for="flash-option" class="cursor-pointer">
|
||||
<div
|
||||
class="flex relative gap-2 items-center py-3.5 px-5 bg-gray-900 rounded-md transition-all duration-75 ease-in"
|
||||
class:bg-transparent=move || ui_is_flash.get()
|
||||
>
|
||||
<div class="text-white bg-white rounded-sm border-gray-500 ring-offset-gray-700 aspect-square">
|
||||
<span class=("text-cyan-500", move || ui_is_flash.get())>
|
||||
<icons::Check />
|
||||
</span>
|
||||
</div>
|
||||
// <icons::Bolt />
|
||||
<div class="w-full text-lg font-semibold">Flash</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="inline-flex overflow-hidden relative justify-center items-center p-0.5 mb-2 text-sm font-medium text-white bg-gradient-to-br from-teal-300 to-lime-300 rounded-lg me-2 group hover:brightness-125">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="climbed-option"
|
||||
value=""
|
||||
class="hidden peer"
|
||||
required=""
|
||||
bind:checked=ui_is_climbed
|
||||
/>
|
||||
<label for="climbed-option" class="cursor-pointer">
|
||||
<div
|
||||
class="flex relative gap-2 items-center py-3.5 px-5 text-white bg-gray-900 rounded-md transition-all duration-75 ease-in"
|
||||
class:bg-transparent=move || ui_is_climbed.get()
|
||||
>
|
||||
<div class="bg-white rounded-sm border-gray-500 ring-offset-gray-700 aspect-square">
|
||||
<span class=("text-black", move || ui_is_climbed.get())>
|
||||
<icons::Check />
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="w-full text-lg font-semibold"
|
||||
class=("text-black", move || ui_is_climbed.get())
|
||||
>
|
||||
Climbed
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="inline-flex overflow-hidden relative justify-center items-center p-0.5 mb-2 text-sm font-medium text-white bg-gradient-to-br from-pink-500 to-orange-400 rounded-lg me-2 group hover:brightness-125">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="favorite-option"
|
||||
value=""
|
||||
class="hidden peer"
|
||||
required=""
|
||||
bind:checked=ui_is_favorite
|
||||
/>
|
||||
<label for="favorite-option" class="cursor-pointer">
|
||||
<div
|
||||
class="flex relative gap-2 items-center py-3.5 px-5 bg-gray-900 rounded-md transition-all duration-75 ease-in"
|
||||
class:bg-transparent=move || ui_is_favorite.get()
|
||||
>
|
||||
<div class="text-pink-500 rounded-sm border-gray-500 ring-offset-gray-700 aspect-square">
|
||||
<span class=("text-white", move || ui_is_favorite.get())>
|
||||
<icons::HeartOutline />
|
||||
</span>
|
||||
</div>
|
||||
<div class="w-full text-lg font-semibold">Favorite</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<Suspense fallback=move || {
|
||||
view! {}
|
||||
}>
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
rust.toolchain.targets = [ "wasm32-unknown-unknown" ];
|
||||
|
||||
packages = [
|
||||
pkgs.bacon
|
||||
pkgs.cargo-leptos
|
||||
pkgs.leptosfmt
|
||||
pkgs.dart-sass
|
||||
|
||||
Reference in New Issue
Block a user