A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

Add /write route and writing-first chrome styles

+163
+24
src/pages/_write.meta.test.ts
··· 1 + import { describe, it, expect } from 'vitest'; 2 + import { readFileSync } from 'node:fs'; 3 + import { dirname, join } from 'node:path'; 4 + import { fileURLToPath } from 'node:url'; 5 + 6 + // Read the page source off disk. We resolve via `fileURLToPath` + `join` rather 7 + // than handing a `URL` straight to `readFileSync` because, under this repo's 8 + // Astro/Vite-backed Vitest, the global `URL` resolves a relative specifier 9 + // against the test module to an `http://localhost` dev-server URL (not `file:`), 10 + // which `readFileSync` rejects. This mirrors the sibling `_*.meta.test.ts` pages. 11 + const here = dirname( fileURLToPath( import.meta.url ) ); 12 + const src = readFileSync( join( here, './write.astro' ), 'utf8' ); 13 + 14 + describe( '/write route', () => { 15 + it( 'mounts WriteStudio as a client:only island', () => { 16 + expect( src ).toContain( "import WriteStudio from '../components/WriteStudio.tsx'" ); 17 + expect( src ).toMatch( /<WriteStudio\s+client:only="react"/ ); 18 + } ); 19 + 20 + it( 'ships a writing-focused title and the write chrome styles', () => { 21 + expect( src ).toMatch( /<Base title="Write[^"]*"/ ); 22 + expect( src ).toContain( "import '../styles/write-chrome.css'" ); 23 + } ); 24 + } );
+21
src/pages/write.astro
··· 1 + --- 2 + import Base from '../layouts/Base.astro'; 3 + import WriteStudio from '../components/WriteStudio.tsx'; 4 + import LoadingScene from '../components/LoadingScene.astro'; 5 + // The island is `client:only`, so Astro's scoped styles never reach its DOM — its 6 + // chrome is styled globally from these shared stylesheets plus the write-specific one. 7 + import '../styles/app-bar.css'; 8 + import '../styles/editor-chrome.css'; 9 + import '../styles/login.css'; 10 + import '../styles/write-chrome.css'; 11 + --- 12 + 13 + <Base title="Write — SkyPress"> 14 + <main class="editor-shell"> 15 + <!-- client:only — auth + editor run only in the browser (Decisions 0001 & 0004). 16 + Unlike /editor this surface never gates on auth: you can write signed out. --> 17 + <WriteStudio client:only="react"> 18 + <LoadingScene slot="fallback" variant="editor" /> 19 + </WriteStudio> 20 + </main> 21 + </Base>
+118
src/styles/write-chrome.css
··· 1 + /* src/styles/write-chrome.css 2 + * Chrome unique to the writing-first page (/write): the top-right corner (sign-in / pill), 3 + * the sign-in panel, the publish stepper, and the in-header Publish button. The editor body 4 + * itself reuses editor-chrome.css (.studio__title / .studio__lede / .studio__cover*). 5 + */ 6 + 7 + .write-corner { 8 + display: flex; 9 + justify-content: flex-end; 10 + padding: 0.5rem 1rem; 11 + } 12 + 13 + .write-corner__signin, 14 + .write-publish { 15 + font: inherit; 16 + cursor: pointer; 17 + border-radius: 999px; 18 + border: 1px solid currentColor; 19 + padding: 0.35rem 0.9rem; 20 + background: transparent; 21 + } 22 + 23 + .write-publish[disabled] { 24 + opacity: 0.5; 25 + cursor: default; 26 + } 27 + 28 + .write-header { 29 + display: flex; 30 + align-items: flex-start; 31 + gap: 0.75rem; 32 + } 33 + 34 + .write-header .studio__title { 35 + flex: 1 1 auto; 36 + } 37 + 38 + .account-pill { 39 + position: relative; 40 + } 41 + 42 + .account-pill__trigger { 43 + display: inline-flex; 44 + align-items: center; 45 + gap: 0.5rem; 46 + background: transparent; 47 + border: 0; 48 + cursor: pointer; 49 + font: inherit; 50 + } 51 + 52 + .account-pill__avatar { 53 + border-radius: 999px; 54 + } 55 + 56 + .account-pill__avatar--fallback { 57 + display: inline-grid; 58 + place-items: center; 59 + width: 28px; 60 + height: 28px; 61 + border-radius: 999px; 62 + background: rgba( 0, 0, 0, 0.1 ); 63 + } 64 + 65 + .account-pill__menu { 66 + position: absolute; 67 + right: 0; 68 + margin-top: 0.4rem; 69 + min-width: 12rem; 70 + display: flex; 71 + flex-direction: column; 72 + background: Canvas; 73 + border: 1px solid rgba( 0, 0, 0, 0.15 ); 74 + border-radius: 0.5rem; 75 + box-shadow: 0 8px 24px rgba( 0, 0, 0, 0.12 ); 76 + overflow: hidden; 77 + } 78 + 79 + .account-pill__item { 80 + padding: 0.6rem 0.9rem; 81 + text-align: left; 82 + background: transparent; 83 + border: 0; 84 + font: inherit; 85 + cursor: pointer; 86 + color: inherit; 87 + text-decoration: none; 88 + } 89 + 90 + .account-pill__item:hover { 91 + background: rgba( 0, 0, 0, 0.06 ); 92 + } 93 + 94 + .write-signin, 95 + .writeflow { 96 + max-width: 32rem; 97 + margin: 1rem auto; 98 + padding: 1rem 1.25rem; 99 + border: 1px solid rgba( 0, 0, 0, 0.15 ); 100 + border-radius: 0.75rem; 101 + } 102 + 103 + .signin-panel__actions, 104 + .writeflow__actions { 105 + display: flex; 106 + gap: 0.75rem; 107 + margin-top: 0.75rem; 108 + } 109 + 110 + .writeflow__warning { 111 + font-size: 0.95rem; 112 + } 113 + 114 + .writeflow__count, 115 + .writeflow__error, 116 + .signin-panel__error { 117 + color: #b3261e; 118 + }