atmosphere explorer
0
fork

Configure Feed

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

expand/collapse collection groups

resolves #49

Juliet 647785eb 7d6c1e79

+83 -22
+83 -22
src/views/repo.tsx
··· 195 195 196 196 const [repo] = createResource(fetchRepo); 197 197 198 + const toggleCollapsed = (authority: string) => { 199 + setNsids((prev) => ({ 200 + ...prev!, 201 + [authority]: { ...prev![authority], hidden: !prev![authority].hidden }, 202 + })); 203 + }; 204 + 205 + const collapseAll = () => { 206 + setNsids((prev) => 207 + Object.fromEntries(Object.entries(prev!).map(([k, v]) => [k, { ...v, hidden: true }])), 208 + ); 209 + }; 210 + 211 + const expandAll = () => { 212 + setNsids((prev) => 213 + Object.fromEntries(Object.entries(prev!).map(([k, v]) => [k, { ...v, hidden: false }])), 214 + ); 215 + }; 216 + 198 217 const validateHandles = async () => { 199 218 for (const alias of didDoc()?.alsoKnownAs ?? []) { 200 219 if (alias.startsWith("at://")) ··· 429 448 </ErrorBoundary> 430 449 </Show> 431 450 <Show when={nsids() && (!location.hash || location.hash.startsWith("#collections"))}> 432 - <div class={`flex flex-col ${canHover ? "pb-16" : "pb-12"} text-sm wrap-anywhere`}> 451 + <div class="flex flex-col pb-20 text-sm wrap-anywhere"> 433 452 <Show 434 453 when={Object.keys(nsids() ?? {}).length != 0} 435 454 fallback={<span class="mt-3 text-center text-base">No collections found.</span>} ··· 446 465 > 447 466 {(authority) => { 448 467 const isHighlighted = () => location.hash === `#collections:${authority}`; 468 + const isCollapsed = () => nsids()?.[authority].hidden ?? false; 449 469 450 470 return ( 451 471 <div 452 472 id={`collection-${authority}`} 453 - class="group flex scroll-mt-4 items-start gap-2 rounded-lg p-1 transition-colors" 473 + class="group relative flex scroll-mt-4 items-start gap-2 rounded-lg p-1 transition-colors" 454 474 classList={{ 455 475 "dark:hover:bg-dark-300 hover:bg-neutral-200": !isHighlighted(), 456 476 "bg-blue-100 dark:bg-blue-500/25": isHighlighted(), ··· 470 490 </a> 471 491 )} 472 492 /> 473 - <div class="flex flex-1 flex-col"> 474 - <For 475 - each={nsids()?.[authority].nsids.filter((nsid) => 476 - filter() ? `${authority}.${nsid}`.includes(filter()!) : true, 477 - )} 493 + <Show 494 + when={!isCollapsed()} 495 + fallback={ 496 + <button 497 + class="flex flex-1 items-center text-left" 498 + onClick={() => toggleCollapsed(authority)} 499 + > 500 + <span class="text-neutral-700 dark:text-neutral-300"> 501 + {authority}. 502 + </span> 503 + <span class="text-neutral-500 dark:text-neutral-400">*</span> 504 + <span class="ml-1.5 text-neutral-400 dark:text-neutral-500"> 505 + ({nsids()?.[authority].nsids.length}) 506 + </span> 507 + </button> 508 + } 509 + > 510 + <div class="flex min-w-0 flex-1 flex-col"> 511 + <For 512 + each={nsids()?.[authority].nsids.filter((nsid) => 513 + filter() ? `${authority}.${nsid}`.includes(filter()!) : true, 514 + )} 515 + > 516 + {(nsid, index) => ( 517 + <A 518 + href={`/at://${did}/${authority}.${nsid}`} 519 + class="truncate hover:underline active:underline" 520 + classList={{ "pr-16": canHover && index() === 0 }} 521 + > 522 + <span class="text-neutral-800/70 dark:text-neutral-200/70"> 523 + {authority}. 524 + </span> 525 + <span>{nsid}</span> 526 + </A> 527 + )} 528 + </For> 529 + </div> 530 + </Show> 531 + <Show when={canHover}> 532 + <button 533 + class="absolute top-1 right-1 rounded px-2 py-0.5 text-xs text-neutral-500 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-neutral-300 hover:text-neutral-700 active:bg-neutral-400 dark:text-neutral-400 dark:hover:bg-neutral-600 dark:hover:text-neutral-200 dark:active:bg-neutral-500" 534 + onClick={() => toggleCollapsed(authority)} 478 535 > 479 - {(nsid) => ( 480 - <A 481 - href={`/at://${did}/${authority}.${nsid}`} 482 - class="hover:underline active:underline" 483 - > 484 - <span class="text-neutral-800/70 dark:text-neutral-200/70"> 485 - {authority}. 486 - </span> 487 - <span>{nsid}</span> 488 - </A> 489 - )} 490 - </For> 491 - </div> 536 + {isCollapsed() ? "expand" : "collapse"} 537 + </button> 538 + </Show> 492 539 </div> 493 540 ); 494 541 }} ··· 749 796 </Show> 750 797 751 798 <Show when={nsids() && (!location.hash || location.hash.startsWith("#collections"))}> 752 - <div class={`fixed ${canHover ? "bottom-12" : "bottom-8"} z-10 w-full max-w-lg`}> 799 + <div class="dark:bg-dark-500 fixed bottom-0 z-10 flex w-full flex-col items-center gap-2 border-t border-neutral-200 bg-neutral-100 px-3 pt-3 pb-6 dark:border-neutral-700"> 753 800 <div 754 - class="dark:bg-dark-200 dark:shadow-dark-700 mx-3 flex cursor-text items-center gap-2 rounded-lg border border-neutral-200 bg-white px-3 shadow-sm dark:border-neutral-700" 801 + class="dark:bg-dark-200 flex w-full max-w-lg cursor-text items-center gap-2 rounded-lg border border-neutral-200 bg-white px-3 dark:border-neutral-700" 755 802 onClick={(e) => { 756 803 const input = e.currentTarget.querySelector("input"); 757 804 if (e.target !== input) input?.focus(); ··· 775 822 / 776 823 </kbd> 777 824 </Show> 825 + </div> 826 + <div class="flex w-full max-w-lg justify-end gap-1"> 827 + <button 828 + class="rounded px-2 py-1 text-xs text-neutral-500 hover:bg-neutral-200 hover:text-neutral-700 active:bg-neutral-300 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:hover:text-neutral-200 dark:active:bg-neutral-600" 829 + onClick={expandAll} 830 + > 831 + Expand all 832 + </button> 833 + <button 834 + class="rounded px-2 py-1 text-xs text-neutral-500 hover:bg-neutral-200 hover:text-neutral-700 active:bg-neutral-300 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:hover:text-neutral-200 dark:active:bg-neutral-600" 835 + onClick={collapseAll} 836 + > 837 + Collapse all 838 + </button> 778 839 </div> 779 840 </div> 780 841 </Show>