a proof of concept realtime collaborative text editor using atproto as a sync server jake.tngl.io/y-pds/
1
fork

Configure Feed

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

Yet more style improvements

+80 -37
+21 -4
app.js
··· 237 237 238 238 render() { 239 239 return html` 240 - <dialog ref=${this.dialogRef}> 241 - <h2>Share</h2> 240 + <dialog ref=${this.dialogRef} closedby="any"> 241 + <header> 242 + <h2>Share</h2> 243 + <form method="dialog"> 244 + <button class="icon-button" aria-label="Close"> 245 + <svg 246 + width="16" 247 + height="16" 248 + viewBox="0 0 16 16" 249 + fill="none" 250 + stroke="currentColor" 251 + stroke-width="2" 252 + stroke-linecap="round" 253 + > 254 + <line x1="4" y1="4" x2="12" y2="12" /> 255 + <line x1="12" y1="4" x2="4" y2="12" /> 256 + </svg> 257 + </button> 258 + </form> 259 + </header> 242 260 <ul id="editors"> 243 261 ${this.editors.value.map( 244 262 ({ did, label }) => html` ··· 251 269 </ul> 252 270 <form id="add-member" onSubmit=${e => this.addMember(e)}> 253 271 <actor-typeahead> 254 - <input name="did" placeholder="Search for a user…" autocomplete="off" /> 272 + <input name="did" placeholder="example.bsky.social" autocomplete="off" /> 255 273 </actor-typeahead> 256 274 <button type="submit">Add</button> 257 275 </form> 258 - <button onClick=${() => this.dialogRef.current.close()}>Close</button> 259 276 </dialog> 260 277 `; 261 278 }
+59 -33
style.css
··· 8 8 input, 9 9 select, 10 10 textarea { 11 + flex: 1; 11 12 width: 100%; 12 13 padding: 0.4rem 0.5rem; 13 14 border: 1px solid #ccc; ··· 20 21 outline-offset: 1px; 21 22 outline: 2px solid rgba(from blue r g b / 0.5); 22 23 } 24 + } 25 + 26 + actor-typeahead { 27 + flex: 1; 23 28 } 24 29 25 30 button { ··· 143 148 .ProseMirror-menubar-wrapper { 144 149 height: 100%; 145 150 } 151 + 146 152 #share { 147 153 position: fixed; 148 154 top: 0.6rem; 149 155 right: 0.75rem; 150 156 z-index: 10; 151 157 } 158 + 152 159 dialog { 160 + overflow: visible; 161 + place-self: center; 153 162 min-width: 320px; 154 - padding: 1.5rem; 155 - border: 1px solid #ddd; 163 + border: none; 156 164 border-radius: 10px; 157 165 box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); 158 166 ··· 160 168 background: rgba(0, 0, 0, 0.25); 161 169 } 162 170 171 + header { 172 + display: flex; 173 + justify-content: space-between; 174 + align-items: center; 175 + border-bottom: 1px solid #dddddd; 176 + } 177 + 163 178 h2 { 164 - margin-bottom: 1rem; 165 179 font-size: 1rem; 166 180 } 167 - } 168 - #members { 169 - list-style: none; 170 - margin-bottom: 1rem; 181 + 182 + > * { 183 + padding: 12px; 184 + } 171 185 } 172 - #members li { 186 + 187 + .icon-button { 188 + all: unset; 189 + cursor: pointer; 173 190 display: flex; 174 191 align-items: center; 175 - gap: 0.5rem; 176 - padding: 0.25rem 0; 192 + justify-content: center; 193 + padding: 0.25rem; 194 + border-radius: 4px; 195 + color: #888; 196 + 197 + &:hover { 198 + color: #333; 199 + background: #f0f0f0; 200 + } 177 201 } 178 - #members li span { 179 - flex: 1; 180 - font-size: 0.875rem; 181 - font-family: monospace; 182 - overflow: hidden; 183 - text-overflow: ellipsis; 202 + 203 + #editors { 204 + list-style: none; 205 + 206 + &:empty { 207 + display: none; 208 + } 209 + 210 + > li { 211 + display: flex; 212 + align-items: center; 213 + gap: 0.5rem; 214 + padding: 0.25rem 0; 215 + 216 + > span { 217 + flex: 1; 218 + font-size: 0.875rem; 219 + font-family: monospace; 220 + overflow: hidden; 221 + text-overflow: ellipsis; 222 + } 223 + } 184 224 } 225 + 185 226 #add-member { 186 227 display: flex; 187 228 gap: 0.5rem; 188 - margin-bottom: 1rem; 189 229 } 190 - #add-member input { 191 - flex: 1; 192 - font: inherit; 193 - font-size: 0.875rem; 194 - padding: 0.25rem 0.5rem; 195 - border: 1px solid #ccc; 196 - border-radius: 4px; 197 - } 198 - #share-dialog button { 199 - font: inherit; 200 - font-size: 0.875rem; 201 - padding: 0.25rem 0.75rem; 202 - border: 1px solid #ccc; 203 - border-radius: 4px; 204 - cursor: pointer; 205 - } 230 + 206 231 .collab-cursor { 207 232 position: relative; 208 233 border-left: 2px solid var(--color); 209 234 margin-left: -1px; 210 235 pointer-events: none; 211 236 } 237 + 212 238 .collab-cursor::after { 213 239 content: attr(data-name); 214 240 position: absolute;