a tool for shared writing and social publishing

added a posts button to scope publications in the @ mention dropdown

+114 -28
+114 -28
components/Mention.tsx
··· 133 133 134 134 if (!mentionCoords || suggestions.length === 0) return null; 135 135 136 - const headerStyle = "text-xs text-tertiary font-bold pt-1 px-2"; 136 + 137 + const getHeader = (type: Mention["type"]) => { 138 + switch (type) { 139 + case "did": 140 + return "People"; 141 + case "publication": 142 + return "Publications"; 143 + } 144 + }; 137 145 138 146 const sortedSuggestions = [...suggestions].sort((a, b) => { 139 147 const order: Mention["type"][] = ["did", "publication"]; ··· 180 188 return ( 181 189 <> 182 190 {showHeader && ( 183 - <Fragment key={`header-publications`}> 184 - <hr className="border-border-light mx-1 my-1" /> 185 - <div className={headerStyle}>Publications</div> 186 - </Fragment> 191 + <> 192 + {index > 0 && ( 193 + <hr className="border-border-light mx-1 my-1" /> 194 + )} 195 + <div className="text-xs text-tertiary font-bold pt-1 px-2"> 196 + {getHeader(result.type)} 197 + </div> 198 + </> 199 + )} 200 + {result.type === "did" ? ( 201 + <DidResult 202 + key={result.did} 203 + onClick={() => { 204 + if (mentionRange) { 205 + props.onSelect(result, mentionRange); 206 + setMentionQuery(null); 207 + setMentionRange(null); 208 + setMentionCoords(null); 209 + } 210 + }} 211 + onMouseDown={(e) => e.preventDefault()} 212 + displayName={result.displayName} 213 + handle={result.handle} 214 + selected={index === suggestionIndex} 215 + /> 216 + ) : ( 217 + <PublicationResult 218 + key={result.uri} 219 + onClick={() => { 220 + if (mentionRange) { 221 + props.onSelect(result, mentionRange); 222 + setMentionQuery(null); 223 + setMentionRange(null); 224 + setMentionCoords(null); 225 + } 226 + }} 227 + onMouseDown={(e) => e.preventDefault()} 228 + pubName={result.name} 229 + selected={index === suggestionIndex} 230 + /> 187 231 )} 188 - <Result 189 - key={key} 190 - onClick={() => { 191 - if (mentionRange) { 192 - props.onSelect(result, mentionRange); 193 - setMentionQuery(null); 194 - setMentionRange(null); 195 - setMentionCoords(null); 196 - } 197 - }} 198 - onMouseDown={(e) => e.preventDefault()} 199 - result={resultText} 200 - subtext={subtext} 201 - selected={index === suggestionIndex} 202 - /> 203 232 </> 204 233 ); 205 234 })} ··· 218 247 selected?: boolean; 219 248 }) => { 220 249 return ( 221 - <div 250 + <button 222 251 className={` 223 - menuItem flex-col! gap-0! 224 - text-secondary leading-tight text-sm truncate 252 + menuItem w-full flex-col! gap-0! 253 + text-secondary leading-snug text-sm 225 254 ${props.subtext ? "py-1!" : "py-2!"} 226 - ${props.selected ? "bg-[var(--accent-light)]!" : ""}`} 227 - onClick={() => props.onClick()} 255 + ${props.selected ? "bg-[var(--accent-light)]" : ""}`} 256 + onClick={() => { 257 + props.onClick(); 258 + }} 228 259 onMouseDown={(e) => props.onMouseDown(e)} 229 260 > 230 - <div className={`flex gap-2 items-center `}> 231 - <div className="truncate w-full grow min-w-0 ">{props.result}</div> 261 + <div 262 + className={`flex gap-2 items-center w-full truncate justify-between`} 263 + > 264 + {props.result} 232 265 </div> 233 266 {props.subtext && ( 234 267 <div className="text-tertiary italic text-xs font-normal min-w-0 truncate pb-[1px]"> 235 268 {props.subtext} 236 269 </div> 237 270 )} 238 - </div> 271 + </button> 272 + ); 273 + }; 274 + 275 + const ScopeButton = (props: { 276 + onClick: () => void; 277 + children: React.ReactNode; 278 + }) => { 279 + return ( 280 + <button 281 + className="flex flex-row shrink-0 text-xs font-normal text-tertiary hover:text-accent-contrast" 282 + onClick={(e) => { 283 + e.preventDefault(); 284 + e.stopPropagation(); 285 + props.onClick(); 286 + }} 287 + > 288 + {props.children} <ArrowRightTiny className="scale-80" /> 289 + </button> 290 + ); 291 + }; 292 + 293 + const DidResult = (props: { 294 + displayName?: string; 295 + handle: string; 296 + onClick: () => void; 297 + onMouseDown: (e: React.MouseEvent) => void; 298 + selected?: boolean; 299 + }) => { 300 + return ( 301 + <Result 302 + result={props.displayName ? props.displayName : props.handle} 303 + subtext={props.displayName && `@${props.handle}`} 304 + {...props} 305 + /> 306 + ); 307 + }; 308 + 309 + const PublicationResult = (props: { 310 + pubName: string; 311 + onClick: () => void; 312 + onMouseDown: (e: React.MouseEvent) => void; 313 + selected?: boolean; 314 + }) => { 315 + return ( 316 + <Result 317 + result={ 318 + <> 319 + <div className="truncate w-full grow min-w-0">{props.pubName}</div> 320 + <ScopeButton onClick={() => {}}>Posts</ScopeButton> 321 + </> 322 + } 323 + {...props} 324 + /> 239 325 ); 240 326 }; 241 327