i can't stop obsessing over the blog layout smdh
							
								
								
									
										
											BIN
										
									
								
								public/fonts/dotum-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								public/fonts/dotumche-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								src/assets/buttons.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
| Before Width: | Height: | Size: 254 B | 
| Before Width: | Height: | Size: 252 B | 
| Before Width: | Height: | Size: 252 B | 
| Before Width: | Height: | Size: 255 B | 
| Before Width: | Height: | Size: 255 B | 
| Before Width: | Height: | Size: 255 B | 
| @ -10,8 +10,7 @@ | ||||
|   --sans-font: "Super Star", 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; | ||||
|   --arial-font: "Arial Pixel", Arial, Helvetica, sans-serif; | ||||
|   --pmd-font: "Wonder Mail", Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif; | ||||
|   --mplus-10-font: "PixelMPlus 10", "MS Gothic", system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, system-ui-ko, sans-serif; | ||||
|   --mplus-12-font: "PixelMPlus 12", "MS Gothic", system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, system-ui-ko, sans-serif; | ||||
|   --dotum-font: "DotumChe", "Dotum", system-ui-ko, system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, monospace, sans-serif; | ||||
| 
 | ||||
|   @media screen and (prefers-color-scheme: light) { | ||||
|     --bg-color: #e6f2ef; | ||||
|  | ||||
| @ -2,12 +2,14 @@ | ||||
|   font-family: "Arial Pixel"; | ||||
|   src: url("/fonts/pixearg.woff2") format("woff2"); | ||||
|   font-weight: normal; | ||||
|   font-display: fallback; | ||||
| } | ||||
| 
 | ||||
| @font-face { | ||||
|   font-family: "Arial Pixel"; | ||||
|   src: url("/fonts/pixeab.woff2") format("woff2"); | ||||
|   font-weight: bold; | ||||
|   font-display: fallback; | ||||
| } | ||||
| 
 | ||||
| @font-face { | ||||
| @ -16,6 +18,18 @@ | ||||
|   font-weight: normal; | ||||
| } | ||||
| 
 | ||||
| @font-face { | ||||
|   font-family: "Dotum"; | ||||
|   src: url("/fonts/dotum-Regular.woff2") format("woff2"); | ||||
|   font-weight: normal; | ||||
| } | ||||
| 
 | ||||
| @font-face { | ||||
|   font-family: "DotumChe"; | ||||
|   src: url("/fonts/dotumche-Regular.woff2") format("woff2"); | ||||
|   font-weight: normal; | ||||
| } | ||||
| 
 | ||||
