Compare commits
	
		
			2 Commits
		
	
	
		
			7c331406a5
			...
			5b11664a3f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5b11664a3f | |||
| ff1188b4b2 | 
| @@ -11,7 +11,6 @@ h3 { | |||||||
|  |  | ||||||
| article>h1 { | article>h1 { | ||||||
|   font-size: 28px; |   font-size: 28px; | ||||||
|   margin-top: 24px; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| article>h2 { | 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.addEventListener("load", () => { | ||||||
|       img.classList.remove("thumb-loading"); |       img.classList.remove("thumb-loading"); | ||||||
|       _img.style.opacity = "1"; |       _img.style.opacity = "1"; | ||||||
|       console.log("loaded"); |  | ||||||
|     }); |     }); | ||||||
|     if (_img?.alt) altText = _img.alt; |     if (_img?.alt) altText = _img.alt; | ||||||
|     else altText = ""; |     else altText = ""; | ||||||
| @@ -62,10 +61,12 @@ | |||||||
|   style={`--height:${height}px`} |   style={`--height:${height}px`} | ||||||
| > | > | ||||||
|   {#if title} |   {#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> |       <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 |         <button | ||||||
|           class="flex-1 i-tabler-arrow-left" |           class="flex-1 i-tabler-arrow-left" | ||||||
|           aria-label="previous image" |           aria-label="previous image" | ||||||
| @@ -80,10 +81,10 @@ | |||||||
|     </div> |     </div> | ||||||
|   {/if} |   {/if} | ||||||
|  |  | ||||||
|   <div class="images" bind:this={slot}> |   <div class="images border-t-1 border-b-1 border-neutral" bind:this={slot}> | ||||||
|     <slot /> |     <slot /> | ||||||
|   </div> |   </div> | ||||||
|   <div class="p-2 flex place-content-between bg"> |   <div class="px-4 flex items-center place-content-between bg"> | ||||||
|     <p> |     <p> | ||||||
|       {#if images?.length} |       {#if images?.length} | ||||||
|         {index + 1}/{images?.length} |         {index + 1}/{images?.length} | ||||||
| @@ -97,7 +98,7 @@ | |||||||
|  |  | ||||||
| <style> | <style> | ||||||
|   .wrapper { |   .wrapper { | ||||||
|     grid-template-rows: 1fr 40px; |     grid-template-rows: 1fr 50px; | ||||||
|     transition: height 0.3s; |     transition: height 0.3s; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -106,11 +107,11 @@ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   .wrapper.title { |   .wrapper.title { | ||||||
|     grid-template-rows: 40px 1fr 40px; |     grid-template-rows: 50px 1fr 50px; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .loaded { |   .loaded { | ||||||
|     height: calc(var(--height) + 40px); |     height: calc(var(--height) + 50px); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .not-loaded .images :global(picture):first-child { |   .not-loaded .images :global(picture):first-child { | ||||||
| @@ -118,7 +119,7 @@ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   .wrapper.title.loaded { |   .wrapper.title.loaded { | ||||||
|     height: calc(var(--height) + 80px); |     height: calc(var(--height) + 100px); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .images :global(picture) { |   .images :global(picture) { | ||||||
| @@ -126,6 +127,10 @@ | |||||||
|     display: none; |     display: none; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   .images :global(.thumb-loading)::before { | ||||||
|  |     opacity: 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   .images :global(.active) { |   .images :global(.active) { | ||||||
|     position: relative; |     position: relative; | ||||||
|     display: block !important; |     display: block !important; | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ const { headings } = Astro.props; | |||||||
|  |  | ||||||
| <div class="toc-wrapper lg:fixed lg:left-6 lg:top-6"> | <div class="toc-wrapper lg:fixed lg:left-6 lg:top-6"> | ||||||
|   <details |   <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" |     <summary class="text-lg cursor-pointer select-none" | ||||||
|       >{t("toc.title")}</summary |       >{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" | license: "CC-BY-SA:4.0" | ||||||
| featured: true | featured: true | ||||||
| toc: true | toc: true | ||||||
|  | icon: /projects/karl/favicon.png | ||||||
| links: | links: | ||||||
|   [ |   [ | ||||||
|     ["live", "https://max-richter.dev/karl"], |     ["live", "https://max-richter.dev/karl"], | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ | |||||||
| import Layout from "@layouts/Layout.astro"; | import Layout from "@layouts/Layout.astro"; | ||||||
| import { getCollection } from "astro:content"; | import { getCollection } from "astro:content"; | ||||||
| import { useTranslatedPath } from "@i18n/utils"; | import { useTranslatedPath } from "@i18n/utils"; | ||||||
|  | import SmallCard from "@components/SmallCard.astro"; | ||||||
|  | import SmallGrid from "@components/SmallGrid.astro"; | ||||||
|  |  | ||||||
| const collections = ["blog", "photos", "projects"] as const; | const collections = ["blog", "photos", "projects"] as const; | ||||||
|  |  | ||||||
| @@ -48,18 +50,15 @@ const posts = allPosts.filter((post) => { | |||||||
|  |  | ||||||
| <Layout title="Max Richter"> | <Layout title="Max Richter"> | ||||||
|   <article> |   <article> | ||||||
|     <h1>Tags</h1> |     <h1>Tag: {tag}</h1> | ||||||
|     {posts.length} |     <SmallGrid> | ||||||
|     <div class="flex flex-col gap-2"> |  | ||||||
|       { |       { | ||||||
|         posts.map((post) => { |         posts.map((post) => { | ||||||
|           return ( |           return ( | ||||||
|             <a href={tp("/" + post.collection + "/" + post.slug)}> |             <SmallCard post={post} /> | ||||||
|               {post.slug} |  | ||||||
|             </a> |  | ||||||
|           ); |           ); | ||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|     </div> |     </SmallGrid> | ||||||
|   </article> |   </article> | ||||||
| </Layout> | </Layout> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user