the statusphere demo reworked into a vite/react app in a monorepo

Merge pull request #4 from bluesky-social/paul/improvements

Some improvements to the UI

authored by

Paul Frazee and committed by
GitHub
1668c812 5a0ccb65

+42 -5
+11 -3
src/pages/home.ts
··· 3 3 import { html } from '../view' 4 4 import { shell } from './shell' 5 5 6 + const TODAY = new Date().toDateString() 7 + 6 8 const STATUS_OPTIONS = [ 7 9 '👍', 8 10 '👎', ··· 37 39 statuses: Status[] 38 40 didHandleMap: Record<string, string> 39 41 profile?: { displayName?: string; handle: string } 42 + myStatus?: Status 40 43 } 41 44 42 45 export function home(props: Props) { ··· 46 49 }) 47 50 } 48 51 49 - function content({ statuses, didHandleMap, profile }: Props) { 52 + function content({ statuses, didHandleMap, profile, myStatus }: Props) { 50 53 return html`<div id="root"> 51 54 <div class="error"></div> 52 55 <div id="header"> ··· 76 79 ${STATUS_OPTIONS.map( 77 80 (status) => 78 81 html`<div 79 - class="status-option" 82 + class=${myStatus?.status === status 83 + ? 'status-option selected' 84 + : 'status-option'} 80 85 data-value="${status}" 81 86 data-authed=${profile ? '1' : '0'} 82 87 > ··· 86 91 </div> 87 92 ${statuses.map((status, i) => { 88 93 const handle = didHandleMap[status.authorDid] || status.authorDid 94 + const date = ts(status) 89 95 return html` 90 96 <div class=${i === 0 ? 'status-line no-line' : 'status-line'}> 91 97 <div> ··· 93 99 </div> 94 100 <div class="desc"> 95 101 <a class="author" href=${toBskyLink(handle)}>@${handle}</a> 96 - is feeling ${status.status} on ${ts(status)} 102 + ${date === TODAY 103 + ? `is feeling ${status.status} today` 104 + : `was feeling ${status.status} on ${date}`} 97 105 </div> 98 106 </div> 99 107 `
+4
src/pages/login.ts
··· 27 27 <button type="submit">Log in</button> 28 28 ${error ? html`<p>Error: <i>${error}</i></p>` : undefined} 29 29 </form> 30 + <div class="signup-cta"> 31 + Don't have an account on the Atmosphere? 32 + <a href="https://bsky.app">Sign up for Bluesky</a> to create one now! 33 + </div> 30 34 </div> 31 35 </div>` 32 36 }
+19 -1
src/public/styles.css
··· 5 5 --gray-100: #fafafa; 6 6 --gray-500: #666; 7 7 --gray-700: #333; 8 + --primary-100: #d2e7ff; 9 + --primary-200: #b1d3fa; 8 10 --primary-400: #2e8fff; 9 11 --primary-500: #0078ff; 10 12 --primary-600: #0066db; ··· 146 148 } 147 149 148 150 .status-option:hover { 149 - background-color: var(--gray-100); 151 + background-color: var(--primary-100); 152 + box-shadow: 0 0 0 1px var(--primary-400); 153 + } 154 + 155 + .status-option.selected { 156 + box-shadow: 0 0 0 1px var(--primary-500); 157 + background-color: var(--primary-100); 158 + } 159 + 160 + .status-option.selected:hover { 161 + background-color: var(--primary-200); 150 162 } 151 163 152 164 .status-line { ··· 190 202 191 203 .status-line .author:hover { 192 204 text-decoration: underline; 205 + } 206 + 207 + .signup-cta { 208 + text-align: center; 209 + text-wrap: balance; 210 + margin-top: 1rem; 193 211 }
+8 -1
src/routes/index.ts
··· 95 95 .orderBy('indexedAt', 'desc') 96 96 .limit(10) 97 97 .execute() 98 + const myStatus = agent 99 + ? await ctx.db 100 + .selectFrom('status') 101 + .selectAll() 102 + .where('authorDid', '=', agent.accountDid) 103 + .executeTakeFirst() 104 + : undefined 98 105 const didHandleMap = await ctx.resolver.resolveDidsToHandles( 99 106 statuses.map((s) => s.authorDid) 100 107 ) ··· 104 111 const { data: profile } = await agent.getProfile({ actor: session.did }) 105 112 return res 106 113 .type('html') 107 - .send(page(home({ statuses, didHandleMap, profile }))) 114 + .send(page(home({ statuses, didHandleMap, profile, myStatus }))) 108 115 }) 109 116 ) 110 117