-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(examples): added full page layout demo
- Loading branch information
1 parent
41590b1
commit fb00daf
Showing
12 changed files
with
232 additions
and
0 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
dist/ | ||
target_engine/ | ||
target_wasm/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "perseus-example-full-page-layout" | ||
version = "0.4.0-beta.7" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
perseus = { path = "../../../packages/perseus", features = [ "hydrate" ] } | ||
sycamore = "=0.8.0-beta.7" | ||
serde = { version = "1", features = ["derive"] } | ||
serde_json = "1" | ||
|
||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] | ||
fantoccini = "0.17" | ||
|
||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] | ||
tokio = { version = "1", features = [ "macros", "rt", "rt-multi-thread" ] } | ||
# This is an internal convenience crate that exposes all integrations through features for testing | ||
perseus-integration = { path = "../../../packages/perseus-integration", default-features = false } | ||
|
||
[target.'cfg(target_arch = "wasm32")'.dependencies] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Full Page Layout Example | ||
|
||
Perseus currently has some UI quirks, which can make building full-page layouts (i.e. those with headers and footers) a little difficult. This example uses a simple stylesheet to make an app with a sticky header and footer, that can support content of any height, using CSS Grid for flexibility and convenience. | ||
|
||
*Note: the UI quirks that make this a little tricky will be resolved by the time v0.4.0 becomes stable.* | ||
|
||
**Warning:** there is currently a strange page transition bug when going between the index and long pages... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use sycamore::prelude::*; | ||
|
||
// NOTE: None of the code in this file is Perseus-specific! This could easily be | ||
// applied to any Sycamore app. | ||
|
||
#[component] | ||
pub fn Layout<G: Html>(cx: Scope, props: LayoutProps<G>) -> View<G> { | ||
view! { cx, | ||
// These elements are styled with bright colors for demonstration purposes | ||
header(style = "background-color: red; color: white; padding: 1rem") { | ||
p { (props.title) } | ||
} | ||
main(style = "padding: 1rem") { | ||
(props.children) | ||
} | ||
footer(style = "background-color: black; color: white; padding: 1rem") { | ||
p { "Hey there, I'm a footer!" } | ||
} | ||
} | ||
} | ||
|
||
#[derive(Prop)] | ||
pub struct LayoutProps<G: Html> { | ||
/// The title of the page, which will be displayed in the header. | ||
pub title: String, | ||
/// The content to put inside the layout. | ||
pub children: View<G>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod layout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
use perseus::{ErrorPages, Html}; | ||
use sycamore::view; | ||
|
||
pub fn get_error_pages<G: Html>() -> ErrorPages<G> { | ||
let mut error_pages = ErrorPages::new( | ||
|cx, url, status, err, _| { | ||
view! { cx, | ||
p { (format!("An error with HTTP code {} occurred at '{}': '{}'.", status, url, err)) } | ||
} | ||
}, | ||
|cx, _, _, _, _| { | ||
view! { cx, | ||
title { "Error" } | ||
} | ||
}, | ||
); | ||
error_pages.add_page( | ||
404, | ||
|cx, _, _, _, _| { | ||
view! { cx, | ||
p { "Page not found." } | ||
} | ||
}, | ||
|cx, _, _, _, _| { | ||
view! { cx, | ||
title { "Not Found" } | ||
} | ||
}, | ||
); | ||
|
||
error_pages | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
mod components; | ||
mod error_pages; | ||
mod templates; | ||
|
||
use perseus::{Html, PerseusApp, PerseusRoot}; | ||
use sycamore::prelude::view; | ||
|
||
#[perseus::main(perseus_integration::dflt_server)] | ||
pub fn main<G: Html>() -> PerseusApp<G> { | ||
PerseusApp::new() | ||
.template(crate::templates::index::get_template) | ||
.template(crate::templates::long::get_template) | ||
.error_pages(crate::error_pages::get_error_pages) | ||
.index_view(|cx| { | ||
view! { cx, | ||
html { | ||
head { | ||
meta(charset = "UTF-8") | ||
meta(name = "viewport", content = "width=device-width, initial-scale=1.0") | ||
// Perseus automatically resolves `/.perseus/static/` URLs to the contents of the `static/` directory at the project root | ||
link(rel = "stylesheet", href = ".perseus/static/style.css") | ||
} | ||
body { | ||
// Quirk: this creates a wrapper `<div>` around the root `<div>` by necessity | ||
PerseusRoot() | ||
} | ||
} | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use crate::components::layout::Layout; | ||
use perseus::Template; | ||
use sycamore::prelude::{view, Html, Scope, SsrNode, View}; | ||
|
||
#[perseus::template_rx] | ||
pub fn index_page<G: Html>(cx: Scope) -> View<G> { | ||
view! { cx, | ||
Layout { | ||
title: "Index".to_string(), | ||
children: view! { cx, | ||
// Anything we put in here will be rendered inside the `<main>` block of the layout | ||
p { "Hello World!" } | ||
br {} | ||
a(href = "long") { "Long page" } | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[perseus::head] | ||
pub fn head(cx: Scope) -> View<SsrNode> { | ||
view! { cx, | ||
title { "Index Page" } | ||
} | ||
} | ||
|
||
pub fn get_template<G: Html>() -> Template<G> { | ||
Template::new("index").template(index_page).head(head) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use crate::components::layout::Layout; | ||
use perseus::Template; | ||
use sycamore::prelude::{view, Html, Scope, SsrNode, View}; | ||
|
||
#[perseus::template_rx] | ||
pub fn long_page<G: Html>(cx: Scope) -> View<G> { | ||
view! { cx, | ||
Layout { | ||
title: "Long".to_string(), | ||
children: view! { cx, | ||
a(href = "") { "Index" } | ||
br {} | ||
p { | ||
("This is a test. ".repeat(5000)) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[perseus::head] | ||
pub fn head(cx: Scope) -> View<SsrNode> { | ||
view! { cx, | ||
title { "Long Page" } | ||
} | ||
} | ||
|
||
pub fn get_template<G: Html>() -> Template<G> { | ||
Template::new("long").template(long_page).head(head) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod index; | ||
pub mod long; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* This removes the margins inserted by default around pages */ | ||
* { | ||
margin: 0; | ||
} | ||
|
||
/* This makes all the elements that wrap our code take up the whole page, so that we can put things at the bottom. | ||
* Without this, the footer would be just beneath the content if the content doesn't fill the whole page (try disabling this). | ||
* | ||
* Quirk: we have to deal with the wrapper around `#root` created by `PerseusRoot` as well as the wrapper inside it (both will be gone by v0.4.0 stabilization) | ||
*/ | ||
html, body, body > div, #root, #root > div { | ||
height: 100%; | ||
} | ||
/* This makes the `<div>` that wraps our whole app use CSS Grid to display three sections: the header, content, and footer. | ||
* Quirk: soon, this will just be `#root` | ||
*/ | ||
#root > div { | ||
display: grid; | ||
grid-template-columns: 1fr; | ||
/* The header will be automatically sized, the footer will be as small as possible, and the content will take up the rest of the space in the middle */ | ||
grid-template-rows: auto 1fr min-content; | ||
grid-template-areas: | ||
'header' | ||
'main' | ||
'footer'; | ||
} | ||
header { | ||
/* Put this in the right place in the grid */ | ||
grid-area: header; | ||
/* Make this float over the content so it persists as we scroll */ | ||
position: fixed; | ||
top: 0; | ||
z-index: 99; | ||
/* Make this span the whole page */ | ||
width: 100%; | ||
} | ||
main { | ||
/* Put this in the right place in the grid */ | ||
grid-area: main; | ||
/* The header is positioned 'floating' over the content, so we have to make sure this doesn't go behind the header, or it would be invisible. | ||
* You may need to adjust this based on screen size, depending on how the header expands. | ||
*/ | ||
margin-top: 5rem; | ||
} | ||
footer { | ||
/* Put this in the right place in the grid */ | ||
grid-area: footer; | ||
} |