A project tracker for decentralized social media platforms, clients, and tools

feat: improve mobile UI experience

- Fix spacing between logo and network selector on mobile
- Hide "Social Meshes" text on small screens to save space
- Make warning icon clickable on mobile with tap-to-show popup
- Add backdrop to dismiss warning popup on mobile tap
- Maintain hover behavior on desktop unchanged

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

+33 -11
+29 -7
src/components/ProjectCard.tsx
··· 1 + import { useState } from 'react'; 1 2 import type { Project } from '../types/project'; 2 3 3 4 interface ProjectCardProps { ··· 5 6 } 6 7 7 8 export default function ProjectCard({ project }: ProjectCardProps) { 9 + const [showWarning, setShowWarning] = useState(false); 8 10 const getLinkIcon = (kind: string, url?: string) => { 9 11 // Special case: Show Bluesky icon for social links on bsky.app 10 12 if (kind === 'social' && url?.includes('bsky.app')) { ··· 119 121 </a> 120 122 {project.type === 'semi-platform' && ( 121 123 <div className="relative group"> 122 - <svg 123 - className="w-5 h-5 text-yellow-500" 124 - fill="currentColor" 125 - viewBox="0 0 20 20" 124 + <button 125 + onClick={(e) => { 126 + e.stopPropagation(); 127 + setShowWarning(!showWarning); 128 + }} 129 + className="p-1 -m-1 rounded hover:bg-gray-700 transition-colors sm:pointer-events-none" 130 + aria-label="Warning information" 126 131 > 127 - <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" /> 128 - </svg> 129 - <div className="absolute right-0 top-6 w-48 p-2 bg-gray-900 text-gray-200 text-xs rounded-lg opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-10 border border-gray-700"> 132 + <svg 133 + className="w-5 h-5 text-yellow-500" 134 + fill="currentColor" 135 + viewBox="0 0 20 20" 136 + > 137 + <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" /> 138 + </svg> 139 + </button> 140 + {showWarning && ( 141 + <> 142 + <div 143 + className="fixed inset-0 z-20 sm:hidden" 144 + onClick={() => setShowWarning(false)} 145 + /> 146 + <div className="absolute right-0 top-8 w-48 p-2 bg-gray-900 text-gray-200 text-xs rounded-lg z-30 border border-gray-700 sm:hidden"> 147 + Has not implemented platform-based AT Protocol lexicon 148 + </div> 149 + </> 150 + )} 151 + <div className="hidden sm:block absolute right-0 top-6 w-48 p-2 bg-gray-900 text-gray-200 text-xs rounded-lg opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-10 border border-gray-700"> 130 152 Has not implemented platform-based AT Protocol lexicon 131 153 </div> 132 154 </div>
+4 -4
src/components/TopBar.tsx
··· 15 15 <div className="fixed top-0 left-0 right-0 bg-gray-800 border-b border-gray-700 z-50"> 16 16 <div className="container mx-auto px-4"> 17 17 <div className="flex items-center justify-between h-16"> 18 - <div className="flex items-center space-x-6"> 18 + <div className="flex items-center gap-3 sm:gap-6"> 19 19 <div className="flex items-center space-x-2"> 20 - <svg className="w-8 h-8 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"> 20 + <svg className="w-8 h-8 text-blue-500 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"> 21 21 <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /> 22 22 </svg> 23 - <h1 className="text-xl font-bold text-white">Social Meshes</h1> 23 + <h1 className="text-lg sm:text-xl font-bold text-white hidden sm:block">Social Meshes</h1> 24 24 </div> 25 - 25 + 26 26 <div className="flex bg-gray-700 rounded-lg p-1"> 27 27 {networks.map(network => ( 28 28 <button