| @font-face { | ||||
|   font-family: "Kiwi Soda"; | ||||
|   src: url("/fonts/KiwiSoda.woff2") format("woff2"); | ||||
|  | ||||
| @ -26,10 +26,17 @@ const { title, date, currently } = Astro.props; | ||||
| 
 | ||||
| const blog = await getCollection("blog"); | ||||
| blog.length = Math.min(blog.length, 12); | ||||
| blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
| blog.sort((a, b) => b.data.pubDate!.valueOf() - a.data.pubDate!.valueOf()); | ||||
| --- | ||||
| <Layout {title}> | ||||
|   <slot slot="head" name="head" /> | ||||
|   <Fragment slot="head"> | ||||
|     <link rel="preload" href={outerBBS.src} as="image" /> | ||||
|     <link rel="preload" href={innerBBS.src} as="image" /> | ||||
|     <link rel="preload" href={sideBBS.src} as="image" /> | ||||
|     <link rel="preload" href="/fonts/pixearg.woff2" as="font" /> | ||||
|     <link rel="preload" href="/fonts/pixeab.woff2" as="font" /> | ||||
|     <slot name="head" /> | ||||
|   </Fragment> | ||||
|   <Navbar /> | ||||
| 
 | ||||
|   <main> | ||||
| @ -143,15 +150,19 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
|     --border-4: #88aabb; | ||||
|     --border-5: #99bbcc; | ||||
|     --border-6: #bbccdd; | ||||
|     --normal-color: #335577; | ||||
|     --active-color: #aa0033; | ||||
|     --active-border: #442266; | ||||
|     color: #000; | ||||
|   } | ||||
|   h1 { font: bold 1rem var(--arial-font); } | ||||
|   h2 { | ||||
|     font: normal 1.5rem var(--mplus-12-font); | ||||
|     font: normal 1rem var(--dotum-font); | ||||
|     text-transform: uppercase; | ||||
|   } | ||||
|   main { | ||||
|     font: 1rem var(--arial-font); | ||||
|     letter-spacing: 1px; | ||||
|     display: grid; | ||||
|     grid-template-columns: auto minmax(auto, 75ch); | ||||
|     justify-content: center; | ||||
| @ -211,8 +222,7 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
| 
 | ||||
|         .item { | ||||
|           position: relative; | ||||
|           font-family: var(--mplus-10-font); | ||||
|           font-size: 1.25rem; /* this should be 20px */ | ||||
|           font: bold 1em var(--dotum-font); | ||||
|           display: flex; | ||||
|           justify-content: space-between; | ||||
|           align-items: center; | ||||
| @ -225,6 +235,17 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
|               left: 0; | ||||
|               width: 100%; | ||||
|               height: 100%; | ||||
| 
 | ||||
|               ~ .link { | ||||
|                 white-space: nowrap; | ||||
|                 overflow: hidden; | ||||
|                 text-overflow: ellipsis; | ||||
|                 /* max-width: 19ch; */ | ||||
| 
 | ||||
|                 @media screen and (max-width: 76em) { | ||||
|                   max-width: unset; | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
| 
 | ||||
| @ -269,7 +290,6 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
|    | ||||
|   article { | ||||
|     display: flex; | ||||
|     letter-spacing: 1px; | ||||
|     border: 2px solid var(--border-0); | ||||
|     border-image: var(--outerBorder) 19 9 38 11 fill / 38px 18px 76px 22px; | ||||
|     background-color: var(--bg-3); | ||||
| @ -286,7 +306,9 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
|     } | ||||
| 
 | ||||
|     .title { | ||||
|       font: normal 1.5rem var(--mplus-12-font); | ||||
|       display: grid; | ||||
|       place-content: center; | ||||
|       font: normal 1.25em var(--dotum-font); | ||||
|       background-color: var(--bg-2); | ||||
|       padding: 2px 6px; | ||||
|     } | ||||
| @ -316,9 +338,10 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
|         border-color: var(--bg-2) var(--bg-2) var(--bg-1) var(--bg-1); | ||||
|         padding: 2px 4px; | ||||
| 
 | ||||
|         time, .section { | ||||
|         time { | ||||
|           display: flex; | ||||
|           width: 100%; | ||||
|           align-items: stretch; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
| @ -345,6 +368,19 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); | ||||
| 
 | ||||
|       p { margin-block: 1lh; } | ||||
|       a, del, s { text-decoration-thickness: 2px; } | ||||
|       a { | ||||
|         color: var(--normal-color); | ||||
| 
 | ||||
|         &:visited { | ||||
|           color: var(--active-border); | ||||
|         } | ||||
|         &:hover { | ||||
|           color: var(--active-color); | ||||
|         } | ||||
|         &:active, &:focus { | ||||
|           color: var(--normal-color); | ||||
|         } | ||||
|       } | ||||
|        | ||||
|       @supports not (margin-trim: block) { | ||||
|         :first-child { margin-block-start: 0; } | ||||
|  | ||||
| @ -2,13 +2,7 @@ | ||||
| import Blog from '@/layouts/Blog.astro'; | ||||
| import type { GetStaticPaths } from 'astro'; | ||||
| import { getCollection, render } from 'astro:content'; | ||||
| 
 | ||||
| import leftNormal from "$/left-normal.png"; | ||||
| import leftHover from "$/left-hover.png"; | ||||
| import leftActive from "$/left-active.png"; | ||||
| import rightNormal from "$/right-normal.png"; | ||||
| import rightHover from "$/right-hover.png"; | ||||
| import rightActive from "$/right-active.png"; | ||||
| import buttons from "$/buttons.png"; | ||||
| 
 | ||||
| export const getStaticPaths = (async () => { | ||||
|   const blog = await getCollection("blog"); | ||||
| @ -30,30 +24,37 @@ const next = current === 0 ? undefined : blog[current - 1]; | ||||
| <Blog title={entry.data.title!} date={entry.data.pubDate!} currently={entry.data.currently}> | ||||
|   <Fragment slot="head"> | ||||
|     <meta name="description" content={entry.body?.substring(0, 150) + "…"}> | ||||
|     <link rel="preload" href={buttons.src} as="image" /> | ||||
|   </Fragment> | ||||
| 
 | ||||
|   <Content /> | ||||
| 
 | ||||
|   {(previous || next) && ( | ||||
|     <div id="blog-pagination" slot="pagination"> | ||||
|     <footer id="blog-pagination" slot="pagination"> | ||||
|       {previous && ( | ||||
|         <a id="previous" aria-label="previous post" href={`/blog/${previous.id}`}> | ||||
|           <img class="arrow" src={leftNormal.src} alt="" /> | ||||
|           {previous.data.title} | ||||
|         <a id="previous" aria-label="go to previous post" href={`/blog/${previous.id}`}> | ||||
|           <div class="arrow" /> | ||||
|           <div class="title"> | ||||
|             <span>{previous.data.title}</span> | ||||
|           </div> | ||||
|         </a> | ||||
|       )} | ||||
| 
 | ||||
|       {next && ( | ||||
|         <a id="next" aria-label="next post" href={`/blog/${next.id}`}> | ||||
|           {next.data.title} | ||||
|           <img class="arrow" src={rightNormal.src} alt="" /> | ||||
|         <a id="next" aria-label="go to next post" href={`/blog/${next.id}`}> | ||||
|           <div class="title"> | ||||
|             <span>{next.data.title}</span> | ||||
|           </div> | ||||
|           <div class="arrow" /> | ||||
|         </a> | ||||
|       )} | ||||
|     </div> | ||||
|     </footer> | ||||
|   )} | ||||
| </Blog> | ||||
| 
 | ||||
| <style define:vars={{ leftNormal: `url(${leftNormal.src})`, leftHover: `url(${leftHover.src})`, leftActive: `url(${leftActive.src})`, rightNormal: `url(${rightNormal.src})`, rightHover: `url(${rightHover.src})`, rightActive: `url(${rightActive.src})` }}> | ||||
| <style define:vars={{ buttons: `url(${buttons.src})` }}> | ||||
|   #blog-pagination { | ||||
|     margin: 1rem 0; | ||||
|     display: grid; | ||||
|     grid-column: 1 / -1; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
| @ -61,33 +62,87 @@ const next = current === 0 ? undefined : blog[current - 1]; | ||||
|     .arrow { | ||||
|       width: 36px; | ||||
|       height: 50px; | ||||
|       background: var(--buttons) no-repeat top left; | ||||
|     } | ||||
| 
 | ||||
|     #previous { | ||||
|       grid-column: 1 / 2; | ||||
|       justify-self: left; | ||||
|        | ||||
|       .arrow { content: var(--leftNormal) var(--leftHover) var(--leftActive); } | ||||
|       &:hover .arrow { content: var(--leftHover); } | ||||
|       &:active .arrow, &:focus .arrow { content: var(--leftActive); } | ||||
|       .arrow { background-position: 0 0; } | ||||
|       &:hover .arrow { background-position: -36px 0; } | ||||
|       &:active .arrow, &:focus .arrow { background-position: -72px 0; } | ||||
| 
 | ||||
|       .title { | ||||
|         border-left: none; | ||||
|         margin-left: -2px; | ||||
|         padding-left: calc(0.5em + 2px); | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     #next { | ||||
|       grid-column: 2 / -1; | ||||
|       justify-self: right; | ||||
| 
 | ||||
|       .arrow { content: var(--rightNormal) var(--rightHover) var(--rightActive); } | ||||
|       &:hover .arrow { content: var(--rightHover); } | ||||
|       &:active .arrow, &:focus .arrow { content: var(--rightActive); } | ||||
|       .arrow { background-position: -108px 0; } | ||||
|       &:hover .arrow { background-position: -144px 0; } | ||||
|       &:active .arrow, &:focus .arrow { background-position: -180px 0; } | ||||
| 
 | ||||
|       .title { | ||||
|         position: relative; | ||||
|         z-index: 1; | ||||
|         border-right: none; | ||||
|         margin-right: -2px; | ||||
|         padding-right: calc(0.5em + 2px); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     a { | ||||
|       display: flex; | ||||
|       flex-flow: row wrap; | ||||
|       align-items: center; | ||||
|       gap: 2px; | ||||
|       color: var(--bg-0); | ||||
|       align-items: stretch; | ||||
|       font: bold larger var(--dotum-font); | ||||
|       color: var(--normal-color); | ||||
|       text-decoration: none; | ||||
| 
 | ||||
|       .title { | ||||
|         display: grid; | ||||
|         place-content: center; | ||||
|         padding: 0 0.5em; | ||||
|         background-color: var(--bg-7); | ||||
|         border: 2px solid var(--border-1); | ||||
|         box-shadow:  | ||||
|           inset 2px 2px 0 0 var(--bg-0), | ||||
|           inset 4px 4px 0 0 var(--bg-5), | ||||
|           inset -2px -2px 0 0 var(--border-5), | ||||
|           inset -4px -4px 0 0 var(--border-6); | ||||
|          | ||||
|         @media screen and (468px > width) { | ||||
|           > span { | ||||
|             white-space: nowrap; | ||||
|             overflow: hidden; | ||||
|             text-overflow: ellipsis; | ||||
|             max-width: calc(12ch + 1em); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       &:hover { | ||||
|         color: var(--active-color); | ||||
|         .title { border-color: var(--active-border); } | ||||
|       } | ||||
| 
 | ||||
|       &:active, &:focus { | ||||
|         color: var(--normal-color); | ||||
|         .title { | ||||
|           border-color: var(--border-1); | ||||
|           box-shadow:  | ||||
|             inset -2px -2px 0 0 var(--bg-0), | ||||
|             inset -4px -4px 0 0 var(--bg-5), | ||||
|             inset 2px 2px 0 0 var(--border-5), | ||||
|             inset 4px 4px 0 0 var(--border-6); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @ -1,16 +1,14 @@ | ||||
| --- | ||||
| import Layout from "@/layouts/Layout.astro"; | ||||
| import formatDate from "@/utils/formatDate"; | ||||
| import { getCollection } from "astro:content"; | ||||
| import dayjs from "dayjs"; | ||||
| import utc from "dayjs/plugin/utc"; | ||||
| 
 | ||||
| const blog = await getCollection("blog"); | ||||
| const sorted = Object.groupBy(blog, ({ data }) => data.pubDate!.getMonth()); | ||||
| 
 | ||||
| dayjs.extend(utc); | ||||
| const getMonth = (id: number) => { | ||||
| function getMonth(id: number): string { | ||||
|   let date = new Date(); | ||||
|   date.setDate(1); | ||||
|   date.setMonth(id); | ||||
|   return dayjs(date).format("MMMM"); | ||||
| } | ||||
| @ -27,8 +25,8 @@ const getMonth = (id: number) => { | ||||
|         <ul> | ||||
|           {entry[1]?.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()).map(post => ( | ||||
|             <li> | ||||
|               <time datetime={dayjs(post.data.pubDate).utc(true).toISOString()}> | ||||
|                 {dayjs(post.data.pubDate).utc(true).format("MMMM DD, YYYY")} | ||||
|               <time datetime={formatDate(post.data.pubDate!, true)}> | ||||
|                 {formatDate(post.data.pubDate!)} | ||||
|               </time> | ||||
|               <a href={`/blog/${post.id}`}>{post.data.title}</a> | ||||
|             </li> | ||||
|  | ||||