an appview-less Bluesky client using Constellation and PDS Queries reddwarf.app
frontend spa bluesky reddwarf microcosm

tablet support for nav bar

rimar1337 a798ba8c 0f2b0196

Changed files
+119 -9
src
routes
+119 -9
src/routes/__root.tsx
··· 415 </div> 416 </nav> 417 418 {agent?.did && ( 419 <button 420 className="lg:hidden fixed bottom-22 right-4 z-50 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 rounded-2xl w-14 h-14 flex items-center justify-center transition-all" ··· 431 </button> 432 )} 433 434 - <main className="w-full max-w-[600px] lg:border-x border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 pb-16 lg:pb-0 overflow-x-clip"> 435 {children} 436 </main> 437 ··· 448 </div> 449 450 {agent?.did ? ( 451 - <nav className="lg:hidden fixed bottom-0 left-0 right-0 bg-gray-50 dark:bg-gray-900 border-0 shadow border-gray-200 dark:border-gray-700 z-40"> 452 <div className="flex justify-around items-center p-2"> 453 <MaterialNavItem 454 small ··· 651 text: string; 652 active: boolean; 653 onClickCallbback: () => void; 654 - small?: boolean; 655 }) { 656 if (small) 657 return ( 658 <button 659 - className={`flex flex-col items-center rounded-lg transition-colors flex-1 gap-1 ${ 660 active 661 ? "text-gray-900 dark:text-gray-100" 662 : "text-gray-600 dark:text-gray-400" ··· 714 text: string; 715 //active: boolean; 716 onClickCallbback: () => void; 717 - small?: boolean; 718 }) { 719 const active = false; 720 return ( 721 <button 722 - className={`flex border border-gray-400 dark:border-gray-400 flex-row h-12 min-h-12 max-h-12 px-4 py-0.5 items-center rounded-full transition-colors gap-1 ${ 723 active 724 ? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-700 bg-gray-200 hover:dark:bg-gray-600" 725 : "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-800" ··· 728 onClickCallbback(); 729 }} 730 > 731 - <div className={`mr-2 ${active ? " " : " "}`}> 732 {active ? ActiveIcon : InactiveIcon} 733 </div> 734 - <span 735 className={`text-[17px] text-roboto ${active ? "font-medium" : ""}`} 736 > 737 {text} 738 - </span> 739 </button> 740 ); 741 }
··· 415 </div> 416 </nav> 417 418 + <nav className="hidden sm:flex items-center lg:hidden h-screen flex-col gap-0 p-4 dark:border-gray-800 sticky top-0 self-start"> 419 + <div className="flex items-center gap-3 mb-4"> 420 + <img src="/redstar.png" alt="Red Dwarf Logo" className="w-8 h-8" /> 421 + </div> 422 + <MaterialNavItem 423 + small 424 + InactiveIcon={ 425 + <IconMaterialSymbolsHomeOutline className="w-6 h-6" /> 426 + } 427 + ActiveIcon={<IconMaterialSymbolsHome className="w-6 h-6" />} 428 + active={isHome} 429 + onClickCallbback={() => 430 + navigate({ 431 + to: "/", 432 + //params: { did: agent.assertDid }, 433 + }) 434 + } 435 + text="Home" 436 + /> 437 + 438 + <MaterialNavItem 439 + small 440 + InactiveIcon={ 441 + <IconMaterialSymbolsNotificationsOutline className="w-6 h-6" /> 442 + } 443 + ActiveIcon={ 444 + <IconMaterialSymbolsNotifications className="w-6 h-6" /> 445 + } 446 + active={isNotifications} 447 + onClickCallbback={() => 448 + navigate({ 449 + to: "/notifications", 450 + //params: { did: agent.assertDid }, 451 + }) 452 + } 453 + text="Notifications" 454 + /> 455 + <MaterialNavItem 456 + small 457 + InactiveIcon={<IconMaterialSymbolsTag className="w-6 h-6" />} 458 + ActiveIcon={<IconMaterialSymbolsTag className="w-6 h-6" />} 459 + active={location.pathname.startsWith("/feeds")} 460 + onClickCallbback={() => 461 + navigate({ 462 + to: "/feeds", 463 + //params: { did: agent.assertDid }, 464 + }) 465 + } 466 + text="Feeds" 467 + /> 468 + <MaterialNavItem 469 + small 470 + InactiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />} 471 + ActiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />} 472 + active={location.pathname.startsWith("/search")} 473 + onClickCallbback={() => 474 + navigate({ 475 + to: "/search", 476 + //params: { did: agent.assertDid }, 477 + }) 478 + } 479 + text="Search" 480 + /> 481 + <MaterialNavItem 482 + small 483 + InactiveIcon={ 484 + <IconMaterialSymbolsAccountCircleOutline className="w-6 h-6" /> 485 + } 486 + ActiveIcon={ 487 + <IconMaterialSymbolsAccountCircle className="w-6 h-6" /> 488 + } 489 + active={isProfile ?? false} 490 + onClickCallbback={() => { 491 + if (authed && agent && agent.assertDid) { 492 + //window.location.href = `/profile/${agent.assertDid}`; 493 + navigate({ 494 + to: "/profile/$did", 495 + params: { did: agent.assertDid }, 496 + }); 497 + } 498 + }} 499 + text="Profile" 500 + /> 501 + <MaterialNavItem 502 + small 503 + InactiveIcon={ 504 + <IconMaterialSymbolsSettingsOutline className="w-6 h-6" /> 505 + } 506 + ActiveIcon={<IconMaterialSymbolsSettings className="w-6 h-6" />} 507 + active={location.pathname.startsWith("/settings")} 508 + onClickCallbback={() => 509 + navigate({ 510 + to: "/settings", 511 + //params: { did: agent.assertDid }, 512 + }) 513 + } 514 + text="Settings" 515 + /> 516 + <div className="flex flex-row items-center justify-center mt-3"> 517 + <MaterialPillButton 518 + small 519 + InactiveIcon={<IconMdiPencilOutline className="w-6 h-6" />} 520 + ActiveIcon={<IconMdiPencilOutline className="w-6 h-6" />} 521 + //active={true} 522 + onClickCallbback={() => setPostOpen(true)} 523 + text="Post" 524 + /> 525 + </div> 526 + </nav> 527 + 528 {agent?.did && ( 529 <button 530 className="lg:hidden fixed bottom-22 right-4 z-50 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 rounded-2xl w-14 h-14 flex items-center justify-center transition-all" ··· 541 </button> 542 )} 543 544 + <main className="w-full max-w-[600px] sm:border-x border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 pb-16 lg:pb-0 overflow-x-clip"> 545 {children} 546 </main> 547 ··· 558 </div> 559 560 {agent?.did ? ( 561 + <nav className="sm:hidden fixed bottom-0 left-0 right-0 bg-gray-50 dark:bg-gray-900 border-0 shadow border-gray-200 dark:border-gray-700 z-40"> 562 <div className="flex justify-around items-center p-2"> 563 <MaterialNavItem 564 small ··· 761 text: string; 762 active: boolean; 763 onClickCallbback: () => void; 764 + small?: boolean | string; 765 }) { 766 if (small) 767 return ( 768 <button 769 + className={`flex flex-col items-center rounded-lg transition-colors ${small} gap-1 ${ 770 active 771 ? "text-gray-900 dark:text-gray-100" 772 : "text-gray-600 dark:text-gray-400" ··· 824 text: string; 825 //active: boolean; 826 onClickCallbback: () => void; 827 + small?: boolean | string; 828 }) { 829 const active = false; 830 return ( 831 <button 832 + className={`flex border border-gray-400 dark:border-gray-400 flex-row h-12 min-h-12 max-h-12 ${small ? "p-3 w-12" : "px-4 py-0.5"} items-center rounded-full transition-colors gap-1 ${ 833 active 834 ? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-700 bg-gray-200 hover:dark:bg-gray-600" 835 : "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-800" ··· 838 onClickCallbback(); 839 }} 840 > 841 + <div className={`${!small && "mr-2"} ${active ? " " : " "}`}> 842 {active ? ActiveIcon : InactiveIcon} 843 </div> 844 + {!small && (<span 845 className={`text-[17px] text-roboto ${active ? "font-medium" : ""}`} 846 > 847 {text} 848 + </span>)} 849 </button> 850 ); 851 }