use dioxus::prelude::*;
use freya_core::platform::CursorIcon;
use freya_elements::{
self as dioxus_elements,
KeyboardEvent,
};
use freya_hooks::{
use_activable_route,
use_applied_theme,
use_focus,
use_platform,
BottomTabTheme,
BottomTabThemeWith,
TabTheme,
TabThemeWith,
};
#[allow(non_snake_case)]
#[component]
pub fn Tabsbar(children: Element) -> Element {
rsx!(
rect {
direction: "horizontal",
{children}
}
)
}
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub enum TabStatus {
#[default]
Idle,
Hovering,
}
#[cfg_attr(feature = "docs",
doc = embed_doc_image::embed_image!("tab", "images/gallery_tab.png")
)]
#[component]
pub fn Tab(
children: Element,
theme: Option<TabThemeWith>,
onpress: Option<EventHandler<()>>,
) -> Element {
let focus = use_focus();
let mut status = use_signal(TabStatus::default);
let platform = use_platform();
let is_active = use_activable_route();
let a11y_id = focus.attribute();
let TabTheme {
background,
hover_background,
border_fill,
focus_border_fill,
padding,
width,
height,
font_theme,
} = use_applied_theme!(&theme, tab);
use_drop(move || {
if *status.read() == TabStatus::Hovering {
platform.set_cursor(CursorIcon::default());
}
});
let onclick = move |_| {
if let Some(onpress) = &onpress {
onpress.call(());
}
};
let onmouseenter = move |_| {
platform.set_cursor(CursorIcon::Pointer);
status.set(TabStatus::Hovering);
};
let onmouseleave = move |_| {
platform.set_cursor(CursorIcon::default());
status.set(TabStatus::default());
};
let background = match *status.read() {
TabStatus::Hovering => hover_background,
TabStatus::Idle => background,
};
let border = if focus.is_focused_with_keyboard() || is_active {
focus_border_fill
} else {
border_fill
};
rsx!(
rect {
onclick,
onmouseenter,
onmouseleave,
a11y_id,
width: "{width}",
height: "{height}",
overflow: "clip",
a11y_role:"tab",
color: "{font_theme.color}",
background: "{background}",
content: "fit",
rect {
padding: "{padding}",
main_align: "center",
cross_align: "center",
{children}
}
rect {
height: "2",
width: "fill-min",
background: "{border}"
}
}
)
}
#[cfg_attr(feature = "docs",
doc = embed_doc_image::embed_image!("bottom_tab", "images/gallery_bottom_tab.png")
)]
#[component]
pub fn BottomTab(
children: Element,
theme: Option<BottomTabThemeWith>,
onpress: Option<EventHandler<()>>,
) -> Element {
let focus = use_focus();
let mut status = use_signal(TabStatus::default);
let platform = use_platform();
let is_active = use_activable_route();
let a11y_id = focus.attribute();
let BottomTabTheme {
background,
hover_background,
padding,
width,
height,
font_theme,
} = use_applied_theme!(&theme, bottom_tab);
use_drop(move || {
if *status.read() == TabStatus::Hovering {
platform.set_cursor(CursorIcon::default());
}
});
let onclick = move |_| {
if let Some(onpress) = &onpress {
onpress.call(());
}
};
let onmouseenter = move |_| {
platform.set_cursor(CursorIcon::Pointer);
status.set(TabStatus::Hovering);
};
let onmouseleave = move |_| {
platform.set_cursor(CursorIcon::default());
status.set(TabStatus::default());
};
let onkeydown = move |ev: KeyboardEvent| {
if focus.validate_keydown(&ev) {
if let Some(onpress) = &onpress {
onpress.call(());
}
}
};
let background = match *status.read() {
_ if focus.is_focused_with_keyboard() || is_active => hover_background,
TabStatus::Hovering => hover_background,
TabStatus::Idle => background,
};
rsx!(
rect {
onclick,
onmouseenter,
onmouseleave,
onkeydown,
a11y_id,
width: "{width}",
height: "{height}",
overflow: "clip",
a11y_role:"tab",
color: "{font_theme.color}",
background: "{background}",
padding: "{padding}",
main_align: "center",
cross_align: "center",
corner_radius: "99",
text_height: "disable-least-ascent",
{children}
}
)
}