diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-03-05 17:24:59 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-05 09:24:59 -0800 |
commit | 2d854091b9684ab253a2c117509bf95609a975a1 (patch) | |
tree | 965f049c7d8e13e61bd1ce05737113340fb3d991 /bskyembed/src/screens | |
parent | 01a51c327505bc84f5755be82f15a855234a2750 (diff) | |
download | voidsky-2d854091b9684ab253a2c117509bf95609a975a1.tar.zst |
enhance(embed): add ability to pin color mode (#7186)
* enhance(embed): add ability to pin color mode * fix: Move color mode dropdown to the root section * auto -> system * style tweaks * default to light theme * try and fix eslint * fix dropdown styles on other browsers * rm unnecessary eslintrc change * more explicit color mode select * make light explicit --------- Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
Diffstat (limited to 'bskyembed/src/screens')
-rw-r--r-- | bskyembed/src/screens/landing.tsx | 77 | ||||
-rw-r--r-- | bskyembed/src/screens/post.tsx | 20 |
2 files changed, 76 insertions, 21 deletions
diff --git a/bskyembed/src/screens/landing.tsx b/bskyembed/src/screens/landing.tsx index a3448e90a..880b71337 100644 --- a/bskyembed/src/screens/landing.tsx +++ b/bskyembed/src/screens/landing.tsx @@ -1,12 +1,16 @@ import '../index.css' -import {AppBskyFeedDefs, AppBskyFeedPost, AtUri, BskyAgent} from '@atproto/api' +import {AppBskyFeedDefs, AppBskyFeedPost, AtpAgent, AtUri} from '@atproto/api' import {h, render} from 'preact' import {useEffect, useMemo, useRef, useState} from 'preact/hooks' import arrowBottom from '../../assets/arrowBottom_stroke2_corner0_rounded.svg' import logo from '../../assets/logo.svg' -import {initColorMode} from '../color-mode' +import { + assertColorModeValues, + ColorModeValues, + initSystemColorMode, +} from '../color-mode' import {Container} from '../components/container' import {Link} from '../components/link' import {Post} from '../components/post' @@ -22,9 +26,9 @@ export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js` const root = document.getElementById('app') if (!root) throw new Error('No root element') -initColorMode() +initSystemColorMode() -const agent = new BskyAgent({ +const agent = new AtpAgent({ service: 'https://public.api.bsky.app', }) @@ -32,6 +36,7 @@ render(<LandingPage />, root) function LandingPage() { const [uri, setUri] = useState('') + const [colorMode, setColorMode] = useState<ColorModeValues>('system') const [error, setError] = useState<string | null>(null) const [loading, setLoading] = useState(false) const [thread, setThread] = useState<AppBskyFeedDefs.ThreadViewPost | null>( @@ -120,24 +125,50 @@ function LandingPage() { <h1 className="text-4xl font-bold text-center">Embed a Bluesky Post</h1> - <input - type="text" - value={uri} - onInput={e => setUri(e.currentTarget.value)} - className="border rounded-lg py-3 w-full max-w-[600px] px-4 dark:bg-dimmedBg dark:border-slate-500" - placeholder={DEFAULT_POST} - /> + <div className="flex flex-col w-full max-w-[600px] gap-6"> + <input + type="text" + value={uri} + onInput={e => setUri(e.currentTarget.value)} + className="border rounded-lg py-3 px-4 dark:bg-dimmedBg dark:border-slate-500" + placeholder={DEFAULT_POST} + /> + + <div className="flex flex-col gap-1.5"> + <label className="text-sm font-medium" for="colorModeSelect"> + Theme + </label> + <select + value={colorMode} + onChange={e => { + const value = e.currentTarget.value + if (assertColorModeValues(value)) { + setColorMode(value) + } + }} + id="colorModeSelect" + className="appearance-none bg-white border w-full rounded-lg text-sm px-3 py-2 dark:bg-dimmedBg dark:border-slate-500"> + <option value="system">System</option> + <option value="light">Light</option> + <option value="dark">Dark</option> + </select> + </div> + </div> <img src={arrowBottom} className="w-6 dark:invert" /> {loading ? ( - <div className="w-full max-w-[600px]"> + <div className={`${colorMode} w-full max-w-[600px]`}> <Skeleton /> </div> ) : ( <div className="w-full max-w-[600px] gap-8 flex flex-col"> - {!error && thread && uri && <Snippet thread={thread} />} - {!error && thread && <Post thread={thread} key={thread.post.uri} />} + {!error && thread && uri && ( + <Snippet thread={thread} colorMode={colorMode} /> + )} + <div className={colorMode}> + {!error && thread && <Post thread={thread} key={thread.post.uri} />} + </div> {error && ( <div className="w-full border border-red-500 bg-red-500/10 px-4 py-3 rounded-lg"> <p className="text-red-500 text-center">{error}</p> @@ -168,7 +199,13 @@ function Skeleton() { ) } -function Snippet({thread}: {thread: AppBskyFeedDefs.ThreadViewPost}) { +function Snippet({ + thread, + colorMode, +}: { + thread: AppBskyFeedDefs.ThreadViewPost + colorMode: ColorModeValues +}) { const ref = useRef<HTMLInputElement>(null) const [copied, setCopied] = useState(false) @@ -204,9 +241,11 @@ function Snippet({thread}: {thread: AppBskyFeedDefs.ThreadViewPost}) { // x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x return `<blockquote class="bluesky-embed" data-bluesky-uri="${escapeHtml( thread.post.uri, - )}" data-bluesky-cid="${escapeHtml(thread.post.cid)}"><p lang="${escapeHtml( - lang, - )}">${escapeHtml(record.text)}${ + )}" data-bluesky-cid="${escapeHtml( + thread.post.cid, + )}" data-bluesky-embed-color-mode="${escapeHtml( + colorMode, + )}"><p lang="${escapeHtml(lang)}">${escapeHtml(record.text)}${ record.embed ? `<br><br><a href="${escapeHtml(href)}">[image or embed]</a>` : '' @@ -217,7 +256,7 @@ function Snippet({thread}: {thread: AppBskyFeedDefs.ThreadViewPost}) { )}</a>) <a href="${escapeHtml(href)}">${escapeHtml( niceDate(thread.post.indexedAt), )}</a></blockquote><script async src="${EMBED_SCRIPT}" charset="utf-8"></script>` - }, [thread]) + }, [thread, colorMode]) return ( <div className="flex gap-2 w-full"> diff --git a/bskyembed/src/screens/post.tsx b/bskyembed/src/screens/post.tsx index 1764442b7..4cd72b69b 100644 --- a/bskyembed/src/screens/post.tsx +++ b/bskyembed/src/screens/post.tsx @@ -4,7 +4,7 @@ import {AppBskyFeedDefs, AtpAgent} from '@atproto/api' import {h, render} from 'preact' import logo from '../../assets/logo.svg' -import {initColorMode} from '../color-mode' +import {applyTheme, initSystemColorMode} from '../color-mode' import {Container} from '../components/container' import {Link} from '../components/link' import {Post} from '../components/post' @@ -22,7 +22,23 @@ if (!uri) { throw new Error('No uri in path') } -initColorMode() +const query = new URLSearchParams(window.location.search) + +// theme - default to light mode +const colorMode = query.get('colorMode') + +switch (colorMode) { + case 'dark': + applyTheme('dark') + break + case 'system': + initSystemColorMode() + break + case 'light': + default: + applyTheme('light') + break +} agent .getPostThread({ |