experimenting with making decentralized fanfic archives on atproto. github mirror: https://github.com/haetae-bit/fanfic-atproto

clean up css

+10
README.md
··· 62 62 63 63 This has images / libre font / `.css` files to be used stylistically throughout the site. 64 64 65 + ##### Styles (AKA, abomination) 66 + 67 + This is the most messed up design system but I sure tried my best with it. The base style uses [daisyui](https://daisyui.com/docs/) and [UnoCSS](https://unocss.dev/guide/), which means the configurations are Strange(tm). Beware of `uno.config.ts`, please don't poke it too hard unless you know what you're doing. 68 + 69 + This uses CSS layers to make things work. Any styles used in `base.css` will overwrite everything else across the entire site. This should only be modified sparingly. 70 + 71 + All styling should be *within* components or pages via HTML classes or within scoped `<style>` blocks. There are various colors and sizes to keep track of - at some point, I'll document them. 72 + 73 + To make contribute new themes, check out the examples inside the `src/assets/styles/themes` folder. You can use the [daisyui Theme Generator](https://daisyui.com/theme-generator/) to quickly build a theme! 74 + 65 75 #### Components: `src/components` 66 76 67 77 These hold components that are reused throughout `src/pages`. Like PHP includes but in HTML and JavaScript (well, technically it's JSX).
lexicon/moe/fanfics/chapter.json lexicons/moe/fanfics/chapter.json
lexicon/moe/fanfics/comment.json lexicons/moe/fanfics/comment.json
lexicon/moe/fanfics/work.json lexicons/moe/fanfics/work.json
+39 -15
src/assets/styles/base.css
··· 1 - @import "reset.css"; 1 + /* import themes here */ 2 2 @import "./themes/evergarden.css"; 3 3 @import "./themes/rosepine.css"; 4 4 5 5 :root { 6 6 /* size tokens */ 7 7 /* @link https://utopia.fyi/type/calculator?c=360,18,1.067,1240,20,1.125,10,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,NaN */ 8 - --text-xs: clamp(0.9877rem, 0.9884rem + -0.0009vw, 0.9882rem); 9 - --text-sm: clamp(1.0544rem, 1.0311rem + 0.1032vw, 1.1111rem); 10 - --text-base: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem); 11 - --text-lg: clamp(1.2004rem, 1.1162rem + 0.3743vw, 1.4063rem); 12 - --text-xl: clamp(1.2808rem, 1.1576rem + 0.5477vw, 1.582rem); 13 - --text-2xl: clamp(1.3666rem, 1.1976rem + 0.7512vw, 1.7798rem); 14 - --text-3xl: clamp(1.4582rem, 1.2356rem + 0.9892vw, 2.0023rem); 15 - --text-4xl: clamp(1.5559rem, 1.2709rem + 1.2667vw, 2.2525rem); 16 - --text-5xl: clamp(1.6601rem, 1.3026rem + 1.5891vw, 2.5341rem); 17 - --text-6xl: clamp(1.7713rem, 1.3297rem + 1.9628vw, 2.8509rem); 18 - --text-7xl: clamp(1.89rem, 1.3512rem + 2.3949vw, 3.2072rem); 19 - --text-8xl: clamp(2.0167rem, 1.3656rem + 2.8936vw, 3.6081rem); 20 - --text-9xl: clamp(2.1518rem, 1.3715rem + 3.468vw, 4.0592rem); 8 + --step--2: clamp(0.9877rem, 0.9884rem + -0.0009vw, 0.9882rem); 9 + --step--1: clamp(1.0544rem, 1.0311rem + 0.1032vw, 1.1111rem); 10 + --step-0: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem); 11 + --step-1: clamp(1.2004rem, 1.1162rem + 0.3743vw, 1.4063rem); 12 + --step-2: clamp(1.2808rem, 1.1576rem + 0.5477vw, 1.582rem); 13 + --step-3: clamp(1.3666rem, 1.1976rem + 0.7512vw, 1.7798rem); 14 + --step-4: clamp(1.4582rem, 1.2356rem + 0.9892vw, 2.0023rem); 15 + --step-5: clamp(1.5559rem, 1.2709rem + 1.2667vw, 2.2525rem); 16 + --step-6: clamp(1.6601rem, 1.3026rem + 1.5891vw, 2.5341rem); 17 + --step-7: clamp(1.7713rem, 1.3297rem + 1.9628vw, 2.8509rem); 18 + --step-8: clamp(1.89rem, 1.3512rem + 2.3949vw, 3.2072rem); 19 + --step-9: clamp(2.0167rem, 1.3656rem + 2.8936vw, 3.6081rem); 20 + --step-10: clamp(2.1518rem, 1.3715rem + 3.468vw, 4.0592rem); 21 + 22 + /* space tokens */ 23 + /* @link https://utopia.fyi/space/calculator?c=360,18,1.067,1240,20,1.125,10,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,NaN */ 24 + --space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem); 25 + --space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem); 26 + --space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem); 27 + --space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem); 28 + --space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem); 29 + --space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem); 30 + --space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem); 31 + --space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem); 32 + --space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem); 21 33 22 34 /* font tokens */ 23 35 --font-serif: var(--plex-serif); ··· 32 44 @supports (min-height: 100svh) { 33 45 min-height: 100svh; 34 46 } 35 - } 47 + } 48 + 49 + h1, h2, h3 { 50 + font-family: var(--font-display); 51 + font-weight: normal; 52 + } 53 + h4, h5, h6 { font-family: var(--font-sans); } 54 + h1 { font-size: var(--step-6); } 55 + h2 { font-size: var(--step-5); } 56 + h3 { font-size: var(--step-4); } 57 + h4 { font-size: var(--step-3); } 58 + h5 { font-size: var(--step-2); } 59 + h6 { font-size: var(--step-1); }
+3 -3
src/components/Navbar.astro
··· 6 6 --- 7 7 <nav id="main-nav" class="navbar bg-base-100"> 8 8 <div class="flex-1"> 9 - <a href="/" class="btn btn-ghost font-display text-xl">Home</a> 9 + <a href="/" class="font-display text-xl ml-3">Home</a> 10 10 </div> 11 - <div class="flex items-center gap2"> 11 + <div class="flex items-center gap-2"> 12 12 <search> 13 13 <form action="" method="get"> 14 14 <input type="search" class="input" /> ··· 24 24 : <li><a href="/login">Login</a></li> 25 25 } 26 26 <li> 27 - <button id="trigger-settings" class="btn btn-neutral btn-square"> 27 + <button id="trigger-settings" class="btn btn-neutral btn-square ml-3"> 28 28 <Cog aria-label="Open settings" /> 29 29 </button> 30 30 </li>
+4 -5
src/components/Popover.astro
··· 45 45 <div 46 46 {id} 47 47 class:list={[ 48 - "popover-content", 48 + "popover-content card w-72 border-2 border-accent shadow shadow-inherit", 49 49 className, 50 50 ]} 51 - role="tooltip" 51 + role="tooltip" 52 52 popover="auto" 53 53 {...rest} 54 54 > ··· 69 69 } 70 70 71 71 .popover-content { 72 - @apply dropdown card mx-0 inset-auto bg-base-100 w-72 shadow; 72 + @apply dropdown bg-base-100; 73 73 74 74 @supports (position-anchor: var(--anchor)) and (left: anchor(center)) { 75 75 position-anchor: var(--anchor); ··· 85 85 86 86 triggers.forEach(trigger => { 87 87 const btn = trigger as HTMLButtonElement; 88 - // triggering button will always end with "-trigger" 89 - // so slice that from the id 88 + // triggering button will always end with "-trigger", so slice that from the id 90 89 const id = btn.id.slice(0, -8); 91 90 const popover = document.getElementById(`${id}`) as HTMLElement; 92 91
+15 -15
src/components/Settings.astro
··· 15 15 </fieldset> 16 16 17 17 <fieldset class="fieldset"> 18 - <label for="font-family">Font family</label> 19 - <select class="select" name="fontFamily" id="font-family"> 18 + <label for="font-family" class="label">Font family</label> 19 + <select name="fontFamily" id="font-family" class="select"> 20 20 <option value="default">Choose...</option> 21 21 <option value="--font-serif">serif</option> 22 22 <option value="--font-mono">monospaced</option> ··· 26 26 </fieldset> 27 27 28 28 <fieldset class="fieldset"> 29 - <label for="font-size">text size</label> 30 - <input class="range" type="range" name="fontSize" id="font-size" min="-1" max="2" step="1" /> 29 + <label for="font-size" class="label">Text size</label> 30 + <input class="range" type="range" name="fontSize" id="font-size" min="-1" max="2" step="1" value="0" /> 31 31 </fieldset> 32 32 33 33 <fieldset class="fieldset"> 34 - <label for="line-height">line height</label> 35 - <input class="range" type="range" name="lineHeight" id="line-height" min="1" max="2" step="0.05" /> 34 + <label for="line-height" class="label">Line height</label> 35 + <input class="range" type="range" name="lineHeight" id="line-height" min="1" max="2" step="0.05" value="1" /> 36 36 </fieldset> 37 37 38 38 <fieldset class="fieldset"> 39 - <label for="letter-spacing">letter spacing</label> 40 - <input class="range" type="range" name="letterSpacing" id="letter-spacing" min="0" max="0.1" step="0.01" /> 39 + <label for="letter-spacing" class="label">Letter spacing</label> 40 + <input class="range" type="range" name="letterSpacing" id="letter-spacing" min="0" max="0.1" step="0.01" value="0" /> 41 41 </fieldset> 42 42 43 43 <fieldset class="fieldset"> 44 - <label for="word-spacing">word spacing</label> 45 - <input class="range" type="range" name="wordSpacing" id="word-spacing" min="0" max="0.5" step="0.01" /> 44 + <label for="word-spacing" class="label">Word spacing</label> 45 + <input class="range" type="range" name="wordSpacing" id="word-spacing" min="0" max="0.5" step="0.01" value="0" /> 46 46 </fieldset> 47 47 48 48 <div id="test-area" class="mt-4 text-(length:--size) leading-(--line-height) tracking-(--letter-spacing) line-clamp-4"> 49 49 <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Asperiores quae dolorum debitis vero nostrum nobis aspernatur ipsam sunt dolorem, eum ut corrupti unde commodi soluta natus repellendus totam animi adipisci.</p> 50 50 </div> 51 51 52 + <!-- reset here? --> 53 + 52 54 <div class="modal-action"> 53 55 <button formmethod="dialog" value="default" class="btn btn-neutral">Cancel</button> 54 56 <button id="confirm-settings" class="btn btn-primary">Save</button> ··· 78 80 const submitter = document.getElementById("confirm-settings"); 79 81 const test = document.getElementById("test-area"); 80 82 83 + // on load, grab the preferences from private data 84 + 81 85 form?.addEventListener("submit", (e) => { 82 86 const target = e.target as HTMLFormElement; 83 - if (target.nodeValue === null) { 84 - return; 85 - } else { 86 - e.preventDefault(); 87 - } 87 + if (target.nodeValue === null) return; e.preventDefault(); 88 88 }); 89 89 90 90 inputs.forEach((input) => {
+4 -6
src/layouts/Layout.astro
··· 18 18 <meta name="viewport" content="width=device-width" /> 19 19 <title>{title}</title> 20 20 <Font cssVariable="--quattro" preload /> 21 - <Font cssVariable="--dyslexic" preload /> 22 - <Font cssVariable="--intel-mono" preload /> 23 - <Font cssVariable="--plex-serif" preload /> 21 + <Font cssVariable="--dyslexic" /> 22 + <Font cssVariable="--intel-mono" /> 23 + <Font cssVariable="--plex-serif" /> 24 24 <Font cssVariable="--jacquard-12" preload /> 25 25 <slot name="head" /> 26 26 </head> ··· 33 33 <Navbar /> 34 34 </header> 35 35 36 - <div class:list={["sm:w-10/12 sm:mx-auto max-w-full mx-6 text-base", className]} {...rest}> 36 + <div class:list={["sm:w-10/12 sm:mx-auto max-w-full mx-6 mb-5", className]} {...rest}> 37 37 <slot /> 38 38 </div> 39 39 ··· 44 44 </html> 45 45 46 46 <style> 47 - @reference "../assets/styles/global.css"; 48 - 49 47 .skip-link { 50 48 @apply absolute top-3 -left-full transition-all ease-in-out btn btn-ghost; 51 49
+1 -1
src/pages/errors/not-found.astro
··· 2 2 import Layout from "@/layouts/Layout.astro"; 3 3 --- 4 4 <Layout> 5 - <h1 class="title">Not found!</h1> 5 + <h1>Not found!</h1> 6 6 <p>There's a chance that the resource you're looking for doesn't exist or there was a typo in the URL.</p> 7 7 <p>You can go back to the <a href="/">home page</a> or report the issue through the contact form.</p> 8 8 </Layout>
+1 -1
src/pages/errors/unauthorized.astro
··· 2 2 import Layout from "@/layouts/Layout.astro"; 3 3 --- 4 4 <Layout> 5 - <h1 class="title">Unauthorized</h1> 5 + <h1>Unauthorized</h1> 6 6 <p>You don't have the proper permissions to make that operation.</p> 7 7 </Layout>
+1 -1
src/pages/index.astro
··· 5 5 --- 6 6 <Layout skipLink="content"> 7 7 <main id="content"> 8 - <h1 class="font-display text-xl">hi</h1> 8 + <h1>hi</h1> 9 9 <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Praesentium eum est quisquam distinctio magni recusandae quia vero tempore consectetur! Dolore repellat, voluptatem dignissimos sit eaque iste atque facilis in saepe?</p> 10 10 <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem, maxime libero eveniet repellat corporis, architecto voluptate maiores ullam accusamus quasi nostrum nihil placeat cum earum ex voluptatum, harum sunt quam!</p> 11 11 </main>
+1 -1
src/pages/login.astro
··· 6 6 --- 7 7 <Layout> 8 8 <main id="content"> 9 - <h1 class="font-display text-xl">Log in</h1> 9 + <h1>Log in</h1> 10 10 { 11 11 currentUser ? ( 12 12 // If there's a current user, show the log out button
+1 -1
src/pages/user/[userDid].astro
··· 16 16 } 17 17 --- 18 18 <Layout> 19 - <h1 class="title"> 19 + <h1> 20 20 {user.Users.nickname 21 21 ? user.Users.nickname 22 22 : await didToHandle(user.Users.userDid)}
+8 -9
src/pages/works/index.astro
··· 12 12 --- 13 13 14 14 <Layout> 15 - <h1 class="title">Works</h1> 15 + <h1>Works</h1> 16 16 17 17 <main id="content" class="flex flex-col gap-5 max-w-full"> 18 18 {loggedInUser && ··· 37 37 {Works.createdAt.toLocaleDateString()} 38 38 </time> 39 39 </div> 40 - {JSON.stringify(Works.tags)} 41 - {/* <ul class="flex flex-wrap gap-1.5"> 42 - {(Works.tags as Tag[]).map((tag: Tag) => ( 43 - <li><a class="tag" href={tag.url}>{tag.label}</a></li> 44 - ))} 45 - </ul> */} 40 + {Array.isArray(Works.tags) 41 + ? (<ul class="flex flex-wrap gap-1.5"> 42 + {(Works.tags as Tag[]).map((tag: Tag) => ( 43 + <li><a class="tag" href={tag.url}>{tag.label}</a></li> 44 + ))} 45 + </ul>) 46 + : <pre>{JSON.stringify(Works.tags)}</pre>} 46 47 </header> 47 48 48 49 <div class="card-body prose lg:prose-xl"> ··· 54 55 </Layout> 55 56 56 57 <style> 57 - @reference "../../assets/styles/global.css"; 58 - 59 58 .tag { 60 59 @apply btn btn-accent; 61 60 }
+85 -2
uno.config.ts
··· 1 - import { defineConfig, presetWind4, transformerDirectives } from "unocss"; 1 + import { defineConfig, presetTypography, presetWind4, transformerDirectives, type PresetWind4Theme } from "unocss"; 2 2 import { presetDaisy } from "@ameinhardt/unocss-preset-daisy"; 3 3 // @ts-expect-error 4 4 import theme from 'daisyui/functions/variables.js'; 5 5 6 - export default defineConfig({ 6 + export default defineConfig<PresetWind4Theme>({ 7 + outputToCssLayers: true, 8 + layers: { 9 + 'properties': -6, 10 + 'theme': -5, 11 + 'base': -4, 12 + 'daisy-base': -3, 13 + 'daisy-components': -2, 14 + 'shortcuts': -1, 15 + 'default': 0, 16 + 'typography': 1, 17 + }, 7 18 presets: [ 8 19 presetDaisy(), 9 20 presetWind4(), 21 + presetTypography({ 22 + colorScheme: { 23 + "body": ["color-mix(in oklab,var(--color-base-content)80%,#0000)", "color-mix(in oklab,var(--color-base-content)80%,#0000)"], 24 + "headings": ["var(--color-base-content)", "var(--color-base-content)"], 25 + "lead": ["var(--color-base-content)", "var(--color-base-content)"], 26 + "links": ["var(--color-content)", "var(--color-content)"], 27 + "bold": ["var(--color-base-content)", "var(--color-base-content)"], 28 + "counters": ["var(--color-base-content)", "var(--color-base-content)"], 29 + "bullets": ["color-mix(in oklab,var(--color-base-content)50%,#0000)", "color-mix(in oklab,var(--color-base-content)50%,#0000)"], 30 + "hr": ["color-mix(in oklab,var(--color-base-content)20%,#0000)", "color-mix(in oklab,var(--color-base-content)20%,#0000)"], 31 + "quotes": ["var(--color-base-content)", "var(--color-base-content)"], 32 + "quote-borders": ["color-mix(in oklab,var(--color-base-content)20%,#0000)", "color-mix(in oklab,var(--color-base-content)20%,#0000)"], 33 + "captions": ["color-mix(in oklab,var(--color-base-content)50%,#0000)", "color-mix(in oklab,var(--color-base-content)50%,#0000)"], 34 + "kbd": ["color-mix(in oklab,var(--color-base-content)80%,#0000)", "color-mix(in oklab,var(--color-base-content)80%,#0000)"], 35 + "kbd-shadows": ["oklab(21% -.00316127 -.0338527/.1)", "oklab(21% -.00316127 -.0338527/.1)"], 36 + "code": ["var(--color-base-content)", "var(--color-base-content)"], 37 + "pre-code": ["var(--color-neutral-content)", "var(--color-neutral-content)"], 38 + "pre-bg": ["var(--color-neutral)", "var(--color-neutral)"], 39 + "th-borders": ["color-mix(in oklab,var(--color-base-content)50%,#0000)", "color-mix(in oklab,var(--color-base-content)50%,#0000)"], 40 + "td-borders": ["color-mix(in oklab,var(--color-base-content)20%,#0000)", "color-mix(in oklab,var(--color-base-content)20%,#0000)"] 41 + }, 42 + }), 10 43 ], 44 + shortcuts: { 45 + "heading-1": "font-display text-5xl", 46 + "heading-2": "font-display text-4xl", 47 + "heading-3": "font-display text-3xl", 48 + "heading-4": "font-sans text-2xl", 49 + "heading-5": "font-sans text-xl", 50 + "heading-6": "font-sans text-lg", 51 + }, 11 52 transformers: [ 12 53 transformerDirectives(), 13 54 ], ··· 18 59 mono: "var(--intel-mono)", 19 60 display: "var(--jacquard-12)", 20 61 }, 62 + leading: 1.5, 63 + text: { 64 + xs: { 65 + fontSize: "var(--step--2)", 66 + }, 67 + sm: { 68 + fontSize: "var(--step--1)", 69 + }, 70 + base: { 71 + fontSize: "var(--step-0)", 72 + }, 73 + lg: { 74 + fontSize: "var(--step-1)", 75 + }, 76 + xl: { 77 + fontSize: "var(--step-2)", 78 + }, 79 + "2xl": { 80 + fontSize: "var(--step-3)", 81 + }, 82 + "3xl": { 83 + fontSize: "var(--step-4)", 84 + }, 85 + "4xl": { 86 + fontSize: "var(--step-5)", 87 + }, 88 + "5xl": { 89 + fontSize: "var(--step-6)", 90 + }, 91 + "6xl": { 92 + fontSize: "var(--step-7)", 93 + }, 94 + "7xl": { 95 + fontSize: "var(--step-8)", 96 + }, 97 + "8xl": { 98 + fontSize: "var(--step-9)", 99 + }, 100 + "9xl": { 101 + fontSize: "var(--step-10)", 102 + }, 103 + } 21 104 }, 22 105 });