Migrate website to Starlight with full-text resource search (#883)

* Add search functionality to Learning Hub index page

Add a client-side search bar that filters articles by title, description,
and tags. Sections with no matching results are hidden automatically.
Uses the existing .search-bar CSS pattern from the cookbook page.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove deprecated layouts, theme script, and learning-hub config

Phase 5 cleanup of Starlight migration:
- Delete BaseLayout.astro (replaced by StarlightPage)
- Delete ArticleLayout.astro (replaced by Starlight docs rendering)
- Delete theme.ts (Starlight has built-in theme toggle)
- Delete src/config/learning-hub.ts (sidebar order now in astro.config.mjs)
- Replace learning-hub glob collection with Starlight docs collection in content.config.ts
- Keep search.ts (still used by homepage and all resource page scripts)

Build verified: 23 pages, no errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate website to Starlight with full-text resource search

- Replace bespoke Astro layouts with Starlight integration
  - Homepage and resource pages use StarlightPage wrapper
  - Learning Hub articles rendered via Starlight docs collection
  - Starlight provides search, theme toggle, sidebar, ToC, a11y

- Add custom Pagefind integration for resource search
  - All 614 agents/skills/instructions/hooks/workflows/plugins
    indexed as custom records with deep-link URLs
  - Type filter pills (horizontal pill toggles) above results
  - Search results link directly to resource modals via #file= hash

- Move global.css to src/styles/ for Vite processing
  - Scope CSS reset to #main-content to avoid Starlight conflicts
  - Full-width page gradient via body:has(#main-content)
  - Light/dark theme support with Starlight gray scale inversion

- Delete old layouts (BaseLayout, ArticleLayout), theme.ts, config

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback

- Fix pagefind-resources.ts header comment (pagefind:true not false)
- Remove unused base variable in cookbook/index.astro
- Replace hardcoded /awesome-copilot/ paths with relative links in index.md
- Delete stale public/styles/global.css (source of truth is src/styles/)
- Replace fragile getBasePath() with Astro config base in pagefind integration
- Document pagefind:true reasoning in astro.config.mjs
- Use proper visually-hidden pattern + :focus-visible ring for filter pills
- Remove dead header/nav/theme CSS from global.css (~160 lines)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-03-05 21:50:44 +11:00
committed by GitHub
parent 8fedf95507
commit 40fd1a6c72
50 changed files with 1891 additions and 888 deletions

View File

@@ -0,0 +1,11 @@
---
import Default from '@astrojs/starlight/components/Head.astro';
const basePath = import.meta.env.BASE_URL;
---
<Default><slot /></Default>
<script is:inline define:vars={{ basePath }}>
document.addEventListener('DOMContentLoaded', () => {
document.body.dataset.basePath = basePath;
});
</script>

View File

@@ -1,21 +0,0 @@
// Shared article ordering for the Learning Hub.
// Used by both the index page and the article sidebar layout.
export const fundamentalsOrder = [
'what-are-agents-skills-instructions',
'understanding-copilot-context',
'copilot-configuration-basics',
'defining-custom-instructions',
'creating-effective-skills',
'building-custom-agents',
'understanding-mcp-servers',
'automating-with-hooks',
'agentic-workflows',
'using-copilot-coding-agent',
'installing-and-using-plugins',
'before-after-customization-examples',
];
export const referenceOrder = [
'github-copilot-terminology-glossary',
];

View File

@@ -1,20 +1,20 @@
import { defineCollection, z } from "astro:content";
import { glob } from "astro/loaders";
import { docsLoader } from "@astrojs/starlight/loaders";
import { docsSchema } from "@astrojs/starlight/schema";
const learningHub = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/content/learning-hub" }),
schema: z.object({
title: z.string(),
description: z.string(),
authors: z.array(z.string()).optional(),
lastUpdated: z.string().optional(),
estimatedReadingTime: z.string().optional(),
tags: z.array(z.string()).optional(),
relatedArticles: z.array(z.string()).optional(),
prerequisites: z.array(z.string()).optional(),
const docs = defineCollection({
loader: docsLoader(),
schema: docsSchema({
extend: z.object({
authors: z.array(z.string()).optional(),
estimatedReadingTime: z.string().optional(),
tags: z.array(z.string()).optional(),
relatedArticles: z.array(z.string()).optional(),
prerequisites: z.array(z.string()).optional(),
}),
}),
});
export const collections = {
"learning-hub": learningHub,
docs,
};

View File

@@ -0,0 +1 @@
../../learning-hub/agentic-workflows.md

View File

@@ -0,0 +1 @@
../../learning-hub/automating-with-hooks.md

View File

@@ -0,0 +1 @@
../../learning-hub/before-after-customization-examples.md

View File

@@ -0,0 +1 @@
../../learning-hub/building-custom-agents.md

View File

@@ -0,0 +1 @@
../../learning-hub/copilot-configuration-basics.md

View File

@@ -0,0 +1 @@
../../learning-hub/creating-effective-skills.md

View File

@@ -0,0 +1 @@
../../learning-hub/defining-custom-instructions.md

View File

@@ -0,0 +1 @@
../../learning-hub/github-copilot-terminology-glossary.md

View File

@@ -0,0 +1,32 @@
---
title: Learning Hub
description: 'Curated articles, walkthroughs, and reference material to help you unlock everything you can do with GitHub Copilot'
template: splash
hero:
tagline: 'Curated articles, walkthroughs, and reference material to help you unlock everything you can do with GitHub Copilot'
actions:
- text: Start with Fundamentals
link: /learning-hub/what-are-agents-skills-instructions/
icon: right-arrow
sidebar:
hidden: true
tableOfContents: false
---
## Fundamentals
Essential concepts to tailor GitHub Copilot beyond its default experience. Start with
[What are Agents, Skills, and Instructions](/learning-hub/what-are-agents-skills-instructions/)
and work through the full track to master every customization primitive.
## Reference
Quick-lookup resources to keep handy while you work. Browse the
[GitHub Copilot Terminology Glossary](/learning-hub/github-copilot-terminology-glossary/)
for definitions of common terms and concepts.
## Hands-on
Interactive samples and recipes to learn by doing. Jump into the
[Cookbook](/learning-hub/cookbook/) for code samples, recipes,
and examples you can use right away.

View File

@@ -0,0 +1 @@
../../learning-hub/installing-and-using-plugins.md

View File

@@ -0,0 +1 @@
../../learning-hub/understanding-copilot-context.md

View File

@@ -0,0 +1 @@
../../learning-hub/understanding-mcp-servers.md

View File

@@ -0,0 +1 @@
../../learning-hub/using-copilot-coding-agent.md

View File

@@ -0,0 +1 @@
../../learning-hub/what-are-agents-skills-instructions.md

View File

@@ -3,7 +3,7 @@ title: 'Agentic Workflows'
description: 'Learn what GitHub Agentic Workflows are, how to use community workflows from Awesome Copilot, and how to contribute your own.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-27'
lastUpdated: 2026-02-27
estimatedReadingTime: '7 minutes'
tags:
- workflows

View File

@@ -3,7 +3,7 @@ title: 'Automating with Hooks'
description: 'Learn how to use hooks to automate lifecycle events like formatting, linting, and governance checks during Copilot agent sessions.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '8 minutes'
tags:
- hooks

View File

@@ -3,7 +3,7 @@ title: 'Before/After Customization Examples'
description: 'See real-world transformations showing how custom agents, skills, and instructions dramatically improve GitHub Copilot effectiveness.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2025-12-12'
lastUpdated: 2025-12-12
estimatedReadingTime: '12 minutes'
tags:
- customization

View File

@@ -3,7 +3,7 @@ title: 'Building Custom Agents'
description: 'Learn how to create specialized GitHub Copilot agents with custom personas, tool integrations, and domain expertise.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '10 minutes'
tags:
- agents

View File

@@ -3,7 +3,7 @@ title: 'Copilot Configuration Basics'
description: 'Learn how to configure GitHub Copilot at user, workspace, and repository levels to optimize your AI-assisted development experience.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2025-11-28'
lastUpdated: 2025-11-28
estimatedReadingTime: '10 minutes'
tags:
- configuration

View File

@@ -3,7 +3,7 @@ title: 'Creating Effective Skills'
description: 'Master the art of writing reusable, shareable skill folders that deliver consistent results across your team.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '9 minutes'
tags:
- skills

View File

@@ -3,7 +3,7 @@ title: 'Defining Custom Instructions'
description: 'Learn how to create persistent, context-aware instructions that guide GitHub Copilot automatically across your codebase.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2025-12-02'
lastUpdated: 2025-12-02
estimatedReadingTime: '8 minutes'
tags:
- instructions

View File

@@ -3,7 +3,7 @@ title: 'GitHub Copilot Terminology Glossary'
description: 'A quick reference guide defining common GitHub Copilot and platform-specific terms.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2025-12-15'
lastUpdated: 2025-12-15
estimatedReadingTime: '8 minutes'
tags:
- glossary

View File

@@ -3,7 +3,7 @@ title: 'Installing and Using Plugins'
description: 'Learn how to find, install, and manage plugins that extend GitHub Copilot CLI with reusable agents, skills, hooks, and integrations.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '8 minutes'
tags:
- plugins

View File

@@ -3,7 +3,7 @@ title: 'Understanding Copilot Context'
description: 'Learn how GitHub Copilot uses context from your code, workspace, and conversation to generate relevant suggestions.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2025-11-28'
lastUpdated: 2025-11-28
estimatedReadingTime: '8 minutes'
tags:
- context

View File

@@ -3,7 +3,7 @@ title: 'Understanding MCP Servers'
description: 'Learn how Model Context Protocol servers extend GitHub Copilot with access to external tools, databases, and APIs.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '8 minutes'
tags:
- mcp

View File

@@ -3,7 +3,7 @@ title: 'Using the Copilot Coding Agent'
description: 'Learn how to use GitHub Copilot coding agent to autonomously work on issues, generate pull requests, and automate development tasks.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '12 minutes'
tags:
- coding-agent

View File

@@ -3,8 +3,9 @@ title: 'What are Agents, Skills, and Instructions'
description: 'Understand the primary customization primitives that extend GitHub Copilot for specific workflows.'
authors:
- GitHub Copilot Learning Hub Team
lastUpdated: '2026-02-26'
lastUpdated: 2026-02-26
estimatedReadingTime: '7 minutes'
prev: false
---
Building great experiences with GitHub Copilot starts with understanding the core primitives that shape how Copilot behaves in different contexts. This article clarifies what each artifact does, how it is packaged inside this repository, and when to use it.

View File

@@ -0,0 +1,142 @@
/**
* Custom Pagefind integration that extends Starlight's search index
* with resource records (agents, skills, instructions, hooks, workflows, plugins).
*
* Starlight's pagefind is enabled (pagefind: true) so the search UI renders,
* but this integration runs AFTER Starlight's and overwrites the index with
* HTML pages + custom resource records combined.
*/
import type { AstroIntegration } from "astro";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import * as pagefind from "pagefind";
interface SearchRecord {
type: string;
id: string;
title: string;
description: string;
path: string;
tags?: string[];
searchText: string;
}
const TYPE_LABELS: Record<string, string> = {
agent: "Agent",
instruction: "Instruction",
skill: "Skill",
hook: "Hook",
workflow: "Workflow",
plugin: "Plugin",
tool: "Tool",
};
const TYPE_PAGES: Record<string, string> = {
agent: "/agents/",
instruction: "/instructions/",
skill: "/skills/",
hook: "/hooks/",
workflow: "/workflows/",
plugin: "/plugins/",
tool: "/tools/",
};
export default function pagefindResources(): AstroIntegration {
let siteBase = "/";
return {
name: "pagefind-resources",
hooks: {
"astro:config:done": ({ config }) => {
siteBase = config.base;
},
"astro:build:done": async ({ dir, logger }) => {
const log = logger.fork("pagefind-resources");
const now = performance.now();
try {
log.info("Building search index with Pagefind + resource records...");
const response = await pagefind.createIndex();
if (response.errors.length > 0) {
for (const err of response.errors) log.error(err);
throw new Error("Failed to create Pagefind index");
}
const { index } = response;
// Index all built HTML pages (same as Starlight's default)
const indexResult = await index.addDirectory({
path: fileURLToPath(dir),
});
if (indexResult.errors.length > 0) {
for (const err of indexResult.errors) log.error(err);
throw new Error("Failed to index HTML directory");
}
log.info(`Indexed ${indexResult.page_count} HTML pages.`);
// Read and index resource records from search-index.json
const searchIndexPath = fileURLToPath(
new URL("./data/search-index.json", dir)
);
let records: SearchRecord[];
try {
records = JSON.parse(readFileSync(searchIndexPath, "utf-8"));
} catch {
log.warn("Could not read search-index.json, skipping resource indexing.");
records = [];
}
// Use the base path from Astro config (e.g. "/awesome-copilot/")
const base = siteBase.endsWith("/") ? siteBase : `${siteBase}/`;
let added = 0;
for (const record of records) {
const typePage = TYPE_PAGES[record.type];
if (!typePage) continue;
const url = `${base}${typePage.slice(1)}#file=${encodeURIComponent(record.path)}`;
const typeLabel = TYPE_LABELS[record.type] || record.type;
const addResult = await index.addCustomRecord({
url,
content: record.searchText || `${record.title} ${record.description}`,
language: "en",
meta: {
title: `${record.title}${typeLabel}`,
},
filters: {
type: [record.type],
},
});
if (addResult.errors.length > 0) {
for (const err of addResult.errors) log.warn(`Record ${record.id}: ${err}`);
} else {
added++;
}
}
log.info(`Added ${added} resource records.`);
// Write the combined index
const writeResult = await index.writeFiles({
outputPath: fileURLToPath(new URL("./pagefind/", dir)),
});
if (writeResult.errors.length > 0) {
for (const err of writeResult.errors) log.error(err);
throw new Error("Failed to write Pagefind files");
}
const elapsed = performance.now() - now;
log.info(
`Search index built in ${elapsed < 750 ? `${Math.round(elapsed)}ms` : `${(elapsed / 1000).toFixed(2)}s`}.`
);
} catch (cause) {
throw new Error("Failed to build Pagefind search index.", { cause });
} finally {
await pagefind.close();
}
},
},
};
}

View File

@@ -1,132 +0,0 @@
---
import BaseLayout from './BaseLayout.astro';
import { getCollection } from 'astro:content';
import { fundamentalsOrder, referenceOrder } from '../config/learning-hub';
interface Props {
title: string;
description?: string;
estimatedReadingTime?: string;
lastUpdated?: string;
tags?: string[];
}
const { title, description, estimatedReadingTime, lastUpdated, tags } = Astro.props;
const base = import.meta.env.BASE_URL;
const createOrderIndexMap = (order: string[]) => {
const map = new Map<string, number>();
for (let i = 0; i < order.length; i += 1) {
map.set(order[i], i);
}
return map;
};
const articles = await getCollection('learning-hub');
const fundamentalsOrderIndex = createOrderIndexMap(fundamentalsOrder);
const referenceOrderIndex = createOrderIndexMap(referenceOrder);
const fundamentals = articles
.filter((a) => fundamentalsOrderIndex.has(a.id))
.sort(
(a, b) =>
(fundamentalsOrderIndex.get(a.id) ?? 0) - (fundamentalsOrderIndex.get(b.id) ?? 0),
);
const reference = articles
.filter((a) => referenceOrderIndex.has(a.id))
.sort(
(a, b) =>
(referenceOrderIndex.get(a.id) ?? 0) - (referenceOrderIndex.get(b.id) ?? 0),
);
const currentSlug = Astro.url.pathname.replace(/\/$/, '').split('/').pop();
---
<BaseLayout title={title} description={description} activeNav="learning-hub">
<main id="main-content">
<div class="page-header">
<div class="container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<a href={`${base}learning-hub/`}>← Learning Hub</a>
</nav>
<h1>{title}</h1>
{description && <p>{description}</p>}
<div class="article-meta">
{estimatedReadingTime && (
<span class="meta-item">
<span aria-hidden="true">📖</span> {estimatedReadingTime}
</span>
)}
{lastUpdated && <span class="meta-item">Updated: {lastUpdated}</span>}
</div>
{tags && tags.length > 0 && (
<div class="article-tags">
{tags.map((tag) => (
<span class="tag">{tag}</span>
))}
</div>
)}
</div>
</div>
<div class="page-content">
<div class="container">
<div class="learning-hub-layout">
<nav class="learning-hub-sidebar" aria-label="Learning Hub articles">
<div class="sidebar-section">
<h3>Fundamentals</h3>
<ol class="sidebar-nav-list">
{fundamentals.map((article) => (
<li>
<a
href={`${base}learning-hub/${article.id}/`}
class={currentSlug === article.id ? 'active' : ''}
aria-current={currentSlug === article.id ? 'page' : undefined}
>
{article.data.title}
</a>
</li>
))}
</ol>
</div>
<div class="sidebar-section">
<h3>Reference</h3>
<ul class="sidebar-nav-list">
{reference.map((article) => (
<li>
<a
href={`${base}learning-hub/${article.id}/`}
class={currentSlug === article.id ? 'active' : ''}
aria-current={currentSlug === article.id ? 'page' : undefined}
>
{article.data.title}
</a>
</li>
))}
</ul>
</div>
<div class="sidebar-section">
<h3>Hands-on</h3>
<ul class="sidebar-nav-list">
<li>
<a
href={`${base}learning-hub/cookbook/`}
class={currentSlug === 'cookbook' ? 'active' : ''}
aria-current={currentSlug === 'cookbook' ? 'page' : undefined}
>
Cookbook
</a>
</li>
</ul>
</div>
</nav>
<article class="article-content">
<slot />
</article>
</div>
</div>
</div>
</main>
</BaseLayout>

View File

@@ -1,199 +0,0 @@
---
import { execSync } from "child_process";
interface Props {
title: string;
description?: string;
activeNav?: string;
}
const {
title,
description = "Community-driven collection of custom agents, instructions, and skills for GitHub Copilot",
activeNav = "",
} = Astro.props;
const base = import.meta.env.BASE_URL;
const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
const socialImageUrl = new URL(`${base}images/social-image.png`, Astro.site);
// Get git commit SHA and build date at build time
let commitSha = "unknown";
let buildDate = new Date().toISOString().split("T")[0];
try {
// Use GITHUB_SHA env var in GitHub Actions, fallback to git command locally
const githubSha = process.env.GITHUB_SHA;
if (githubSha) {
commitSha = githubSha.substring(0, 7);
} else {
commitSha = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
}
} catch {
// Fallback if git is not available
}
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title} | Awesome GitHub Copilot</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonicalUrl} />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content={canonicalUrl.toString()} />
<meta property="og:title" content={`${title} | Awesome GitHub Copilot`} />
<meta property="og:description" content={description} />
<meta property="og:image" content={socialImageUrl.toString()} />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="2400" />
<meta property="og:image:height" content="1260" />
<meta property="og:site_name" content="Awesome GitHub Copilot" />
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={`${title} | Awesome GitHub Copilot`} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={socialImageUrl.toString()} />
<meta name="twitter:image:alt" content={`${title} | Awesome GitHub Copilot`} />
<link rel="stylesheet" href={`${base}styles/global.css`} />
<link
rel="icon"
href={`${base}images/Copilot_Icon_Black.svg`}
type="image/svg+xml"
/>
</head>
<body data-base-path={base}>
<a href="#main-content" class="skip-link">Skip to main content</a>
<header class="site-header">
<div class="container">
<div class="header-content">
<a href={base} class="logo">
<span class="logo-text">Awesome Copilot</span>
</a>
<nav class="main-nav" aria-label="Main navigation">
<a
href={`${base}agents/`}
class:list={[{ active: activeNav === "agents" }]}>Agents</a
>
<a
href={`${base}instructions/`}
class:list={[{ active: activeNav === "instructions" }]}
>Instructions</a
>
<a
href={`${base}skills/`}
class:list={[{ active: activeNav === "skills" }]}>Skills</a
>
<a
href={`${base}hooks/`}
class:list={[{ active: activeNav === "hooks" }]}>Hooks</a
>
<a
href={`${base}workflows/`}
class:list={[{ active: activeNav === "workflows" }]}>Workflows</a
>
<a
href={`${base}plugins/`}
class:list={[{ active: activeNav === "plugins" }]}
>Plugins</a
>
<a
href={`${base}tools/`}
class:list={[{ active: activeNav === "tools" }]}>Tools</a
>
<a
href={`${base}learning-hub/`}
class:list={[{ active: activeNav === "learning-hub" }]}>Learning Hub</a
>
</nav>
<div class="header-actions">
<button
id="theme-toggle"
class="theme-toggle"
aria-label="Toggle theme"
>
<svg
class="icon-sun"
viewBox="0 0 16 16"
fill="currentColor"
aria-hidden="true"
>
<path
d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"
></path>
</svg>
<svg
class="icon-moon"
viewBox="0 0 16 16"
fill="currentColor"
aria-hidden="true"
>
<path
d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"
></path>
</svg>
</button>
<a
href="https://github.com/github/awesome-copilot"
class="github-link"
target="_blank"
rel="noopener"
aria-label="View on GitHub"
>
<svg
viewBox="0 0 16 16"
width="24"
height="24"
fill="currentColor"
aria-hidden="true"
>
<path
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</a>
</div>
</div>
</div>
</header>
<slot />
<footer class="site-footer">
<div class="container">
<p>
<a
href="https://github.com/github/awesome-copilot"
target="_blank"
rel="noopener">GitHub</a
> ·
<a
href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md"
target="_blank"
rel="noopener">Contribute</a
> ·
<a
href="https://github.com/github/awesome-copilot/blob/main/LICENSE"
target="_blank"
rel="noopener">MIT License</a
>
</p>
<p class="build-info">
Built from <a
href={`https://github.com/github/awesome-copilot/commit/${commitSha}`}
target="_blank"
rel="noopener">{commitSha}</a
> on {buildDate}
</p>
</div>
</footer>
<script>
import "../scripts/theme";
</script>
</body>
</html>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
---
<BaseLayout title="Agents" description="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains" activeNav="agents">
<StarlightPage frontmatter={{ title: 'Custom Agents', description: 'Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="🤖 Custom Agents" description="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains" />
@@ -56,4 +56,4 @@ import PageHeader from '../components/PageHeader.astro';
<script>
import '../scripts/pages/agents';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
---
<BaseLayout title="Hooks" description="Automated workflows triggered by Copilot coding agent events" activeNav="hooks">
<StarlightPage frontmatter={{ title: 'Hooks', description: 'Automated workflows triggered by Copilot coding agent events', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="🪝 Hooks" description="Automated workflows triggered by Copilot coding agent events" />
@@ -49,4 +49,4 @@ import PageHeader from '../components/PageHeader.astro';
<script>
import '../scripts/pages/hooks';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Home" activeNav="">
<StarlightPage frontmatter={{ title: 'Awesome GitHub Copilot', template: 'splash', pagefind: false, prev: false, next: false, editUrl: false }} hasSidebar={false}>
<main id="main-content">
<!-- Hero Section -->
<section class="hero" aria-labelledby="hero-heading">
@@ -132,4 +132,4 @@ const base = import.meta.env.BASE_URL;
<script>
import '../scripts/pages/index';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
---
<BaseLayout title="Instructions" description="Coding standards and best practices for GitHub Copilot" activeNav="instructions">
<StarlightPage frontmatter={{ title: 'Instructions', description: 'Coding standards and best practices for GitHub Copilot', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="📋 Instructions" description="Coding standards and best practices for GitHub Copilot" />
@@ -45,4 +45,4 @@ import PageHeader from '../components/PageHeader.astro';
<script>
import '../scripts/pages/instructions';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,25 +0,0 @@
---
import ArticleLayout from '../../layouts/ArticleLayout.astro';
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const articles = await getCollection('learning-hub');
return articles.map((article) => ({
params: { slug: article.id },
props: { article },
}));
}
const { article } = Astro.props;
const { Content } = await render(article);
---
<ArticleLayout
title={article.data.title}
description={article.data.description}
estimatedReadingTime={article.data.estimatedReadingTime}
lastUpdated={article.data.lastUpdated}
tags={article.data.tags}
>
<Content />
</ArticleLayout>

View File

@@ -1,51 +1,35 @@
---
import BaseLayout from '../../../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../../../components/Modal.astro';
const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Cookbook" description="Code samples, recipes, and examples for building with GitHub Copilot" activeNav="learning-hub">
<main id="main-content">
<div class="page-header">
<div class="container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<a href={`${base}learning-hub/`}>← Learning Hub</a>
</nav>
<h1>🍳 Cookbook</h1>
<p>Code samples, recipes, and examples for building with GitHub Copilot tools</p>
</div>
<StarlightPage frontmatter={{ title: 'Cookbook', description: 'Code samples, recipes, and examples for building with GitHub Copilot' }}>
<div class="cookbook-page">
<div class="search-bar">
<label for="search-input" class="sr-only">Search recipes</label>
<input type="text" id="search-input" placeholder="Search recipes..." autocomplete="off">
</div>
<div class="page-content">
<div class="container">
<div class="search-bar">
<label for="search-input" class="sr-only">Search recipes</label>
<input type="text" id="search-input" placeholder="Search recipes..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-language">Language:</label>
<select id="filter-language" aria-label="Filter by language">
<option value="">All Languages</option>
</select>
</div>
<div class="filter-group">
<label for="filter-tag">Tags:</label>
<select id="filter-tag" multiple aria-label="Filter by tags"></select>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div id="samples-list" role="list">
<div class="loading" aria-live="polite">Loading samples...</div>
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-language">Language:</label>
<select id="filter-language" aria-label="Filter by language">
<option value="">All Languages</option>
</select>
</div>
<div class="filter-group">
<label for="filter-tag">Tags:</label>
<select id="filter-tag" multiple aria-label="Filter by tags"></select>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
</main>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div id="samples-list" role="list">
<div class="loading" aria-live="polite">Loading samples...</div>
</div>
</div>
<Modal />
@@ -281,4 +265,4 @@ const base = import.meta.env.BASE_URL;
<script>
import '../../../scripts/pages/samples';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,158 +0,0 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import { getCollection } from 'astro:content';
import { fundamentalsOrder, referenceOrder } from '../../config/learning-hub';
const base = import.meta.env.BASE_URL;
const articles = await getCollection('learning-hub');
const createOrderIndexMap = (order) => {
const map = new Map();
order.forEach((id, index) => {
map.set(id, index);
});
return map;
};
const fundamentalsOrderIndex = createOrderIndexMap(fundamentalsOrder);
const referenceOrderIndex = createOrderIndexMap(referenceOrder);
const fundamentals = articles
.filter((a) => fundamentalsOrder.includes(a.id))
.sort((a, b) => fundamentalsOrderIndex.get(a.id) - fundamentalsOrderIndex.get(b.id));
const reference = articles
.filter((a) => referenceOrder.includes(a.id))
.sort((a, b) => referenceOrderIndex.get(a.id) - referenceOrderIndex.get(b.id));
---
<BaseLayout title="Learning Hub" description="Curated articles and walkthroughs to help you unlock everything you can do with GitHub Copilot" activeNav="learning-hub">
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>📚 Learning Hub</h1>
<p>Curated articles, walkthroughs, and reference material to help you unlock everything you can do with GitHub Copilot</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="learning-hub-layout">
<nav class="learning-hub-sidebar" aria-label="Learning Hub sections">
<div class="sidebar-section">
<h3>Fundamentals</h3>
<ol class="sidebar-nav-list">
{fundamentals.map((article) => (
<li>
<a href={`${base}learning-hub/${article.id}/`}>
{article.data.title}
</a>
</li>
))}
</ol>
</div>
<div class="sidebar-section">
<h3>Reference</h3>
<ul class="sidebar-nav-list">
{reference.map((article) => (
<li>
<a href={`${base}learning-hub/${article.id}/`}>
{article.data.title}
</a>
</li>
))}
</ul>
</div>
<div class="sidebar-section">
<h3>Hands-on</h3>
<ul class="sidebar-nav-list">
<li>
<a href={`${base}learning-hub/cookbook/`}>Cookbook</a>
</li>
</ul>
</div>
</nav>
<div class="learning-hub-index-content">
<section class="learning-hub-section" id="fundamentals">
<h2>Fundamentals</h2>
<p class="section-description">Essential concepts to tailor GitHub Copilot beyond its default experience.</p>
<div class="article-list">
{fundamentals.map((article, index) => (
<a href={`${base}learning-hub/${article.id}/`} class="article-card">
<div class="article-number" aria-hidden="true">{index + 1}</div>
<div class="article-info">
<h3>{article.data.title}</h3>
<p>{article.data.description}</p>
<div class="article-meta">
{article.data.estimatedReadingTime && (
<span class="meta-item">📖 {article.data.estimatedReadingTime}</span>
)}
{article.data.tags && article.data.tags.length > 0 && (
<span class="meta-item">
{article.data.tags.map((tag) => (
<span class="tag">{tag}</span>
))}
</span>
)}
</div>
</div>
</a>
))}
</div>
</section>
<section class="learning-hub-section" id="reference">
<h2>Reference</h2>
<p class="section-description">Quick-lookup resources to keep handy while you work.</p>
<div class="article-list">
{reference.map((article) => (
<a href={`${base}learning-hub/${article.id}/`} class="article-card">
<div class="article-number" aria-hidden="true">📖</div>
<div class="article-info">
<h3>{article.data.title}</h3>
<p>{article.data.description}</p>
<div class="article-meta">
{article.data.estimatedReadingTime && (
<span class="meta-item">📖 {article.data.estimatedReadingTime}</span>
)}
{article.data.tags && article.data.tags.length > 0 && (
<span class="meta-item">
{article.data.tags.map((tag) => (
<span class="tag">{tag}</span>
))}
</span>
)}
</div>
</div>
</a>
))}
</div>
</section>
<section class="learning-hub-section" id="hands-on">
<h2>Hands-on</h2>
<p class="section-description">Interactive samples and recipes to learn by doing.</p>
<div class="article-list">
<a href={`${base}learning-hub/cookbook/`} class="article-card">
<div class="article-number" aria-hidden="true">🍳</div>
<div class="article-info">
<h3>Cookbook</h3>
<p>Code samples, recipes, and examples for building with GitHub Copilot tools</p>
<div class="article-meta">
<span class="meta-item">
<span class="tag">samples</span>
<span class="tag">recipes</span>
<span class="tag">sdk</span>
</span>
</div>
</div>
</a>
</div>
</section>
</div>
</div>
</div>
</div>
</main>
</BaseLayout>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
---
<BaseLayout title="Plugins" description="Curated plugins of agents, hooks, and skills for specific workflows" activeNav="plugins">
<StarlightPage frontmatter={{ title: 'Plugins', description: 'Curated plugins of agents, hooks, and skills for specific workflows', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="🔌 Plugins" description="Curated plugins of agents, hooks, and skills for specific workflows" />
@@ -44,4 +44,4 @@ import PageHeader from '../components/PageHeader.astro';
<script>
import '../scripts/pages/plugins';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
---
<BaseLayout title="Skills" description="Self-contained agent skills with instructions and bundled resources" activeNav="skills">
<StarlightPage frontmatter={{ title: 'Skills', description: 'Self-contained agent skills with instructions and bundled resources', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="⚡ Skills" description="Self-contained agent skills with instructions and bundled resources" />
@@ -51,4 +51,4 @@ import PageHeader from '../components/PageHeader.astro';
<script>
import '../scripts/pages/skills';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,14 +1,10 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import ContributeCTA from "../components/ContributeCTA.astro";
import PageHeader from "../components/PageHeader.astro";
---
<BaseLayout
title="Tools"
description="MCP servers and developer tools for GitHub Copilot"
activeNav="tools"
>
<StarlightPage frontmatter={{ title: 'Tools', description: 'MCP servers and developer tools for GitHub Copilot', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="🔧 Tools" description="MCP servers and developer tools for GitHub Copilot" />
@@ -306,4 +302,4 @@ import PageHeader from "../components/PageHeader.astro";
import { initToolsPage } from "../scripts/pages/tools";
initToolsPage();
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,11 +1,11 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
---
<BaseLayout title="Workflows" description="AI-powered repository automations that run coding agents in GitHub Actions" activeNav="workflows">
<StarlightPage frontmatter={{ title: 'Agentic Workflows', description: 'AI-powered repository automations that run coding agents in GitHub Actions', template: 'splash', prev: false, next: false, editUrl: false }}>
<main id="main-content">
<PageHeader title="⚡ Agentic Workflows" description="">
AI-powered repository automations that run coding agents in <a href="https://gh.io/gh-aw" target="_blank" rel="noopener">GitHub Actions</a>
@@ -47,4 +47,4 @@ import PageHeader from '../components/PageHeader.astro';
<script>
import '../scripts/pages/workflows';
</script>
</BaseLayout>
</StarlightPage>

View File

@@ -1,65 +0,0 @@
/**
* Theme management for the Awesome Copilot website
* Supports light/dark mode with user preference storage
*/
const THEME_KEY = 'theme';
/**
* Get the current theme preference
*/
function getThemePreference(): 'light' | 'dark' {
const stored = localStorage.getItem(THEME_KEY);
if (stored === 'light' || stored === 'dark') {
return stored;
}
// Check system preference
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
return 'light';
}
return 'dark';
}
/**
* Apply theme to the document
*/
function applyTheme(theme: 'light' | 'dark'): void {
document.documentElement.setAttribute('data-theme', theme);
}
const initialTheme = getThemePreference();
applyTheme(initialTheme);
/**
* Toggle between light and dark theme
*/
export function toggleTheme(): void {
const current = document.documentElement.getAttribute('data-theme') as 'light' | 'dark';
const newTheme = current === 'light' ? 'dark' : 'light';
applyTheme(newTheme);
localStorage.setItem(THEME_KEY, newTheme);
}
/**
* Initialize theme toggle button
*/
export function initThemeToggle(): void {
const toggleBtn = document.getElementById('theme-toggle');
if (toggleBtn) {
toggleBtn.addEventListener('click', toggleTheme);
}
// Listen for system theme changes
if (window.matchMedia) {
window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', (e) => {
// Only auto-switch if user hasn't set a preference
const stored = localStorage.getItem(THEME_KEY);
if (!stored) {
applyTheme(e.matches ? 'light' : 'dark');
}
});
}
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initThemeToggle);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,181 @@
/* Brand color overrides for Starlight */
/* Purple (#8534F3) and Orange (#FE4C25) theme */
/* ── Dark theme (default) ─────────────────────────────────── */
:root {
--sl-color-accent-low: #1a0d33;
--sl-color-accent: #8534f3;
--sl-color-accent-high: #c9a5fa;
--sl-color-text-accent: #c9a5fa;
--sl-color-white: #f0f0f5;
--sl-color-gray-1: #d0d0da;
--sl-color-gray-2: #9898a6;
--sl-color-gray-3: #60607a;
--sl-color-gray-4: #30304a;
--sl-color-gray-5: #1a1a2e;
--sl-color-gray-6: #111120;
--sl-color-black: #0a0a0f;
--sl-font-system: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif;
}
/* ── Light theme ───────────────────────────────────────────── */
/* Starlight inverts the gray scale for light mode.
Because our customCss is unlayered it overrides Starlight's layered
theme swap, so we must provide the inverted palette ourselves. */
:root[data-theme="light"] {
--sl-color-accent-low: #f0e6ff;
--sl-color-accent: #6b21c8;
--sl-color-accent-high: #3b0d7a;
--sl-color-text-accent: #6b21c8;
--sl-color-white: #0a0a0f;
--sl-color-gray-1: #111120;
--sl-color-gray-2: #1a1a2e;
--sl-color-gray-3: #30304a;
--sl-color-gray-4: #60607a;
--sl-color-gray-5: #9898a6;
--sl-color-gray-6: #d0d0da;
--sl-color-black: #f0f0f5;
}
/* ── Sidebar active item ───────────────────────────────────── */
nav[aria-label="Main"] a[aria-current="page"] {
color: var(--sl-color-accent) !important;
font-weight: 600;
border-inline-start-color: var(--sl-color-accent) !important;
}
/* ── Header brand styling ──────────────────────────────────── */
.site-title {
font-weight: 700 !important;
}
header .site-title:hover {
color: var(--sl-color-accent-high) !important;
}
/* ── Browse Resources sidebar group ────────────────────────── */
nav[aria-label="Main"] > ul > li:first-child details summary,
nav[aria-label="Main"] > ul > li:first-child > a {
font-weight: 600;
}
/* ── Hide Starlight's auto-generated page title on custom splash pages ── */
/* Only affects pages that have their own #main-content (custom pages) */
/* Starlight generates a title h1; custom pages render their own h1 */
main:has(#main-content) > .content-panel:has(h1#_top) {
display: none !important;
}
/* ── Pagefind search filter pills ──────────────────────────── */
/* Restyle the default checkbox filters as horizontal pill toggles above results */
/* Stack filters above results instead of side-by-side */
#starlight__search .pagefind-ui__drawer {
flex-direction: column !important;
}
#starlight__search .pagefind-ui__filter-panel {
border: none;
padding: 0;
margin: 0;
width: 100% !important;
min-width: 0 !important;
flex: none !important;
}
#starlight__search .pagefind-ui__filter-panel-label {
display: none;
}
/* Remove the collapsible <details> wrapper — always show filters */
#starlight__search .pagefind-ui__filter-block {
border: none;
margin: 0;
padding: 0;
}
#starlight__search .pagefind-ui__filter-block > summary {
display: none;
}
/* Hide the "type" group legend */
#starlight__search .pagefind-ui__filter-group-label {
display: none;
}
/* Lay out filter values as a horizontal pill row */
#starlight__search .pagefind-ui__filter-group {
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
align-items: center !important;
gap: 0.375rem;
padding: 0.375rem 0 0.625rem;
border: none;
margin: 0;
}
/* Each pill: hide the checkbox, style the label as a pill */
#starlight__search .pagefind-ui__filter-value {
display: contents;
}
/* Visually hidden but still focusable for keyboard a11y */
#starlight__search .pagefind-ui__filter-checkbox {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
#starlight__search .pagefind-ui__filter-value::before {
display: none !important;
}
#starlight__search .pagefind-ui__filter-label {
display: inline-flex !important;
width: auto !important;
align-items: center;
padding: 0.2rem 0.625rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
line-height: 1.4;
cursor: pointer;
user-select: none;
transition: all 0.15s ease;
border: 1px solid var(--sl-color-gray-5);
color: var(--sl-color-gray-2);
background: transparent;
text-transform: capitalize;
}
#starlight__search .pagefind-ui__filter-label:hover {
border-color: var(--sl-color-accent);
color: var(--sl-color-accent-high);
}
/* Keyboard focus ring for pill filters */
#starlight__search .pagefind-ui__filter-checkbox:focus-visible + .pagefind-ui__filter-label {
outline: 2px solid var(--sl-color-accent);
outline-offset: 2px;
}
/* Active/checked pill state */
#starlight__search .pagefind-ui__filter-checkbox:checked + .pagefind-ui__filter-label {
background: var(--sl-color-accent);
border-color: var(--sl-color-accent);
color: white;
}
#starlight__search .pagefind-ui__filter-checkbox:checked + .pagefind-ui__filter-label:hover {
opacity: 0.9;
}