3 Commits

Author SHA1 Message Date
f52733d9a6 💄 Add buttons which will be used by the Login component 2024-03-09 22:46:00 +01:00
bb56d24f02 💄 Add border variables to the base SCSS file 2024-03-09 22:44:04 +01:00
043a721429 Make Spinner animation suspendable 2024-03-09 13:04:01 +01:00
6 changed files with 215 additions and 2 deletions

View File

@@ -51,9 +51,17 @@ $color-ternary-70: #8B0046;
$color-ternary-60: #720033;
$color-ternary-50: #5A0022;
$border-default-color: $greyscale-90;
$border-big-width: 4px;
$border-big: solid $border-big-width $border-default-color;
$border-normal-width: 2px;
$border-normal: solid $border-normal-width $border-default-color;
$form-max-height: 1024px;
$form-aspect-ratio: 1/1.618;
// TODO: Radius should be a percentage(eg: 1024/16px).
$border-radius: 16px;
$geist-font-path: "../fonts/Geist";

148
src/components/button.rs Normal file
View File

@@ -0,0 +1,148 @@
use dioxus::prelude::*;
use dioxus_free_icons::{Icon, IconShape};
turf::style_sheet!("src/components/button.scss");
#[derive(Props)]
struct _ButtonProps<'a> {
children: Element<'a>,
#[props(default = false)]
focus: bool,
#[props(optional)]
id: Option<&'a str>,
#[props(optional)]
onclick: Option<EventHandler<'a, MouseEvent>>,
style: &'static str,
}
fn Button<'a>(cx: Scope<'a, _ButtonProps<'a>>) -> Element<'a> {
let focus = cx.props.focus;
cx.render(rsx! {
style { STYLE_SHEET },
button {
id: cx.props.id,
class: cx.props.style,
onmounted: move |cx| async move {
let _ = cx.inner().set_focus(focus).await;
},
onclick: move |evt| {
if let Some(cb) = &cx.props.onclick {
cb.call(evt);
}
},
&cx.props.children
}
})
}
#[derive(Copy, Clone, Debug)]
struct RegisterText;
impl IconShape for RegisterText {
fn view_box(&self) -> String {
String::from("0 0 250 50")
}
fn xmlns(&self) -> String {
String::from("http://www.w3.org/2000/svg")
}
fn child_elements(&self) -> LazyNodes {
rsx! {
text {
x: "50%",
y: "50%",
"dominant-baseline": "middle",
"text-anchor": "middle",
"font-size": "50",
style: "fill: #ffffff",
"Register"
}
}
}
}
#[derive(Props)]
pub struct ButtonProps<'a> {
#[props(default = false)]
focus: bool,
#[props(optional)]
id: Option<&'a str>,
#[props(optional)]
onclick: Option<EventHandler<'a, MouseEvent>>,
}
pub fn RegisterButton<'a>(cx: Scope<'a, ButtonProps>) -> Element<'a> {
cx.render(rsx! {
style { STYLE_SHEET },
Button {
id: cx.props.id.unwrap_or(""),
style: ClassName::REGISTER,
onclick: |event| {
if let Some(cb) = &cx.props.onclick {
cb.call(event);
}
},
focus: cx.props.focus,
Icon {
icon: RegisterText,
}
}
})
}
#[derive(Copy, Clone, Debug)]
struct LoginText;
impl IconShape for LoginText {
fn view_box(&self) -> String {
String::from("0 0 250 50")
}
fn xmlns(&self) -> String {
String::from("http://www.w3.org/2000/svg")
}
fn child_elements(&self) -> LazyNodes {
rsx! {
text {
x: "50%",
y: "50%",
"dominant-baseline": "middle",
"text-anchor": "middle",
"font-size": "50",
style: "fill: #ffffff",
"Login"
}
}
}
}
pub fn LoginButton<'a>(cx: Scope<'a, ButtonProps>) -> Element<'a> {
cx.render(rsx! {
style { STYLE_SHEET },
Button {
id: cx.props.id.unwrap_or(""),
style: ClassName::LOGIN,
onclick: |event| {
if let Some(cb) = &cx.props.onclick {
cb.call(event);
}
},
focus: cx.props.focus,
Icon {
icon: LoginText,
}
}
})
}

View File

@@ -0,0 +1,44 @@
@import "../_base.scss"
.root {
height: 100%;
aspect-ratio: 3.5;
border: $border-big;
border-radius: $border-radius;
color: $greyscale-0;
font-family: "Geist";
font-weight: bold;
svg {
height: 100%;
width: 100%;
}
}
.register {
@extend .root;
background-color: $color-ternary-90;
}
.register:hover {
background-color: $color-ternary-80;
}
.register:active {
background-color: $color-ternary-70;
}
.login {
@extend .root;
background-color: $color-secondary-90;
}
.login:hover {
background-color: $color-secondary-80;
}
.login:active {
background-color: $color-secondary-70;
}

View File

@@ -1,4 +1,5 @@
pub mod avatar_selector;
pub mod button;
pub mod chats_window;
pub mod contacts_window;
pub mod header;

View File

@@ -23,14 +23,21 @@ impl IconShape for _Spinner {
}
}
#[component]
pub fn Spinner(cx: Scope) -> Element {
#[derive(PartialEq, Props)]
pub struct SpinnerProps {
#[props(default = true)]
animate: bool,
}
pub fn Spinner(cx: Scope<SpinnerProps>) -> Element {
cx.render(rsx! {
style { STYLE_SHEET },
div {
class: ClassName::ROOT,
Icon {
class: if cx.props.animate { "" } else { ClassName::PAUSED },
icon: _Spinner,
}
}

View File

@@ -35,5 +35,10 @@ $logo-aspect-ratio: calc($logo-width / $logo-height);
fill: $color-ternary-100;
}
}
&.paused {
animation-play-state: paused;
}
}
}