Compare commits
	
		
			2 Commits
		
	
	
		
			7c331406a5
			...
			5b11664a3f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5b11664a3f | |||
| ff1188b4b2 | 
| @@ -11,7 +11,6 @@ h3 { | ||||
|  | ||||
| article>h1 { | ||||
|   font-size: 28px; | ||||
|   margin-top: 24px; | ||||
| } | ||||
|  | ||||
| article>h2 { | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								public/projects/karl/favicon.png
									
									LFS
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/projects/karl/favicon.png
									
									LFS
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -19,7 +19,6 @@ | ||||
|     _img.addEventListener("load", () => { | ||||
|       img.classList.remove("thumb-loading"); | ||||
|       _img.style.opacity = "1"; | ||||
|       console.log("loaded"); | ||||
|     }); | ||||
|     if (_img?.alt) altText = _img.alt; | ||||
|     else altText = ""; | ||||
| @@ -62,10 +61,12 @@ | ||||
|   style={`--height:${height}px`} | ||||
| > | ||||
|   {#if title} | ||||
|     <div class="flex items-center p-x-4 bg justify-between"> | ||||
|     <div class="flex items-center p-x-4 p-y-6 bg justify-between"> | ||||
|       <h3>{title}</h3> | ||||
|  | ||||
|       <div class="overflow-hidden rounded-md bg-light gap-2 flex p-1"> | ||||
|       <div | ||||
|         class="overflow-hidden rounded-md bg-light gap-2 flex p-2 border border-light" | ||||
|       > | ||||
|         <button | ||||
|           class="flex-1 i-tabler-arrow-left" | ||||
|           aria-label="previous image" | ||||
| @@ -80,10 +81,10 @@ | ||||
|     </div> | ||||
|   {/if} | ||||
|  | ||||
|   <div class="images" bind:this={slot}> | ||||
|   <div class="images border-t-1 border-b-1 border-neutral" bind:this={slot}> | ||||
|     <slot /> | ||||
|   </div> | ||||
|   <div class="p-2 flex place-content-between bg"> | ||||
|   <div class="px-4 flex items-center place-content-between bg"> | ||||
|     <p> | ||||
|       {#if images?.length} | ||||
|         {index + 1}/{images?.length} | ||||
| @@ -97,7 +98,7 @@ | ||||
|  | ||||
| <style> | ||||
|   .wrapper { | ||||
|     grid-template-rows: 1fr 40px; | ||||
|     grid-template-rows: 1fr 50px; | ||||
|     transition: height 0.3s; | ||||
|   } | ||||
|  | ||||
| @@ -106,11 +107,11 @@ | ||||
|   } | ||||
|  | ||||
|   .wrapper.title { | ||||
|     grid-template-rows: 40px 1fr 40px; | ||||
|     grid-template-rows: 50px 1fr 50px; | ||||
|   } | ||||
|  | ||||
|   .loaded { | ||||
|     height: calc(var(--height) + 40px); | ||||
|     height: calc(var(--height) + 50px); | ||||
|   } | ||||
|  | ||||
|   .not-loaded .images :global(picture):first-child { | ||||
| @@ -118,7 +119,7 @@ | ||||
|   } | ||||
|  | ||||
|   .wrapper.title.loaded { | ||||
|     height: calc(var(--height) + 80px); | ||||
|     height: calc(var(--height) + 100px); | ||||
|   } | ||||
|  | ||||
|   .images :global(picture) { | ||||
| @@ -126,6 +127,10 @@ | ||||
|     display: none; | ||||
|   } | ||||
|  | ||||
|   .images :global(.thumb-loading)::before { | ||||
|     opacity: 0; | ||||
|   } | ||||
|  | ||||
|   .images :global(.active) { | ||||
|     position: relative; | ||||
|     display: block !important; | ||||
|   | ||||
| @@ -12,7 +12,7 @@ const { headings } = Astro.props; | ||||
|  | ||||
| <div class="toc-wrapper lg:fixed lg:left-6 lg:top-6"> | ||||
|   <details | ||||
|     class="py-2 px-4 rounded-xl border border-neutral flex flex-col bg gap-2" | ||||
|     class="py-2 lg:px-4 rounded-xl lg:border lg:border-neutral flex flex-col lg:bg gap-2" | ||||
|   > | ||||
|     <summary class="text-lg cursor-pointer select-none" | ||||
|       >{t("toc.title")}</summary | ||||
|   | ||||
| @@ -1,55 +0,0 @@ | ||||
| <script> | ||||
|   import { thumbHashToRGBA, rgbaToDataURL } from "thumbhash"; | ||||
|  | ||||
|   function show(img: HTMLImageElement) { | ||||
|     img.style.opacity = "1"; | ||||
|     img.style.filter = "blur(0px)"; | ||||
|     setTimeout(() => { | ||||
|       if (img.parentNode) { | ||||
|         (img.parentNode as HTMLPictureElement).style.background = ""; | ||||
|       } | ||||
|     }, 600); | ||||
|   } | ||||
|  | ||||
|   console.log("Thumbhash script loaded"); | ||||
|  | ||||
|   document.querySelectorAll("[data-thumbhash]").forEach((entry) => { | ||||
|     const parent = entry?.parentNode as HTMLPictureElement; | ||||
|     const img = entry as HTMLImageElement; | ||||
|  | ||||
|     if (parent?.nodeName !== "PICTURE") return; | ||||
|  | ||||
|     const hash = img.getAttribute("data-thumbhash"); | ||||
|     if (!hash) return; | ||||
|  | ||||
|     // its only browser, why you have to be mad | ||||
|     const decodedString = window.atob(hash); | ||||
|  | ||||
|     // Create Uint8Array from decoded string | ||||
|     const buffer = new Uint8Array(decodedString.length); | ||||
|     for (let i = 0; i < decodedString.length; i++) { | ||||
|       buffer[i] = decodedString.charCodeAt(i); | ||||
|     } | ||||
|  | ||||
|     const image = thumbHashToRGBA(buffer); | ||||
|     const dataURL = rgbaToDataURL(image.w, image.h, image.rgba); | ||||
|  | ||||
|     parent.style.background = `url(${dataURL})`; | ||||
|     parent.style.backgroundSize = "cover"; | ||||
|  | ||||
|     if (img.complete) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     img.style.opacity = "0"; | ||||
|     img.style.filter = "blur(5px)"; | ||||
|     img.style.transition = "opacity 0.6s ease, filter 0.8s ease"; | ||||
|  | ||||
|     const sources = parent.querySelectorAll("source"); | ||||
|  | ||||
|     img.onload = () => show(img); | ||||
|     for (const source of sources) { | ||||
|       source.addEventListener("load", () => show(img)); | ||||
|     } | ||||
|   }); | ||||
| </script> | ||||
| @@ -5,6 +5,7 @@ cover: ./images/Indicatrices_of_Distortion.png | ||||
| license: "CC-BY-SA:4.0" | ||||
| featured: true | ||||
| toc: true | ||||
| icon: /projects/karl/favicon.png | ||||
| links: | ||||
|   [ | ||||
|     ["live", "https://max-richter.dev/karl"], | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
| import Layout from "@layouts/Layout.astro"; | ||||
| import { getCollection } from "astro:content"; | ||||
| import { useTranslatedPath } from "@i18n/utils"; | ||||
| import SmallCard from "@components/SmallCard.astro"; | ||||
| import SmallGrid from "@components/SmallGrid.astro"; | ||||
|  | ||||
| const collections = ["blog", "photos", "projects"] as const; | ||||
|  | ||||
| @@ -48,18 +50,15 @@ const posts = allPosts.filter((post) => { | ||||
|  | ||||
| <Layout title="Max Richter"> | ||||
|   <article> | ||||
|     <h1>Tags</h1> | ||||
|     {posts.length} | ||||
|     <div class="flex flex-col gap-2"> | ||||
|     <h1>Tag: {tag}</h1> | ||||
|     <SmallGrid> | ||||
|       { | ||||
|         posts.map((post) => { | ||||
|           return ( | ||||
|             <a href={tp("/" + post.collection + "/" + post.slug)}> | ||||
|               {post.slug} | ||||
|             </a> | ||||
|             <SmallCard post={post} /> | ||||
|           ); | ||||
|         }) | ||||
|       } | ||||
|     </div> | ||||
|     </SmallGrid> | ||||
|   </article> | ||||
| </Layout> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user