学习目标
- 分析GitHub仓库列表页的结构和组件组成
- 使用Tailwind CSS实现仓库卡片组件
- 构建过滤器和排序控件
- 实现分页导航功能
- 创建响应式布局,确保在所有设备上都有良好的用户体验
GitHub仓库列表页分析
GitHub的仓库列表页是用户查看、搜索和管理其所有代码仓库的中心。这个页面布局清晰,功能丰富,包含多种UI组件:
- 顶部导航栏(复用前面章节的组件)
- 子导航标签(区分”Repositories”、”Projects”等)
- 过滤和搜索控件
- 仓库卡片列表
- 分页控件
这个页面的设计专注于高效浏览和管理大量仓库,提供多种方式来过滤和排序内容。
页面骨架结构
首先,让我们创建页面的基本HTML结构:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Your Repositories - GitHub</title><script src="https://cdn.tailwindcss.com"></script><script>tailwind.config = {theme: {extend: {colors: {"github-blue": "#0969da","github-green": "#2da44e","github-red": "#cf222e","github-yellow": "#bf8700","github-purple": "#8250df","github-bg": "#f6f8fa","github-border": "#d0d7de","github-text-primary": "#24292f","github-text-secondary": "#57606a","github-header-bg": "#24292f","github-header-text": "#ffffff","github-btn-primary": "#2da44e","github-btn-primary-hover": "#2c974b",},fontFamily: {"github": ["-apple-system","BlinkMacSystemFont","Segoe UI","Noto Sans","Helvetica","Arial","sans-serif","Apple Color Emoji","Segoe UI Emoji"],},borderRadius: {"github-md": "6px",},boxShadow: {"github-sm": "0 1px 0 rgba(27, 31, 36, 0.04)","github-btn": "0 1px 0 rgba(27, 31, 36, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.25)",}}}}</script></head><body class="bg-white font-github text-github-text-primary"><!-- GitHub Header (复用) --><header class="bg-github-header-bg text-github-header-text py-3 px-4 flex items-center justify-between"><div class="flex items-center w-full"><!-- GitHub Logo --><svg height="32" aria-hidden="true" viewBox="0 0 16 16" version="1.1" width="32" class="fill-current"><path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path></svg><!-- Search bar --><div class="relative mx-4 hidden md:block w-64"><input type="text" placeholder="Search or jump to..."class="bg-github-header-bg border border-gray-600 rounded-md text-sm text-white placeholder-gray-400 w-full py-1 px-3"></div><!-- Navigation links --><nav class="hidden md:flex items-center space-x-4"><a href="#" class="text-white hover:text-gray-300">Pull requests</a><a href="#" class="text-white hover:text-gray-300">Issues</a><a href="#" class="text-white hover:text-gray-300">Marketplace</a><a href="#" class="text-white hover:text-gray-300">Explore</a></nav><!-- Mobile menu button --><button class="ml-auto md:hidden text-white"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /></svg></button><!-- User menu --><div class="hidden md:flex items-center ml-auto"><!-- Notifications icon --><a href="#" class="text-white mr-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M8 16a2 2 0 0 0 1.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 0 0 8 16ZM3 5a5 5 0 0 1 10 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.519 1.519 0 0 1 13.482 13H2.518a1.516 1.516 0 0 1-1.263-2.36l1.703-2.554A.255.255 0 0 0 3 7.947Zm5-3.5A3.5 3.5 0 0 0 4.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.017.017 0 0 0-.003.01l.001.006c0 .002.002.004.004.006l.006.004.007.001h10.964l.007-.001.006-.004.004-.006.001-.007a.017.017 0 0 0-.003-.01l-1.703-2.554a1.745 1.745 0 0 1-.294-.97V5A3.5 3.5 0 0 0 8 1.5Z"></path></svg></a><!-- User avatar dropdown --><div class="relative"><button class="flex items-center"><img src="https://avatars.githubusercontent.com/u/123456789?v=4" alt="User avatar" class="w-5 h-5 rounded-full"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="ml-1 text-white"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></button></div></div></div></header><!-- Main Content Area --><main class="container mx-auto px-4 py-6 max-w-7xl"><!-- Content will go here --></main></body></html>
实现用户信息栏和导航标签
接下来,让我们添加用户信息栏和导航标签,这是仓库列表页的顶部部分:
<!-- Main Content Area --><main class="container mx-auto px-4 py-6 max-w-7xl"><!-- User info bar (mobile only) --><div class="flex items-center mb-6 md:hidden"><img src="https://avatars.githubusercontent.com/u/123456789?v=4" alt="User avatar" class="w-8 h-8 rounded-full mr-2"><span class="font-bold">johndoe</span></div><!-- User tabs navigation --><div class="border-b border-github-border mb-6 overflow-x-auto"><nav class="flex flex-nowrap -mb-px"><a href="#" class="px-4 py-3 border-b-2 border-transparent hover:border-gray-300 text-github-text-secondary hover:text-github-text-primary whitespace-nowrap">Overview</a><a href="#" class="px-4 py-3 border-b-2 border-github-blue text-github-blue font-semibold whitespace-nowrap">Repositories <span class="ml-1 py-0.5 px-1.5 text-xs rounded-full bg-gray-200">28</span></a><a href="#" class="px-4 py-3 border-b-2 border-transparent hover:border-gray-300 text-github-text-secondary hover:text-github-text-primary whitespace-nowrap">Projects <span class="ml-1 py-0.5 px-1.5 text-xs rounded-full bg-gray-200">4</span></a><a href="#" class="px-4 py-3 border-b-2 border-transparent hover:border-gray-300 text-github-text-secondary hover:text-github-text-primary whitespace-nowrap">Packages</a><a href="#" class="px-4 py-3 border-b-2 border-transparent hover:border-gray-300 text-github-text-secondary hover:text-github-text-primary whitespace-nowrap">Stars <span class="ml-1 py-0.5 px-1.5 text-xs rounded-full bg-gray-200">324</span></a></nav></div></main>
添加过滤和搜索控件
GitHub的仓库列表页面具有强大的过滤和搜索功能。让我们实现这些控件:
<!-- After user tabs navigation --><!-- Filter and search controls --><div class="mb-4 flex flex-col sm:flex-row gap-3"><!-- Search repositories --><div class="relative flex-grow order-2 sm:order-1"><input type="text" placeholder="Find a repository..."class="block w-full px-3 py-1.5 text-sm border border-github-border rounded-github-md focus:outline-none focus:border-github-blue focus:ring-1 focus:ring-github-blue"></div><!-- Filter buttons --><div class="flex flex-wrap gap-2 order-1 sm:order-2"><!-- Type dropdown --><div class="relative"><button class="flex items-center px-3 py-1.5 text-sm font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100">Type<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="ml-1"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></button></div><!-- Language dropdown --><div class="relative"><button class="flex items-center px-3 py-1.5 text-sm font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100">Language<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="ml-1"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></button></div><!-- Sort dropdown --><div class="relative"><button class="flex items-center px-3 py-1.5 text-sm font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100">Sort<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="ml-1"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></button></div><!-- New repository button --><a href="#" class="flex items-center px-3 py-1.5 text-sm font-medium rounded-github-md bg-github-btn-primary text-white hover:bg-github-btn-primary-hover border border-github-border border-opacity-20"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-3.5a.25.25 0 0 1-.25-.25Z"></path></svg>New</a></div></div>
实现仓库卡片列表
现在,让我们实现仓库卡片列表,这是页面的核心部分:
<!-- After filter and search controls --><!-- Repository list --><div class="border-t border-github-border divide-y divide-github-border"><!-- Repository item 1 --><div class="py-6"><div class="flex justify-between items-start"><div><div class="flex items-baseline"><h3 class="text-xl font-semibold mr-2"><a href="#" class="text-github-blue hover:underline">awesome-project</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span></div><p class="text-sm text-github-text-secondary mt-1 mb-3">A collection of awesome resources for developers</p><div class="flex flex-wrap items-center text-xs text-github-text-secondary gap-x-4 gap-y-2"><span class="flex items-center"><span class="w-3 h-3 rounded-full bg-yellow-500 mr-1"></span>JavaScript</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>128</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 0-6 0Zm1.5 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm6.75.75a.75.75 0 0 0 0-1.5h-3a.75.75 0 0 0 0 1.5h3ZM4.5 15a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 13.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 12a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 10.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75Z"></path></svg>42</span><span>Updated 2 days ago</span></div></div><div><button class="flex items-center px-3 py-1 text-xs font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>Star</button></div></div></div><!-- Repository item 2 --><div class="py-6"><div class="flex justify-between items-start"><div><div class="flex items-baseline"><h3 class="text-xl font-semibold mr-2"><a href="#" class="text-github-blue hover:underline">react-components</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span></div><p class="text-sm text-github-text-secondary mt-1 mb-3">Collection of reusable React components with TypeScript support</p><div class="flex flex-wrap items-center text-xs text-github-text-secondary gap-x-4 gap-y-2"><span class="flex items-center"><span class="w-3 h-3 rounded-full bg-blue-500 mr-1"></span>TypeScript</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>95</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 0-6 0Zm1.5 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm6.75.75a.75.75 0 0 0 0-1.5h-3a.75.75 0 0 0 0 1.5h3ZM4.5 15a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 13.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 12a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 10.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75Z"></path></svg>37</span><span>Updated last week</span></div></div><div><button class="flex items-center px-3 py-1 text-xs font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>Star</button></div></div></div><!-- Repository item 3 (with pinned indicator) --><div class="py-6"><div class="flex justify-between items-start"><div><div class="flex items-baseline"><h3 class="text-xl font-semibold mr-2"><a href="#" class="text-github-blue hover:underline">tailwind-github-clone</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span><span class="ml-2 inline-flex items-center text-github-text-secondary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M7.775 3.275a.75.75 0 0 0 1.06 1.06l1.25-1.25a2 2 0 1 1 2.83 2.83l-2.5 2.5a2 2 0 0 1-2.83 0 .75.75 0 0 0-1.06 1.06 3.5 3.5 0 0 0 4.95 0l2.5-2.5a3.5 3.5 0 0 0-4.95-4.95l-1.25 1.25Zm-4.69 9.64a2 2 0 0 1 0-2.83l2.5-2.5a2 2 0 0 1 2.83 0 .75.75 0 0 0 1.06-1.06 3.5 3.5 0 0 0-4.95 0l-2.5 2.5a3.5 3.5 0 0 0 4.95 4.95l1.25-1.25a.75.75 0 0 0-1.06-1.06l-1.25 1.25a2 2 0 0 1-2.83 0Z"></path></svg>Pinned</span></div><p class="text-sm text-github-text-secondary mt-1 mb-3">A GitHub UI clone built with Tailwind CSS</p><div class="flex flex-wrap items-center text-xs text-github-text-secondary gap-x-4 gap-y-2"><span class="flex items-center"><span class="w-3 h-3 rounded-full bg-blue-300 mr-1"></span>CSS</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>54</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 0-6 0Zm1.5 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm6.75.75a.75.75 0 0 0 0-1.5h-3a.75.75 0 0 0 0 1.5h3ZM4.5 15a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 13.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 12a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 10.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75Z"></path></svg>15</span><span>Updated 15 days ago</span></div></div><div><button class="flex items-center px-3 py-1 text-xs font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>Star</button></div></div></div><!-- Repository item 4 (with "Private" and "Archived" indicators) --><div class="py-6"><div class="flex justify-between items-start"><div><div class="flex items-baseline flex-wrap gap-2"><h3 class="text-xl font-semibold"><a href="#" class="text-github-blue hover:underline">legacy-project</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border bg-yellow-50">Private</span><span class="text-xs px-2 py-0.5 rounded-full text-github-text-secondary bg-gray-100">Archived</span></div><p class="text-sm text-github-text-secondary mt-1 mb-3">Legacy project from 2020, archived for reference</p><div class="flex flex-wrap items-center text-xs text-github-text-secondary gap-x-4 gap-y-2"><span class="flex items-center"><span class="w-3 h-3 rounded-full bg-purple-500 mr-1"></span>PHP</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>8</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 0-6 0Zm1.5 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm6.75.75a.75.75 0 0 0 0-1.5h-3a.75.75 0 0 0 0 1.5h3ZM4.5 15a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 13.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 12a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 10.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75Z"></path></svg>2</span><span>Archived on Dec 5, 2023</span></div></div><div><button class="flex items-center px-3 py-1 text-xs font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>Star</button></div></div></div><!-- More repository items (5) --><div class="py-6"><div class="flex justify-between items-start"><div><div class="flex items-baseline"><h3 class="text-xl font-semibold mr-2"><a href="#" class="text-github-blue hover:underline">node-api-starter</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span></div><p class="text-sm text-github-text-secondary mt-1 mb-3">A starter template for Node.js APIs with Express and MongoDB</p><div class="flex flex-wrap items-center text-xs text-github-text-secondary gap-x-4 gap-y-2"><span class="flex items-center"><span class="w-3 h-3 rounded-full bg-green-700 mr-1"></span>JavaScript</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>72</span><span class="flex items-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 0-6 0Zm1.5 0a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm6.75.75a.75.75 0 0 0 0-1.5h-3a.75.75 0 0 0 0 1.5h3ZM4.5 15a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 13.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 12a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75ZM4.5 10.5a.75.75 0 0 0 .75-.75v-.5a.75.75 0 0 0-1.5 0v.5c0 .414.336.75.75.75Z"></path></svg>24</span><span>Updated 1 month ago</span></div></div><div><button class="flex items-center px-3 py-1 text-xs font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" class="mr-1"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path></svg>Star</button></div></div></div></div>
添加分页导航组件
最后,我们需要添加分页导航组件来浏览更多的仓库:
<!-- After repository list --><!-- Pagination --><div class="mt-6 flex justify-center"><nav class="inline-flex items-center"><a href="#" class="px-3 py-1 rounded-l-md border border-github-border bg-white text-github-text-primary hover:bg-github-bg disabled:opacity-50 disabled:pointer-events-none" disabled>Previous</a><a href="#" class="px-3 py-1 border-t border-b border-github-border bg-github-blue text-white font-medium">1</a><a href="#" class="px-3 py-1 border-t border-b border-github-border bg-white text-github-text-primary hover:bg-github-bg">2</a><a href="#" class="px-3 py-1 border-t border-b border-github-border bg-white text-github-text-primary hover:bg-github-bg">3</a><span class="px-3 py-1 border-t border-b border-github-border bg-white text-github-text-secondary">...</span><a href="#" class="px-3 py-1 border-t border-b border-github-border bg-white text-github-text-primary hover:bg-github-bg">8</a><a href="#" class="px-3 py-1 rounded-r-md border border-github-border bg-white text-github-text-primary hover:bg-github-bg">Next</a></nav></div>
响应式设计考虑
GitHub的仓库列表页在移动设备上有一些特殊的考虑。我们已经在示例中实现了一些关键的响应式特性:
移动优先的过滤器布局:
- 在小屏幕上,过滤器控件堆叠显示,搜索框在下方
- 在较大屏幕上,它们变为水平排列,搜索框在左侧
导航变换:
- 在移动设备上,主导航栏简化为汉堡菜单
- 用户信息显示在页面顶部
关键样式技术点
1. 仓库卡片模式
GitHub的仓库卡片设计是该页面的核心元素。每个卡片包含仓库名称、描述、统计信息和操作按钮,采用清晰的层次结构:
<div class="py-6"><div class="flex justify-between items-start"><!-- 左侧:仓库信息 --><div><!-- 标题行 --><div class="flex items-baseline"><h3 class="text-xl font-semibold mr-2"><a href="#" class="text-github-blue hover:underline">repository-name</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span></div><!-- 描述 --><p class="text-sm text-github-text-secondary mt-1 mb-3">Repository description goes here</p><!-- 元数据行 --><div class="flex flex-wrap items-center text-xs text-github-text-secondary gap-x-4 gap-y-2"><!-- 各种统计信息... --></div></div><!-- 右侧:动作按钮 --><div><button class="flex items-center px-3 py-1 text-xs font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100"><!-- 按钮内容 --></button></div></div></div>
这种结构使用了Flexbox来创建左右两侧的布局,同时在较小屏幕上仍然能够保持良好的阅读体验。
2. 分隔线和边界
GitHub使用细微的边框和分隔线来区分内容区域,我们使用以下Tailwind类实现:
<div class="border-t border-github-border divide-y divide-github-border"><!-- 仓库项目 --></div>
这种方法为每个仓库项目添加了上边框,并在列表的顶部添加了一个边框,创建了清晰的视觉分隔。
3. 标签和指示器
GitHub使用各种标签和状态指示器来显示仓库状态(公开/私有、已归档、已固定等):
<!-- 公开仓库标签 --><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span><!-- 私有仓库标签 --><span class="text-xs px-2 py-0.5 rounded-full border border-github-border bg-yellow-50">Private</span><!-- 已归档标签 --><span class="text-xs px-2 py-0.5 rounded-full text-github-text-secondary bg-gray-100">Archived</span><!-- 固定指示器 --><span class="ml-2 inline-flex items-center text-github-text-secondary"><svg><!-- ... --></svg>Pinned</span>
这种一致的设计语言帮助用户快速识别仓库的状态和特性。
4. 语言颜色点
GitHub为不同的编程语言使用彩色圆点,这是一个独特的视觉元素:
<span class="flex items-center"><span class="w-3 h-3 rounded-full bg-blue-500 mr-1"></span>TypeScript</span>
我们使用不同的背景色来模拟GitHub的语言颜色系统。
5. 过滤器和排序控件
过滤器和排序控件使用一致的按钮样式,具有轻微的背景色和边框:
<button class="flex items-center px-3 py-1.5 text-sm font-medium border border-github-border rounded-github-md bg-github-bg hover:bg-gray-100">Type<svg><!-- 下拉箭头图标 --></svg></button>
这些按钮在悬停时有轻微的背景色变化,提供了良好的交互反馈。
常见问题与解决方案
问题1:移动设备上过滤控件的排列
解决方案:使用Flexbox的order属性和flex-col/flex-row条件类来根据屏幕尺寸改变元素顺序:
<div class="mb-4 flex flex-col sm:flex-row gap-3"><!-- 搜索框 - 在移动设备上在下方,在桌面上在左侧 --><div class="relative flex-grow order-2 sm:order-1"><!-- 搜索框内容 --></div><!-- 过滤器按钮 - 在移动设备上在上方,在桌面上在右侧 --><div class="flex flex-wrap gap-2 order-1 sm:order-2"><!-- 过滤器按钮内容 --></div></div>
问题2:卡片内容在小屏幕上的溢出
解决方案:使用Flexbox换行和适当的间距来确保内容在小屏幕上能够正确换行:
<div class="flex flex-wrap items-baseline gap-2"><h3 class="text-xl font-semibold"><a href="#" class="text-github-blue hover:underline">repository-name</a></h3><span class="text-xs px-2 py-0.5 rounded-full border border-github-border">Public</span><span class="text-xs px-2 py-0.5 rounded-full text-github-text-secondary bg-gray-100">Archived</span></div>
flex-wrap 和 gap-2 类确保元素在需要时会换行,并保持适当的间距。
问题3:分页控件在小屏幕上的显示
解决方案:使居中布局和横向滚动来确保分页控件在小屏幕上可访问:
<div class="mt-6 flex justify-center overflow-x-auto"><nav class="inline-flex items-center"><!-- 分页控件内容 --></nav></div>
overflow-x-auto 类允许用户在必要时水平滚动以查看所有分页控件。
扩展与练习建议
实现下拉过滤器:为”Type”、”Language”和”Sort”按钮创建下拉菜单,显示相应的过滤选项。
添加批量选择功能:实现GitHub的批量操作功能,允许用户选择多个仓库并执行批量操作(如归档、转移等)。
创建空状态页面:设计一个”无仓库”的空状态页面,当用户没有仓库或过滤条件没有匹配结果时显示。
添加筛选结果标签:实现GitHub的筛选标签功能,显示当前应用的过滤器,并允许用户点击移除它们。
集成暗模式:为仓库列表页添加暗模式支持,确保所有元素在暗背景上有适当的对比度。
总结
在本节中,我们成功实现了GitHub的仓库列表页面,包括仓库卡片、过滤控件和分页导航。这个页面展示了如何使用Tailwind CSS创建复杂的列表布局,包含多种状态指示器和交互元素。
关键技术点包括:
- 使用Flexbox创建灵活的卡片布局
- 采用分隔线和边框创建清晰的视觉层次
- 实现多种类型的状态标签和指示器
- 创建响应式过滤器和搜索控件
- 设计分页导航组件
GitHub的仓库列表页面是一个信息密集型界面,通过精心的设计和布局,使用户能够轻松浏览和管理大量仓库。通过复刻这个页面,我们学习了如何在保持视觉清晰度的同时呈现丰富的信息和功能。
在下一节中,我们将探索GitHub的搜索结果页面,学习如何实现更复杂的过滤器和搜索结果显示。
