mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-04-02 16:44:56 +02:00
fix: reorder GitHub widget tabs and add Repos tab
Tab order: Commits (default), Repos, Featured, PRs. Repos tab fetches full repo list from GitHub public API. Featured tab shows curated projects from /githubapi. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{# GitHub Activity Widget - Tabbed Projects/Commits/PRs with live API data #}
|
||||
<div class="widget" x-data="githubWidget()" x-init="init()">
|
||||
{# GitHub Activity Widget - Tabbed Commits/Repos/Featured/PRs with live API data #}
|
||||
<div class="widget" x-data="githubWidget('{{ site.feeds.github }}')" x-init="init()">
|
||||
<h3 class="widget-title flex items-center gap-2">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path>
|
||||
@@ -7,16 +7,8 @@
|
||||
GitHub
|
||||
</h3>
|
||||
|
||||
{# Tab buttons #}
|
||||
{# Tab buttons — order: Commits, Repos, Featured, PRs #}
|
||||
<div class="flex gap-1 mb-4 border-b border-surface-200 dark:border-surface-700">
|
||||
<button
|
||||
@click="activeTab = 'projects'"
|
||||
:class="activeTab === 'projects' ? 'border-b-2 border-primary-500 text-primary-600 dark:text-primary-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
class="flex items-center gap-1.5 px-3 py-2 text-sm font-medium transition-colors -mb-px"
|
||||
>
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"/></svg>
|
||||
Projects
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'commits'"
|
||||
:class="activeTab === 'commits' ? 'border-b-2 border-primary-500 text-primary-600 dark:text-primary-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
@@ -25,6 +17,22 @@
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/></svg>
|
||||
Commits
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'repos'"
|
||||
:class="activeTab === 'repos' ? 'border-b-2 border-primary-500 text-primary-600 dark:text-primary-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
class="flex items-center gap-1.5 px-3 py-2 text-sm font-medium transition-colors -mb-px"
|
||||
>
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4"/></svg>
|
||||
Repos
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'featured'"
|
||||
:class="activeTab === 'featured' ? 'border-b-2 border-primary-500 text-primary-600 dark:text-primary-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
class="flex items-center gap-1.5 px-3 py-2 text-sm font-medium transition-colors -mb-px"
|
||||
>
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/></svg>
|
||||
Featured
|
||||
</button>
|
||||
<button
|
||||
@click="activeTab = 'prs'"
|
||||
:class="activeTab === 'prs' ? 'border-b-2 border-primary-500 text-primary-600 dark:text-primary-400' : 'text-surface-500 hover:text-surface-700 dark:hover:text-surface-300'"
|
||||
@@ -40,10 +48,54 @@
|
||||
Loading...
|
||||
</div>
|
||||
|
||||
{# Projects Tab #}
|
||||
<div x-show="activeTab === 'projects' && !loading" x-cloak>
|
||||
<ul x-show="projects.length > 0" class="space-y-3">
|
||||
<template x-for="repo in projects.slice(0, 5)" :key="repo.fullName || repo.name">
|
||||
{# Commits Tab #}
|
||||
<div x-show="activeTab === 'commits' && !loading" x-cloak>
|
||||
<ul x-show="commits.length > 0" class="space-y-3">
|
||||
<template x-for="commit in commits.slice(0, 6)" :key="commit.sha">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
<a :href="commit.url" target="_blank" rel="noopener" class="block group">
|
||||
<p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors line-clamp-2" x-text="commit.message"></p>
|
||||
<div class="flex items-center gap-2 mt-1.5 text-xs text-surface-500">
|
||||
<code class="text-xs font-mono bg-surface-100 dark:bg-surface-800 px-1 py-0.5 rounded" x-text="commit.sha"></code>
|
||||
<span class="truncate" x-text="commit.repo?.split('/')[1] || commit.repo"></span>
|
||||
<span x-text="formatDate(commit.date)"></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="commits.length === 0" class="text-sm text-surface-500 py-2">No recent commits.</div>
|
||||
</div>
|
||||
|
||||
{# Repos Tab #}
|
||||
<div x-show="activeTab === 'repos' && !loading" x-cloak>
|
||||
<ul x-show="repos.length > 0" class="space-y-3">
|
||||
<template x-for="repo in repos.slice(0, 8)" :key="repo.name">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
<a :href="repo.html_url" target="_blank" rel="noopener" class="block group">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium text-sm text-primary-600 dark:text-primary-400 group-hover:underline truncate" x-text="repo.name"></span>
|
||||
<span x-show="repo.language" class="text-xs px-1.5 py-0.5 rounded bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-400 flex-shrink-0" x-text="repo.language"></span>
|
||||
</div>
|
||||
<p x-show="repo.description" class="text-xs text-surface-600 dark:text-surface-400 mt-1 line-clamp-2" x-text="repo.description"></p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-surface-500">
|
||||
<span x-show="repo.stargazers_count > 0" class="flex items-center gap-1">
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
|
||||
<span x-text="repo.stargazers_count"></span>
|
||||
</span>
|
||||
<span x-text="formatDate(repo.updated_at)"></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="repos.length === 0" class="text-sm text-surface-500 py-2">No repositories found.</div>
|
||||
</div>
|
||||
|
||||
{# Featured Tab #}
|
||||
<div x-show="activeTab === 'featured' && !loading" x-cloak>
|
||||
<ul x-show="featured.length > 0" class="space-y-3">
|
||||
<template x-for="repo in featured.slice(0, 5)" :key="repo.fullName || repo.name">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
<a :href="repo.url" target="_blank" rel="noopener" class="block group">
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -65,26 +117,7 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="projects.length === 0" class="text-sm text-surface-500 py-2">No projects found.</div>
|
||||
</div>
|
||||
|
||||
{# Commits Tab #}
|
||||
<div x-show="activeTab === 'commits' && !loading" x-cloak>
|
||||
<ul x-show="commits.length > 0" class="space-y-3">
|
||||
<template x-for="commit in commits.slice(0, 6)" :key="commit.sha">
|
||||
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
|
||||
<a :href="commit.url" target="_blank" rel="noopener" class="block group">
|
||||
<p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors line-clamp-2" x-text="commit.message"></p>
|
||||
<div class="flex items-center gap-2 mt-1.5 text-xs text-surface-500">
|
||||
<code class="text-xs font-mono bg-surface-100 dark:bg-surface-800 px-1 py-0.5 rounded" x-text="commit.sha"></code>
|
||||
<span class="truncate" x-text="commit.repo?.split('/')[1] || commit.repo"></span>
|
||||
<span x-text="formatDate(commit.date)"></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div x-show="commits.length === 0" class="text-sm text-surface-500 py-2">No recent commits.</div>
|
||||
<div x-show="featured.length === 0" class="text-sm text-surface-500 py-2">No featured projects.</div>
|
||||
</div>
|
||||
|
||||
{# PRs Tab #}
|
||||
@@ -125,24 +158,34 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function githubWidget() {
|
||||
function githubWidget(username) {
|
||||
return {
|
||||
activeTab: 'projects',
|
||||
activeTab: 'commits',
|
||||
loading: true,
|
||||
projects: [],
|
||||
commits: [],
|
||||
repos: [],
|
||||
featured: [],
|
||||
contributions: [],
|
||||
|
||||
async init() {
|
||||
try {
|
||||
const [featured, commitsRes, contribRes] = await Promise.all([
|
||||
fetch('/githubapi/api/featured').then(r => r.ok ? r.json() : null).catch(() => null),
|
||||
const fetches = [
|
||||
fetch('/githubapi/api/commits').then(r => r.ok ? r.json() : null).catch(() => null),
|
||||
fetch('/githubapi/api/featured').then(r => r.ok ? r.json() : null).catch(() => null),
|
||||
fetch('/githubapi/api/contributions').then(r => r.ok ? r.json() : null).catch(() => null),
|
||||
]);
|
||||
this.projects = featured?.featured || [];
|
||||
];
|
||||
if (username) {
|
||||
fetches.push(
|
||||
fetch(`https://api.github.com/users/${username}/repos?sort=updated&per_page=10&type=owner`, {
|
||||
headers: { 'Accept': 'application/vnd.github.v3+json' }
|
||||
}).then(r => r.ok ? r.json() : null).catch(() => null)
|
||||
);
|
||||
}
|
||||
const [commitsRes, featuredRes, contribRes, reposRes] = await Promise.all(fetches);
|
||||
this.commits = commitsRes?.commits || [];
|
||||
this.featured = featuredRes?.featured || [];
|
||||
this.contributions = contribRes?.contributions || [];
|
||||
this.repos = (reposRes || []).filter(r => !r.fork && !r.private);
|
||||
} catch (err) {
|
||||
console.error('GitHub widget error:', err);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user