Add page navigation
This commit is contained in:
parent
8907487e32
commit
a8e801bf8c
6 changed files with 146 additions and 4 deletions
|
@ -39,6 +39,21 @@ body > footer {
|
|||
grid-area: footer;
|
||||
}
|
||||
|
||||
.page-nav ul {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.page-nav ul li a {
|
||||
display: inline-block;
|
||||
padding: 0.8rem;
|
||||
}
|
||||
|
||||
#tags {
|
||||
list-style-type: none;
|
||||
font-size: 2.75rem;
|
||||
|
@ -76,3 +91,26 @@ body > footer {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.post header nav ul {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: baseline;
|
||||
gap: 0.5rem;
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.post header nav ul li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.post footer {
|
||||
text-align: left;
|
||||
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ fn render_index_pages(
|
|||
posts_with_contents,
|
||||
renderers,
|
||||
"",
|
||||
config.paths.index,
|
||||
element.none(),
|
||||
)
|
||||
}
|
||||
|
@ -119,6 +120,7 @@ fn render_tag_pages(
|
|||
posts_with_contents,
|
||||
renderers,
|
||||
tag,
|
||||
config.paths.tag(tag),
|
||||
element.none(),
|
||||
)
|
||||
})
|
||||
|
@ -150,6 +152,7 @@ fn render_year_pages(
|
|||
posts_with_contents,
|
||||
renderers,
|
||||
"Archives for " <> int.to_string(year),
|
||||
config.paths.year(year),
|
||||
element.none(),
|
||||
)
|
||||
})
|
||||
|
@ -178,6 +181,7 @@ fn render_month_pages(
|
|||
<> date.month_to_string(month)
|
||||
<> " "
|
||||
<> int.to_string(year),
|
||||
config.paths.month(year, month),
|
||||
element.none(),
|
||||
),
|
||||
)
|
||||
|
@ -191,6 +195,7 @@ fn pageify_posts(
|
|||
posts_with_contents: Dict(PostID, RenderedPost),
|
||||
renderers: Renderers,
|
||||
title_prefix: String,
|
||||
root_path: String,
|
||||
extra_header: Element(Nil),
|
||||
) {
|
||||
let posts = list.sized_chunk(posts, config.rendering.posts_per_page)
|
||||
|
@ -200,6 +205,7 @@ fn pageify_posts(
|
|||
|
||||
let info =
|
||||
ListInfo(
|
||||
root_path: root_path,
|
||||
current_page: page,
|
||||
total_pages: total_pages,
|
||||
posts: list.map(page_posts, fn(post_with_id) {
|
||||
|
|
|
@ -13,6 +13,7 @@ pub type SinglePostRenderer =
|
|||
|
||||
pub type ListInfo {
|
||||
ListInfo(
|
||||
root_path: String,
|
||||
current_page: Int,
|
||||
total_pages: Int,
|
||||
posts: List(RenderedPost),
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import gleam/list
|
||||
import lustre/element
|
||||
import lustre/element/html
|
||||
import lustre/attribute.{class}
|
||||
import lustre/element/html.{footer, nav}
|
||||
import lustre/attribute.{attribute, class}
|
||||
import gloss/models/database.{type Database}
|
||||
import gloss/rendering/templates.{type ListInfo}
|
||||
import gloss/rendering/templates/nav
|
||||
import gloss/config.{type Configuration}
|
||||
|
||||
pub fn generate(db: Database, config: Configuration) {
|
||||
|
@ -13,6 +14,14 @@ pub fn generate(db: Database, config: Configuration) {
|
|||
fn(info: ListInfo) {
|
||||
let none = element.none()
|
||||
|
||||
let footer = case info.total_pages > 1 {
|
||||
True ->
|
||||
nav([class("page-nav"), attribute("aria-label", "Pages")], [
|
||||
footer([], [nav.view(info, info.root_path, config)]),
|
||||
])
|
||||
False -> none
|
||||
}
|
||||
|
||||
html.section(
|
||||
[class("post-list")],
|
||||
list.flatten([
|
||||
|
@ -21,7 +30,7 @@ pub fn generate(db: Database, config: Configuration) {
|
|||
el -> [el]
|
||||
},
|
||||
list.map(info.posts, single_post_renderer),
|
||||
[html.footer([], [])],
|
||||
[footer],
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
|
84
src/gloss/rendering/templates/nav.gleam
Normal file
84
src/gloss/rendering/templates/nav.gleam
Normal file
|
@ -0,0 +1,84 @@
|
|||
import gleam/list
|
||||
import gleam/int
|
||||
import lustre/element/html.{a, li, span, ul}
|
||||
import lustre/element.{text}
|
||||
import lustre/attribute.{attribute, href}
|
||||
import gloss/rendering/templates.{type ListInfo}
|
||||
import gloss/config.{type Configuration}
|
||||
|
||||
pub fn view(list_info: ListInfo, root_path: String, config: Configuration) {
|
||||
let page_range = list.range(1, list_info.total_pages)
|
||||
|
||||
ul(
|
||||
[],
|
||||
list.flatten([
|
||||
[
|
||||
nextprev_link(
|
||||
list_info.current_page > 1,
|
||||
list_info.current_page - 1,
|
||||
"Previous",
|
||||
"«",
|
||||
root_path,
|
||||
config,
|
||||
),
|
||||
],
|
||||
list.map(page_range, fn(page) {
|
||||
let link_text = case page == list_info.current_page {
|
||||
True -> "[" <> int.to_string(page) <> "]"
|
||||
False -> int.to_string(page)
|
||||
}
|
||||
|
||||
let link_attributes = case page == list_info.current_page {
|
||||
True -> [
|
||||
attribute("aria-label", int.to_string(page) <> " (current page)"),
|
||||
attribute("aria-disabled", "true"),
|
||||
]
|
||||
False -> []
|
||||
}
|
||||
|
||||
li([], [
|
||||
a(
|
||||
list.flatten([
|
||||
[href(config.paths.html(config.paths.list_page(root_path, page)))],
|
||||
link_attributes,
|
||||
]),
|
||||
[text(link_text)],
|
||||
),
|
||||
])
|
||||
}),
|
||||
[
|
||||
nextprev_link(
|
||||
list_info.current_page < list_info.total_pages,
|
||||
list_info.current_page + 1,
|
||||
"Next",
|
||||
"»",
|
||||
root_path,
|
||||
config,
|
||||
),
|
||||
],
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
||||
fn nextprev_link(
|
||||
condition: Bool,
|
||||
target: Int,
|
||||
label: String,
|
||||
text: String,
|
||||
root_path: String,
|
||||
config: Configuration,
|
||||
) {
|
||||
case condition {
|
||||
True ->
|
||||
li([], [
|
||||
a(
|
||||
[
|
||||
href(config.paths.html(config.paths.list_page(root_path, target))),
|
||||
attribute("aria-label", label),
|
||||
],
|
||||
[span([attribute("aria-hidden", "true")], [element.text(text)])],
|
||||
),
|
||||
])
|
||||
False -> element.none()
|
||||
}
|
||||
}
|
|
@ -47,7 +47,11 @@ fn view(post: RenderedPost, is_full: Bool, _db: Database, config: Configuration)
|
|||
nav([attribute("aria-label", "Tags")], [
|
||||
ul(
|
||||
[],
|
||||
list.map(post.orig.tags, fn(tag) { li([], [a([], [text(tag)])]) }),
|
||||
list.map(post.orig.tags, fn(tag) {
|
||||
li([], [
|
||||
a([href(config.paths.html(config.paths.tag(tag)))], [text(tag)]),
|
||||
])
|
||||
}),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
|
|
Loading…
Reference in a new issue