a tool for shared writing and social publishing

some changes to how the results array is organized

+66 -40
+66 -40
components/Mention.tsx
··· 132 132 ]); 133 133 134 134 if (!mentionCoords || suggestions.length === 0) return null; 135 - let headerStyle = "text-xs text-tertiary font-bold italic pt-1 px-2"; 135 + 136 + const headerStyle = "text-xs text-tertiary font-bold pt-1 px-2"; 137 + 138 + const getHeader = (type: Mention["type"]) => { 139 + switch (type) { 140 + case "did": 141 + return "People"; 142 + case "publication": 143 + return "Publications"; 144 + } 145 + }; 146 + 147 + const getKey = (mention: Mention) => { 148 + switch (mention.type) { 149 + case "did": 150 + return mention.did; 151 + case "publication": 152 + return mention.uri; 153 + } 154 + }; 155 + 156 + const getResultText = (mention: Mention) => { 157 + switch (mention.type) { 158 + case "did": 159 + return mention.displayName || `@${mention.handle}`; 160 + case "publication": 161 + return mention.name; 162 + } 163 + }; 164 + 165 + const getSubtext = (mention: Mention) => { 166 + switch (mention.type) { 167 + case "did": 168 + return mention.displayName ? `@${mention.handle}` : undefined; 169 + case "publication": 170 + return undefined; 171 + } 172 + }; 173 + 174 + const sortedSuggestions = [...suggestions].sort((a, b) => { 175 + const order: Mention["type"][] = ["did", "publication"]; 176 + return order.indexOf(a.type) - order.indexOf(b.type); 177 + }); 136 178 137 179 return ( 138 180 <Popover.Root open> ··· 158 200 overflow-y-scroll`} 159 201 > 160 202 <ul className="list-none p-0 text-sm"> 161 - <div className={headerStyle}>People</div> 162 - {suggestions 163 - .filter((result) => result.type === "did") 164 - .map((result, index) => { 165 - return ( 166 - <Result 167 - key={result.did} 168 - onClick={() => { 169 - if (mentionRange) { 170 - props.onSelect(result, mentionRange); 171 - setMentionQuery(null); 172 - setMentionRange(null); 173 - setMentionCoords(null); 174 - } 175 - }} 176 - onMouseDown={(e) => e.preventDefault()} 177 - result={ 178 - result.displayName 179 - ? result.displayName 180 - : `@${result.handle}` 181 - } 182 - subtext={ 183 - result.displayName ? `@${result.handle}` : undefined 184 - } 185 - selected={index === suggestionIndex} 186 - /> 187 - ); 188 - })} 189 - <hr className="border-border-light mx-1 my-1" /> 190 - <div className={headerStyle}>Publications</div> 191 - {suggestions 192 - .filter((result) => result.type === "publication") 193 - .map((result, index) => { 194 - return ( 203 + {sortedSuggestions.map((result, index) => { 204 + const prevResult = sortedSuggestions[index - 1]; 205 + const showHeader = !prevResult || prevResult.type !== result.type; 206 + 207 + return ( 208 + <> 209 + {showHeader && ( 210 + <> 211 + {index > 0 && ( 212 + <hr className="border-border-light mx-1 my-1" /> 213 + )} 214 + <div className={headerStyle}> 215 + {getHeader(result.type)} 216 + </div> 217 + </> 218 + )} 195 219 <Result 196 - key={result.uri} 220 + key={getKey(result)} 197 221 onClick={() => { 198 222 if (mentionRange) { 199 223 props.onSelect(result, mentionRange); ··· 203 227 } 204 228 }} 205 229 onMouseDown={(e) => e.preventDefault()} 206 - result={result.name} 230 + result={getResultText(result)} 231 + subtext={getSubtext(result)} 207 232 selected={index === suggestionIndex} 208 233 /> 209 - ); 210 - })} 234 + </> 235 + ); 236 + })} 211 237 </ul> 212 238 </Popover.Content> 213 239 </Popover.Portal> ··· 236 262 <div className="truncate w-full grow min-w-0 ">{props.result}</div> 237 263 </div> 238 264 {props.subtext && ( 239 - <div className="text-tertiary italic text-xs font-normal min-w-0 truncate pb-0.5"> 265 + <div className="text-tertiary italic text-xs font-normal min-w-0 truncate pb-[1px]"> 240 266 {props.subtext} 241 267 </div> 242 268 )}