Skip to content

Commit ca6e8de

Browse files
Add more book examples
1 parent 0933a4f commit ca6e8de

15 files changed

Lines changed: 279 additions & 30 deletions

File tree

book-examples/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,10 @@ log.workspace = true
1919
tailwind_fuse = "0.3.1"
2020

2121
[features]
22-
default = ["placement"]
22+
default = ["arrow", "flip", "placement", "shift", "size", "virtual"]
23+
arrow = []
24+
flip = []
2325
placement = []
26+
shift = []
27+
size = []
28+
virtual = []

book-examples/src/app.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ pub fn App() -> impl IntoView {
1111
<PlacementDemo />
1212
});
1313
}
14+
#[cfg(feature = "shift")]
15+
{
16+
use crate::shift::ShiftDemo;
17+
views.push(view! {
18+
<ShiftDemo />
19+
});
20+
}
21+
#[cfg(feature = "flip")]
22+
{
23+
use crate::flip::FlipDemo;
24+
views.push(view! {
25+
<FlipDemo />
26+
});
27+
}
28+
#[cfg(feature = "size")]
29+
{
30+
use crate::size::SizeDemo;
31+
views.push(view! {
32+
<SizeDemo />
33+
});
34+
}
1435

1536
views.into_view()
1637
}

book-examples/src/components/chrome.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn Chrome(
3434
Signal::derive(move || matches!(scrollable.get(), Scrollable::Y | Scrollable::Both));
3535
let is_scrollable = Signal::derive(move || scrollable_x.get() || scrollable_y.get());
3636

37-
Effect::new_isomorphic(move |_| {
37+
Effect::new(move |_| {
3838
if let Some(scrollable) = scrollable_ref.get() {
3939
if scrollable_y.get() {
4040
scrollable.set_scroll_top(
@@ -95,8 +95,8 @@ pub fn Chrome(
9595
<div
9696
class={scrollable_x.get().then_some("w-[180vw] md:w-[75rem] lg:w-[90rem]")}
9797
style:height={match scrollable_y.get() {
98-
true => scroll_height.get(),
99-
false => 1
98+
true => format!("{}px", scroll_height.get()),
99+
false => "1px".into(),
100100
}}
101101
/>
102102
</Show>
@@ -107,8 +107,8 @@ pub fn Chrome(
107107
<div
108108
class={scrollable_x.get().then_some("w-[180vw] md:w-[75rem] lg:w-[90rem]")}
109109
style:height={match scrollable_y.get() {
110-
true => scroll_height.get(),
111-
false => 1
110+
true => format!("{}px", scroll_height.get()),
111+
false => "1px".into(),
112112
}}
113113
/>
114114
</Show>

book-examples/src/components/floating.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ use leptos::{
66
html::{AnyElement, Div},
77
*,
88
};
9+
use tailwind_fuse::tw_merge;
910

1011
#[component]
1112
pub fn Floating<CF, CIV, RF, RIV>(
12-
content: CF,
13+
#[prop(into, optional)] class: MaybeProp<String>,
1314
#[prop(into, optional)] strategy: MaybeProp<Strategy>,
1415
#[prop(into, optional)] placement: MaybeProp<Placement>,
1516
#[prop(into, optional)] middleware: MaybeProp<MiddlewareVec>,
1617
#[prop(default = false.into(), into)] arrow: MaybeSignal<bool>,
18+
content: CF,
1719
reference: RF,
1820
) -> impl IntoView
1921
where
@@ -43,7 +45,14 @@ where
4345

4446
<div
4547
node_ref=floating_ref
46-
class="z-10 grid place-items-center bg-rose-500 text-base font-semibold text-gray-50"
48+
class=move || {
49+
let class = class.get();
50+
51+
tw_merge!(
52+
"z-10 grid place-items-center bg-rose-500 text-base font-semibold text-gray-50",
53+
class
54+
)
55+
}
4756
// TODO: style
4857
style:position=move || floating_styles.get().style_position()
4958
style:top=move || floating_styles.get().style_top()

book-examples/src/components/grid_item.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub fn GridItem<F, IV>(
66
#[prop(into)] title: MaybeSignal<String>,
77
#[prop(into)] description: MaybeSignal<String>,
88
chrome: F,
9-
#[prop(into)] demo_link: MaybeSignal<String>,
9+
// #[prop(into)] demo_link: MaybeSignal<String>,
1010
#[prop(default = false.into(), into)] hidden: MaybeSignal<bool>,
1111
) -> impl IntoView
1212
where
@@ -27,14 +27,14 @@ where
2727
<div class="relative items-center rounded-lg bg-gray-800 shadow-md lg:h-auto">
2828
{chrome()}
2929
</div>
30-
<a
31-
class="absolute right-6 top-6 inline-flex items-center gap-1 border-none font-bold text-rose-600 underline decoration-rose-500/80 decoration-2 underline-offset-4 transition-colors hover:text-gray-1000 hover:decoration-gray-1000 dark:text-rose-300 dark:decoration-rose-300/80 dark:hover:text-gray-50 dark:hover:decoration-gray-50"
32-
href=demo_link
33-
target="_blank"
34-
rel="noopener noreferrer"
35-
>
36-
CodeSandbox
37-
</a>
30+
// <a
31+
// class="absolute right-6 top-6 inline-flex items-center gap-1 border-none font-bold text-rose-600 underline decoration-rose-500/80 decoration-2 underline-offset-4 transition-colors hover:text-gray-1000 hover:decoration-gray-1000 dark:text-rose-300 dark:decoration-rose-300/80 dark:hover:text-gray-50 dark:hover:decoration-gray-50"
32+
// href=demo_link
33+
// target="_blank"
34+
// rel="noopener noreferrer"
35+
// >
36+
// CodeSandbox
37+
// </a>
3838
</div>
3939
}
4040
}

book-examples/src/flip.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use floating_ui_leptos::{
2+
DetectOverflowOptions, Flip, FlipOptions, MiddlewareVec, Offset, OffsetOptions, Placement,
3+
RootBoundary,
4+
};
5+
use leptos::{html::Div, *};
6+
7+
use crate::{
8+
components::{Chrome, Floating, GridItem, Reference, Scrollable},
9+
utils::rem_to_px,
10+
};
11+
12+
#[component]
13+
pub fn FlipDemo() -> impl IntoView {
14+
let boundary_ref: NodeRef<Div> = NodeRef::new();
15+
16+
Effect::new(move |_| {
17+
if let Some(boundary) = boundary_ref.get() {
18+
boundary
19+
.first_element_child()
20+
.expect("First element child should exist.")
21+
.set_scroll_top(rem_to_px(275.0 / 16.0) as i32);
22+
}
23+
});
24+
25+
view! {
26+
<GridItem
27+
title="Flip"
28+
description="Changes the placement of your floating element to keep it in view."
29+
chrome=move || view! {
30+
<div ref={boundary_ref} class="relative overflow-hidden">
31+
<Chrome
32+
label="Scroll down"
33+
scrollable=Scrollable::Y
34+
center=true
35+
shadow=false
36+
>
37+
<Floating
38+
placement=Placement::Top
39+
middleware={
40+
let middleware: MiddlewareVec = vec![
41+
Box::new(Offset::new(OffsetOptions::Value(5.0))),
42+
Box::new(Flip::new(FlipOptions::default().detect_overflow(
43+
DetectOverflowOptions::default().root_boundary(RootBoundary::Document)
44+
))),
45+
];
46+
47+
middleware
48+
}
49+
content=move || view! {
50+
<span class="text-sm font-bold">
51+
Tooltip
52+
</span>
53+
}
54+
reference=move |node_ref| view! {
55+
<Reference node_ref=node_ref />
56+
}
57+
/>
58+
</Chrome>
59+
</div>
60+
}
61+
/>
62+
}
63+
}

book-examples/src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
mod app;
22
mod components;
3+
mod utils;
34

5+
#[cfg(feature = "flip")]
6+
mod flip;
47
#[cfg(feature = "placement")]
58
mod placement;
9+
#[cfg(feature = "shift")]
10+
mod shift;
11+
#[cfg(feature = "size")]
12+
mod size;
613

714
use crate::app::App;
815

book-examples/src/placement.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub fn PlacementDemo() -> impl IntoView {
2121
<GridItem
2222
title="Placement"
2323
description="Places your floating element relative to another element."
24-
demo_link="https://codesandbox.io/s/lively-waterfall-rbc1pi?file=/src/index.js"
2524
chrome=move || view! {
2625
<Chrome
2726
label="Click the dots"
@@ -139,6 +138,11 @@ pub fn PlacementDemo() -> impl IntoView {
139138
}
140139
/>
141140
<Floating
141+
placement=placement
142+
middleware={
143+
let middleware: MiddlewareVec = vec![Box::new(Offset::new(OffsetOptions::Value(5.0)))];
144+
middleware
145+
}
142146
content=move || view! {
143147
<div
144148
class="text-center text-sm font-bold"
@@ -153,11 +157,6 @@ pub fn PlacementDemo() -> impl IntoView {
153157
reference=move |node_ref| view! {
154158
<Reference node_ref=node_ref />
155159
}
156-
placement=placement
157-
middleware={
158-
let middleware: MiddlewareVec = vec![Box::new(Offset::new(OffsetOptions::Value(5.0)))];
159-
middleware
160-
}
161160
/>
162161
</Chrome>
163162
}

book-examples/src/shift.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use floating_ui_leptos::{
2+
Boundary, DetectOverflowOptions, MiddlewareVec, Offset, OffsetOptions, Padding,
3+
PartialSideObject, Placement, RootBoundary, Shift, ShiftOptions,
4+
};
5+
use leptos::{html::Div, *};
6+
7+
use crate::{
8+
components::{Chrome, Floating, GridItem, Reference, Scrollable},
9+
utils::rem_to_px,
10+
};
11+
12+
#[component]
13+
pub fn ShiftDemo() -> impl IntoView {
14+
let boundary_ref: NodeRef<Div> = NodeRef::new();
15+
16+
Effect::new(move |_| {
17+
if let Some(boundary) = boundary_ref.get() {
18+
boundary
19+
.first_element_child()
20+
.expect("First element child should exist.")
21+
.set_scroll_top(rem_to_px(200.0 / 16.0) as i32);
22+
}
23+
});
24+
25+
view! {
26+
<GridItem
27+
title="Shift"
28+
description="Shifts your floating element to keep it in view."
29+
chrome=move || view! {
30+
<div ref={boundary_ref} class="relative overflow-hidden">
31+
<Chrome
32+
label="Scroll the container"
33+
scrollable=Scrollable::Y
34+
relative=false
35+
shadow=false
36+
>
37+
<Floating
38+
placement=Placement::Right
39+
middleware=MaybeProp::derive(move || {
40+
let mut detect_overflow_options = DetectOverflowOptions::default()
41+
.root_boundary(RootBoundary::Document)
42+
.padding(Padding::PerSide(PartialSideObject {
43+
top: Some(rem_to_px(54.0 / 16.0)),
44+
right: None,
45+
bottom: Some(rem_to_px(5.0 / 16.0)),
46+
left: None
47+
}));
48+
49+
if let Some(boundary) = boundary_ref.get() {
50+
let boundary: &web_sys::Element = &boundary;
51+
detect_overflow_options = detect_overflow_options.boundary(Boundary::Element(boundary.clone()));
52+
}
53+
54+
let middleware: MiddlewareVec = vec![
55+
Box::new(Offset::new(OffsetOptions::Value(5.0))),
56+
Box::new(Shift::new(ShiftOptions::default().detect_overflow(detect_overflow_options))),
57+
];
58+
59+
Some(middleware)
60+
})
61+
content=move || view! {
62+
<div class="grid h-48 w-20 place-items-center text-sm font-bold">
63+
Popover
64+
</div>
65+
}
66+
reference=move |node_ref| view! {
67+
<Reference node_ref=node_ref class="ml-[5%] sm:ml-[33%]" />
68+
}
69+
/>
70+
</Chrome>
71+
</div>
72+
}
73+
/>
74+
}
75+
}

book-examples/src/size.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use floating_ui_leptos::{
2+
DetectOverflowOptions, MiddlewareVec, Offset, OffsetOptions, Padding, RootBoundary, Size,
3+
SizeOptions,
4+
};
5+
use leptos::*;
6+
7+
use crate::components::{Chrome, Floating, GridItem, Reference, Scrollable};
8+
9+
#[component]
10+
pub fn SizeDemo() -> impl IntoView {
11+
view! {
12+
<GridItem
13+
title="Size"
14+
description="Changes the size of your floating element to keep it in view."
15+
chrome=move || view! {
16+
<Chrome
17+
label="Scroll the container"
18+
scrollable=Scrollable::Y
19+
center=true
20+
shadow=false
21+
>
22+
<Floating
23+
class="h-[300px] overflow-hidden max-h-0"
24+
middleware={
25+
let middleware: MiddlewareVec = vec![
26+
Box::new(Offset::new(OffsetOptions::Value(5.0))),
27+
Box::new(Size::new(SizeOptions::default().detect_overflow(
28+
DetectOverflowOptions::default()
29+
.root_boundary(RootBoundary::Document)
30+
.padding(Padding::All(8.0))
31+
))),
32+
];
33+
34+
middleware
35+
}
36+
content=move || view! {
37+
<div class="grid items-center text-sm font-bold">
38+
Dropdown
39+
</div>
40+
}
41+
reference=move |node_ref| view! {
42+
<Reference node_ref=node_ref />
43+
}
44+
/>
45+
</Chrome>
46+
}
47+
/>
48+
}
49+
}

0 commit comments

Comments
 (0)