Add projects overview

+5 -1
index.html
··· 3 3 <head> 4 4 <meta charset="UTF-8" /> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + 7 + <link rel="preconnect" href="https://fonts.googleapis.com"> 8 + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 9 + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet"> 6 10 7 - <title>🚧 website</title> 11 + <title>🐈 naomieow</title> 8 12 9 13 <script type="module" src="/priv/static/website.mjs"></script> 10 14 </head>
+61 -21
src/website.gleam
··· 9 9 import lustre/ui 10 10 import lustre/ui/layout/cluster 11 11 import modem 12 + import website/common 12 13 import website/posts 13 14 import website/projects 14 - import website/common 15 15 16 16 // Main 17 17 ··· 28 28 Model( 29 29 current_route: Route, 30 30 posts: List(posts.Post), 31 - projects: List(projects.Project), 31 + projects: List(projects.Project(Msg)), 32 32 ) 33 33 } 34 34 ··· 88 88 // View 89 89 90 90 fn view(model: Model) -> Element(Msg) { 91 - let styles = [#("margin-left", "15vh"), #("margin-top", "5vh")] 91 + let styles = [ 92 + #("margin-left", "25vh"), 93 + #("margin-top", "3vh"), 94 + #("margin-right", "25vh"), 95 + #("font-family", "\"Inter\", sans-serif"), 96 + #("font-weight", "400"), 97 + #("font-style", "normal"), 98 + ] 92 99 93 100 let page = case model.current_route { 94 101 Home -> view_home(model) ··· 101 108 ui.stack([attribute.style(styles)], [view_navbar(model), page]) 102 109 } 103 110 104 - fn view_navbar(_) -> Element(Msg) { 105 - let item_styles = [#("text-decoration", "underline")] 111 + const navbar_style: List(#(String, String)) = [ 112 + #("display", "flex"), #("background-color", "#cae4e7"), 113 + #("border-radius", "1em"), #("padding", "1em"), #("margin-bottom", "3vh"), 114 + #("justify-conten", "center"), #("align-items", "center"), #("gap", "1em"), 115 + ] 116 + 117 + const navitem_style: List(#(String, String)) = [ 118 + #("text-decoration", "none"), #("background-color", "#b8cfd2"), 119 + #("padding", "0.75em"), #("border-radius", "1em"), 120 + #("text-transform", "uppercase"), #("color", "black"), 121 + ] 106 122 123 + fn view_navbar(_) -> Element(Msg) { 107 124 let view_nav_item = fn(path, text) { 108 - html.a([attribute.href("/" <> path), attribute.style(item_styles)], [ 125 + html.a([attribute.href("/" <> path), attribute.style(navitem_style)], [ 109 126 element.text(text), 110 127 ]) 111 128 } 112 129 113 - cluster.of(html.nav, [], [ 130 + cluster.of(html.nav, [attribute.style(navbar_style)], [ 131 + html.h1([attribute.style([#("margin", "0")])], [element.text("naomieow")]), 114 132 view_nav_item("", "Home"), 115 133 view_nav_item("projects", "Projects"), 116 134 view_nav_item("posts", "Posts"), ··· 121 139 html.h1([], [element.text("Homepage")]) 122 140 } 123 141 124 - fn icon_style() -> List(#(String, String)) { 125 - [ 126 - #("max-width", "4em"), 127 - #("max-height", "4em"), 128 - #("border-radius", "1em"), 129 - ] 130 - } 142 + const icon_style: List(#(String, String)) = [ 143 + #("max-width", "4em"), #("max-height", "4em"), #("border-radius", "1em"), 144 + ] 145 + 146 + const project_style: List(#(String, String)) = [ 147 + #("background-color", "#cae4e7"), #("border-radius", "1em"), 148 + #("padding", "1em"), #("margin-bottom", "1em"), 149 + ] 150 + 151 + const project_bar_style: List(#(String, String)) = [ 152 + #("display", "flex"), #("align-items", "center"), #("gap", "1em"), 153 + ] 131 154 132 155 fn view_projects(model: Model) -> Element(Msg) { 133 156 let projects = 134 157 model.projects 135 - |> list.map(fn(project: projects.Project) { 136 - html.div([], [ 137 - html.span([], [ 138 - html.img([attribute.src(project.img), attribute.style(icon_style())]), 139 - html.h1([], [common.link(project.title, "projects/" <> project.id)]) 140 - ]) 141 - ]) 158 + |> list.map(fn(project: projects.Project(Msg)) { 159 + ui.stack( 160 + [attribute.id("project-" <> project.id), attribute.style(project_style)], 161 + [ 162 + cluster.of(html.div, [attribute.style(project_bar_style)], [ 163 + html.img([attribute.src(project.img), attribute.style(icon_style)]), 164 + html.h1([], [common.link(project.title, "projects/" <> project.id)]), 165 + cluster.of( 166 + html.div, 167 + [attribute.style(project_bar_style)], 168 + project.links 169 + |> list.map(fn(link) { 170 + html.a([attribute.href(link.url), attribute.alt(link.title)], [ 171 + html.img([ 172 + attribute.src(link.img), 173 + attribute.style(icon_style), 174 + ]), 175 + ]) 176 + }), 177 + ), 178 + ]), 179 + html.p([], [project.summary]), 180 + ], 181 + ) 142 182 }) 143 183 html.div([], projects) 144 184 }
+5 -1
src/website/common.gleam
··· 2 2 import lustre/element 3 3 import lustre/element/html 4 4 5 + const link_style: List(#(String, String)) = [ 6 + #("text-decoration", "none"), #("color", "black"), 7 + ] 8 + 5 9 pub fn link(text: String, link: String) -> element.Element(a) { 6 - html.a([attr.href(link)], [element.text(text)]) 10 + html.a([attr.href(link), attr.style(link_style)], [element.text(text)]) 7 11 }
-1
src/website/posts.gleam
··· 1 1 import birl.{type Day} 2 - import lustre/attribute 3 2 import lustre/element 4 3 import lustre/element/html 5 4 import website/common.{link}
+10 -10
src/website/projects.gleam
··· 6 6 Link(title: String, url: String, img: String) 7 7 } 8 8 9 - pub type Project { 9 + pub type Project(a) { 10 10 Project( 11 11 id: String, 12 12 title: String, ··· 14 14 img: String, 15 15 links: List(Link), 16 16 archived: Bool, 17 - summary: element.Element(String), 17 + summary: element.Element(a), 18 18 ) 19 19 } 20 20 21 - pub fn all() -> List(Project) { 21 + pub fn all() -> List(Project(a)) { 22 22 [ 23 23 lilypad(), 24 24 caramel(), ··· 54 54 ) 55 55 } 56 56 57 - fn lilypad() -> Project { 57 + fn lilypad() -> Project(a) { 58 58 Project( 59 59 id: "lilypad", 60 60 title: "Lilypad", ··· 71 71 ) 72 72 } 73 73 74 - fn caramel() -> Project { 74 + fn caramel() -> Project(a) { 75 75 Project( 76 76 id: "caramel", 77 77 title: "Caramel", ··· 88 88 ) 89 89 } 90 90 91 - fn mystcraft_ages() -> Project { 91 + fn mystcraft_ages() -> Project(a) { 92 92 Project( 93 93 id: "mystcraft_ages", 94 94 title: "Mystcraft: Ages", ··· 108 108 ) 109 109 } 110 110 111 - fn rpgtitles() -> Project { 111 + fn rpgtitles() -> Project(a) { 112 112 Project( 113 113 id: "rpgtitles", 114 114 title: "RPGTitles", ··· 128 128 ) 129 129 } 130 130 131 - fn biomes_only() -> Project { 131 + fn biomes_only() -> Project(a) { 132 132 Project( 133 133 id: "biomes_only", 134 134 title: "Incendium Biomes Only", ··· 144 144 ) 145 145 } 146 146 147 - fn get_pricked() -> Project { 147 + fn get_pricked() -> Project(a) { 148 148 Project( 149 149 id: "pricked", 150 150 title: "Get Pricked!", ··· 164 164 ) 165 165 } 166 166 167 - fn asbestos() -> Project { 167 + fn asbestos() -> Project(a) { 168 168 Project( 169 169 id: "asbestos", 170 170 title: "Carcinogenic Fibrous Silicate",