yew_cosmo/
menu.rs

1use stylist::yew::{styled_component, use_style};
2use yew::prelude::*;
3#[cfg(feature = "with-yew-router")]
4use yew_router::prelude::*;
5
6use crate::prelude::*;
7
8#[derive(PartialEq, Clone, Properties)]
9pub struct CosmoMainMenuProps {
10    #[prop_or_default]
11    pub children: Children,
12}
13
14#[styled_component(CosmoMainMenu)]
15pub fn main_menu(props: &CosmoMainMenuProps) -> Html {
16    let main_menu_style = use_style!(
17        r#"
18grid-row: main-menu;
19    "#
20    );
21
22    html!(
23        <div class={main_menu_style}>
24            {for props.children.iter()}
25        </div>
26    )
27}
28
29#[derive(PartialEq, Clone, Properties)]
30pub struct CosmoMenuBarProps {
31    #[prop_or_default]
32    pub children: Children,
33}
34
35#[styled_component(CosmoMenuBar)]
36pub fn menu_bar(props: &CosmoMenuBarProps) -> Html {
37    let menu_bar_style = use_style!(
38        r#"
39grid-row: main-menu;
40display: grid;
41position: relative;
42grid-template-columns:
43    [left-touch] var(--menu-left-touch-width) [spacing1] 1rem [backbutton] var(--back-button-width)
44    [spacing2] calc(
45        var(--page-side-spacing) - var(--menu-left-touch-width) - 1rem - var(--back-button-width)
46    )
47    [content] 1fr;
48
49&::before {
50	content: '';
51	position: absolute;
52	width: var(--menu-left-touch-width);
53	height: 100%;
54	background: var(--primary-color);
55	border-bottom-right-radius: var(--border-radius);
56	border-top-right-radius: var(--border-radius);
57}
58    "#
59    );
60
61    html!(
62        <div class={menu_bar_style}>
63            <CosmoBackButton />
64            <CosmoMenuCollection>
65                {for props.children.iter()}
66            </CosmoMenuCollection>
67        </div>
68    )
69}
70
71#[derive(PartialEq, Clone, Properties)]
72struct CosmoMenuCollectionProps {
73    #[prop_or_default]
74    pub children: Children,
75}
76
77#[styled_component(CosmoMenuCollection)]
78fn menu_collection(props: &CosmoMenuCollectionProps) -> Html {
79    let menu_collection_style = use_style!(
80        r#"
81display: grid;
82grid-column: content;
83grid-template-rows: [main-menu] var(--main-menu-height) [sub-menu] var(--sub-menu-height);
84grid-row-gap: var(--menu-gap);
85    "#
86    );
87
88    html!(
89        <nav class={menu_collection_style}>
90            {for props.children.iter()}
91        </nav>
92    )
93}
94
95#[cfg(feature = "with-yew-router")]
96#[derive(PartialEq, Clone, Properties)]
97pub struct CosmoMainMenuItemLinkProps<Route>
98where
99    Route: Routable + 'static,
100{
101    pub label: AttrValue,
102    pub to: Route,
103    pub is_active: bool,
104}
105
106#[hook]
107fn use_main_menu_item_style(is_active: bool) -> Classes {
108    let item_style = use_style!(
109        r#"
110text-decoration: none;
111font-weight: var(--font-weight-menu);
112font-family: var(--font-family-menu);
113text-transform: lowercase;
114font-size: var(--font-size-main-menu);
115line-height: var(--font-size-main-menu);
116vertical-align: text-top;
117color: var(--menu-text-color);
118margin-right: calc(var(--font-size-main-menu) / 2);
119    "#
120    );
121    let mut active_style = Some(use_style!(
122        r#"
123color: var(--menu-text-selected-color);
124    "#
125    ));
126    if !is_active {
127        active_style = None;
128    }
129
130    classes!(item_style, active_style)
131}
132
133#[cfg(feature = "with-yew-router")]
134#[styled_component(CosmoMainMenuItemLink)]
135pub fn main_menu_item_link<Route>(props: &CosmoMainMenuItemLinkProps<Route>) -> Html
136where
137    Route: Routable + 'static,
138{
139    let style = use_main_menu_item_style(props.is_active);
140
141    html!(
142        <Link<Route> to={props.to.clone()} classes={style}>{props.label.clone()}</Link<Route>>
143    )
144}
145
146#[derive(PartialEq, Clone, Properties)]
147pub struct CosmoMainMenuItemProps {
148    pub label: AttrValue,
149    pub is_active: bool,
150}
151
152#[styled_component(CosmoMainMenuItem)]
153pub fn main_menu_item(props: &CosmoMainMenuItemProps) -> Html {
154    let style = use_main_menu_item_style(props.is_active);
155
156    html!(
157        <span class={style}>{props.label.clone()}</span>
158    )
159}
160
161#[derive(PartialEq, Clone, Properties)]
162pub struct CosmoSubMenuBarProps {
163    #[prop_or_default]
164    pub children: Children,
165}
166
167#[styled_component(CosmoSubMenuBar)]
168pub fn sub_menu_bar(props: &CosmoSubMenuBarProps) -> Html {
169    let sub_menu_style = use_style!(
170        r#"
171grid-row: sub-menu;
172    "#
173    );
174
175    html!(
176        <div class={sub_menu_style}>
177            {for props.children.iter()}
178        </div>
179    )
180}
181
182#[hook]
183fn use_sub_menu_item_style(is_active: bool) -> Classes {
184    let item_style = use_style!(
185        r#"
186text-decoration: none;
187font-weight: var(--font-weight-menu);
188font-family: var(--font-family-menu);
189text-transform: uppercase;
190font-size: var(--font-size-sub-menu);
191line-height: var(--font-size-sub-menu);
192vertical-align: text-top;
193margin-right: var(--font-size-sub-menu);
194color: var(--black);
195    "#
196    );
197    let mut active_style = Some(use_style!(
198        r#"
199font-weight: var(--font-weight-sub-menu-active);
200    "#
201    ));
202    if !is_active {
203        active_style = None;
204    }
205
206    classes!(item_style, active_style)
207}
208
209#[cfg(feature = "with-yew-router")]
210#[derive(PartialEq, Clone, Properties)]
211pub struct CosmoSubMenuItemLinkProps<Route>
212where
213    Route: Routable + 'static,
214{
215    pub label: AttrValue,
216    pub to: Route,
217    pub is_active: bool,
218}
219
220#[cfg(feature = "with-yew-router")]
221#[styled_component(CosmoSubMenuItemLink)]
222pub fn sub_menu_item_link<Route>(props: &CosmoSubMenuItemLinkProps<Route>) -> Html
223where
224    Route: Routable + 'static,
225{
226    let style = use_sub_menu_item_style(props.is_active);
227
228    html!(
229        <Link<Route> to={props.to.clone()} classes={style}>{props.label.clone()}</Link<Route>>
230    )
231}
232
233#[derive(PartialEq, Clone, Properties)]
234pub struct CosmoSubMenuItemProps {
235    pub label: AttrValue,
236    pub is_active: bool,
237}
238
239#[styled_component(CosmoSubMenuItem)]
240pub fn sub_menu_item(props: &CosmoSubMenuItemProps) -> Html {
241    let style = use_sub_menu_item_style(props.is_active);
242
243    html!(
244        <span class={style}>{props.label.clone()}</span>
245    )
246}