My personal website

Revamp prompt

fruno.win 1f222985 0a7146ed

verified
+84 -116
+47 -88
assets/style.css
··· 177 177 } 178 178 } 179 179 180 + ul { 181 + display: flex; 182 + list-style-type: none; 183 + margin: 0; 184 + padding: 0; 185 + 186 + a { 187 + border-radius: var(--s-3); 188 + color: var(--color-fg); 189 + 190 + &:visited { 191 + color: inherit; 192 + } 193 + } 194 + } 195 + 180 196 #prompt-left .prompt-rounded-left { 181 197 background: var(--color-primary); 182 198 } 183 199 184 200 #prompt-left { 185 201 display: flex; 186 - color: var(--color-bg); 202 + max-width: 60%; 187 203 188 204 #prompt-user { 189 205 display: flex; ··· 202 218 #prompt-dir { 203 219 display: flex; 204 220 background: var(--color-secondary); 221 + overflow: hidden; 222 + white-space: nowrap; 223 + 224 + li { 225 + margin: 0 var(--s-4); 226 + 227 + &:last-child { 228 + overflow: hidden; 229 + text-overflow: ellipsis; 230 + } 231 + } 232 + 233 + li, a { color: var(--color-bg) } 205 234 206 235 & + .prompt-pointed-right { 207 236 background: linear-gradient(90deg, var(--color-secondary) 25%, var(--color-bg) 0 100%); ··· 258 287 } 259 288 260 289 #nav { 261 - view-transition-name: nav; 262 - flex-grow: 100; 263 - display: flex; 264 - 265 290 ul { 266 - display: flex; 267 - list-style-type: none; 268 - margin: 0; 269 - padding: 0; 270 291 gap: 1ch; 271 - 272 - a { 273 - padding: 0 1ch; 274 - border-radius: var(--s-3); 275 - color: var(--color-fg); 292 + } 293 + 294 + a { 295 + padding: 0 1ch; 296 + text-decoration: none; 276 297 277 - &:visited { 278 - color: inherit; 279 - } 298 + &:hover { 299 + color: var(--color-bg); 300 + background: var(--color-fg); 301 + } 302 + } 280 303 281 - /* 282 - * Pseudo background element we can animate during page transitions 283 - */ 284 - &.active::before { 285 - view-transition-name: nav-active-bg; 286 - border-radius: var(--s-3); 287 - content: ""; 288 - position: absolute; 289 - top: 0; 290 - left: 0; 291 - height: 100%; 292 - width: 100%; 293 - z-index: 50; 294 - background: var(--color-fg); 295 - } 296 - 297 - &.active { 298 - position: relative; 299 - color: var(--color-bg); 300 - background: var(--color-fg); 301 - } 302 - 303 - span { 304 - position: relative; 305 - z-index: 100; 306 - } 307 - 308 - &:hover { 309 - color: var(--color-bg); 310 - background: var(--color-fg); 311 - } 312 - } 313 - }; 304 + flex-grow: 100; 305 + display: flex; 314 306 } 315 307 316 308 .cursor { ··· 330 322 331 323 /* I wanted to avoid breakpoints, but I can't figure out a way around this one */ 332 324 @media (max-width: 700px) { 325 + #prompt-right { display: none !important } 326 + #prompt-left { max-width: 100% !important } 327 + 333 328 main { padding-bottom: var(--s3) } 334 329 335 330 #navbar { ··· 353 348 } 354 349 } 355 350 356 - @media (max-width: 380px) { 357 - #prompt-right { display: none !important } 351 + @keyframes blink { 352 + 50% { visibility: hidden } 358 353 } 359 354 360 355 @view-transition { 361 356 navigation: auto; 362 357 } 363 - 364 - @keyframes blink { 365 - 50% { visibility: hidden } 366 - } 367 - 368 - @keyframes slide-out-up { 369 - from { transform: translateY(0) } 370 - to { transform: translateY(min(-100vh, -100%)) } 371 - } 372 - 373 - @keyframes slide-in-up { 374 - from { transform: translateY(100vh) } 375 - to { transform: translateY(0) } 376 - } 377 - 378 - ::view-transition-old(main-content) { 379 - animation: 80ms ease-in both slide-out-up; 380 - } 381 - 382 - ::view-transition-new(main-content) { 383 - animation: 80ms ease-in both slide-in-up; 384 - /* Wait for slide-out to complete before sliding in */ 385 - animation-delay: 80ms; 386 - } 387 - 388 - ::view-transition-group(navbar) { 389 - z-index: 10; 390 - } 391 - 392 - ::view-transition-group(nav-active-bg) { 393 - z-index: 50; 394 - } 395 - 396 - ::view-transition-group(nav) { 397 - z-index: 100; 398 - }
+1 -1
src/blog.gleam
··· 81 81 True -> { 82 82 let item = 83 83 html.li([], [ 84 - html.a([attribute.href("/blog/" <> post.slug)], [ 84 + html.a([attribute.href("/blog/" <> post.slug), attribute.style("view-transition-name", "nav-blog-post")], [ 85 85 html.text(post.slug), 86 86 html.text(".djot"), 87 87 ]),
+1 -1
src/feed.gleam
··· 45 45 46 46 atomb.Feed( 47 47 id: id(feed_uuid()), 48 - title: "fruno.win", 48 + title: "fruno's blog", 49 49 updated:, 50 50 subtitle: Some(atomb.TextContent( 51 51 atomb.Text,
+35 -26
src/page.gleam
··· 23 23 24 24 pub fn route(page: Page) { 25 25 case page { 26 - Index -> "/" 26 + Index -> "/index" 27 27 Blog -> "/blog/" 28 28 Dots -> "/dots" 29 29 BlogPost(post) -> "/blog/" <> post.slug ··· 32 32 33 33 pub fn title(page: Page) { 34 34 case page { 35 - Index -> "/index" 36 - Blog -> "/blog/" 37 - Dots -> "/.dots" 35 + Index -> "webbed site" 36 + Blog -> "blog" 37 + Dots -> ".dots" 38 38 BlogPost(post) -> post.title 39 39 } 40 40 } 41 41 42 + fn nav_id(page: Page) { 43 + "nav-" 44 + <> case page { 45 + Index -> "index" 46 + Blog -> "blog" 47 + Dots -> "dots" 48 + BlogPost(_) -> "blog-post" 49 + } 50 + } 51 + 42 52 pub type SiteInfo { 43 53 SiteInfo(posts: List(blog.Post), meta: Context) 44 54 } ··· 51 61 attribute.name("viewport"), 52 62 attribute.content("width=device-width, initial-scale=1.0"), 53 63 ]), 54 - html.title([], "fruno | " <> title(page)), 64 + html.title([], title(page) <> " | fruno"), 55 65 preload_font("InclusiveSans"), 56 66 preload_font("InclusiveSans-Italic"), 57 67 preload_font("Myna"), ··· 100 110 } 101 111 102 112 fn navbar(page: Page, meta: Context) -> Element(msg) { 113 + let #(breadcrumbs, links) = case page { 114 + Index -> #([Index], [Blog, Dots]) 115 + Blog -> #([Index, Blog], []) 116 + Dots -> #([Index, Dots], []) 117 + BlogPost(_) -> #([Index, Blog, page], []) 118 + } 119 + 103 120 html.nav([attribute.id("navbar")], [ 104 - prompt_left(), 105 - nav(page), 121 + prompt_left(breadcrumbs), 122 + nav(links), 106 123 prompt_right(meta), 107 124 ]) 108 125 } 109 126 110 - fn prompt_left() -> Element(msg) { 127 + fn prompt_left(breadcrumbs: List(Page)) -> Element(msg) { 111 128 html.div([attribute.id("prompt-left")], [ 112 129 html.div([attribute.id("prompt-user")], [ 113 130 html.text("fruno"), 114 131 ]), 115 132 html.div([attribute.class("prompt-pointed-right")], [html.div([], [])]), 116 - html.div([attribute.id("prompt-dir")], [ 117 - html.text("~/webbed_site"), 133 + html.ul([attribute.id("prompt-dir")], [ 134 + html.text("~"), 135 + ..list.flat_map(breadcrumbs, fn(page) { [html.text("/"), nav_link(page)] }) 118 136 ]), 119 137 html.div([attribute.class("prompt-pointed-right")], [html.div([], [])]), 120 138 ]) 121 139 } 122 140 123 - fn nav(page: Page) -> Element(msg) { 141 + fn nav(links: List(Page)) -> Element(msg) { 124 142 html.div([attribute.id("nav")], [ 125 143 html.span([attribute.id("nav-chevron")], [html.text(">")]), 126 - html.span([], [html.text("/")]), 127 144 html.span([attribute.class("cursor")], []), 128 - html.ul([], [ 129 - nav_link(page, Index), 130 - nav_link(page, Blog), 131 - nav_link(page, Dots), 132 - ]), 145 + html.ul([], list.map(links, nav_link)), 133 146 ]) 134 147 } 135 148 136 - fn nav_link(active: Page, link: Page) { 137 - let is_active = case active, link { 138 - BlogPost(_), Blog -> True 139 - _, _ if link == active -> True 140 - _, _ -> False 141 - } 142 - 149 + fn nav_link(link: Page) { 143 150 html.li([], [ 144 151 html.a( 145 152 [ 146 153 attribute.href(route(link)), 147 - attribute.classes([#("active", is_active)]), 154 + attribute.style("view-transition-name", nav_id(link)), 155 + ], 156 + [ 157 + html.text(title(link)), 148 158 ], 149 - [html.span([], [html.text(title(link))])], 150 159 ), 151 160 ]) 152 161 }