Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions website/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ export default defineConfig({
starlight({
title: "Awesome GitHub Copilot",
description: siteDescription,
social: [
{
icon: "github",
label: "GitHub",
href: "https://github.com/github/awesome-copilot",
},
],
social: [],
head: [
{
tag: "meta",
Expand Down
Binary file added website/public/images/awesome-copilot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
129 changes: 129 additions & 0 deletions website/src/components/BackToTop.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
// Back to Top Button Component
---

<button
id="back-to-top"
class="back-to-top"
aria-label="Back to top"
title="Back to top"
>
<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 15l-6-6-6 6"/>
</svg>
</button>

<script>
(function() {
const button = document.getElementById('back-to-top');
if (!button) return;

// Move button to body level to escape stacking contexts
if (button.parentElement !== document.body) {
document.body.appendChild(button);
}

// Show/hide button based on scroll position
function toggleVisibility() {
const scrollY = window.scrollY || document.documentElement.scrollTop;
if (scrollY > 400) {
button.classList.add('visible');
} else {
button.classList.remove('visible');
}
}

// Scroll to top with smooth behavior
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}

// Throttled scroll handler
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
toggleVisibility();
ticking = false;
});
ticking = true;
}
}, { passive: true });

// Click handler
button.addEventListener('click', scrollToTop);

// Initial check
toggleVisibility();
})();
</script>

<style is:global>
.back-to-top {
position: fixed;
bottom: 24px;
right: 24px;
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--color-accent);
color: white;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
transform: translateY(20px) scale(0.8);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(133, 52, 243, 0.4);
z-index: 9999;
}

.back-to-top.visible {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
}

.back-to-top:hover {
background: var(--color-accent-hover);
transform: translateY(-2px) scale(1.05);
box-shadow: 0 6px 20px rgba(133, 52, 243, 0.5);
}

.back-to-top:active {
transform: translateY(0) scale(0.95);
}

.back-to-top:focus-visible {
outline: 2px solid var(--color-text-emphasis);
outline-offset: 2px;
}

/* Mobile adjustments */
@media (max-width: 768px) {
.back-to-top {
bottom: 16px;
right: 16px;
width: 44px;
height: 44px;
}
}

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
.back-to-top {
transition: opacity 0.2s ease;
transform: none;
}

.back-to-top.visible {
transform: none;
}
}
</style>
7 changes: 5 additions & 2 deletions website/src/components/Footer.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import LastUpdated from "@astrojs/starlight/components/LastUpdated.astro";
import Pagination from "@astrojs/starlight/components/Pagination.astro";
import config from "virtual:starlight/user-config";
import { Icon } from "@astrojs/starlight/components";
import ThemeToggle from "./ThemeToggle.astro";
---

<footer class="sl-flex">
Expand All @@ -21,9 +22,11 @@ import { Icon } from "@astrojs/starlight/components";
)
}

<p class="made-by">Made with ❤️ by our amazing <a href="/contributors/">contributors</a></p>
<p class="made-by">Made with love by our amazing <a href="/contributors/">contributors</a></p>
</footer>

<ThemeToggle />

<style>
footer {
flex-direction: column;
Expand Down Expand Up @@ -81,4 +84,4 @@ import { Icon } from "@astrojs/starlight/components";
.made-by a:hover {
color: var(--sl-color-accent);
}
</style>
</style>
22 changes: 22 additions & 0 deletions website/src/components/Head.astro
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,29 @@ const twitterDomain =
{socialImageUrl && <meta property="og:image:secure_url" content={socialImageUrl} />}
{socialImageType && <meta property="og:image:type" content={socialImageType} />}
{socialImageAlt && <meta name="twitter:image:alt" content={socialImageAlt} />}

<!-- Theme initialization script (runs early to prevent flash) -->
<script is:inline>
(function() {
const STORAGE_KEY = 'awesome-copilot-theme';
const stored = localStorage.getItem(STORAGE_KEY);

// Theme handling:
// - 'dark' or 'light' → set data-theme attribute to that value
// - 'auto' or unset → don't set data-theme (CSS media query handles system preference)
if (stored === 'dark' || stored === 'light') {
document.documentElement.setAttribute('data-theme', stored);
}
// For 'auto' or unset, no attribute means CSS media query controls theme
})();
</script>

<script is:inline define:vars={{ basePath }}>
// basePath setup for runtime use
document.addEventListener('DOMContentLoaded', () => {
document.body.dataset.basePath = basePath;
});

document.addEventListener('DOMContentLoaded', () => {
document.body.dataset.basePath = basePath;
});
Expand Down
120 changes: 120 additions & 0 deletions website/src/components/Icon.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
// Icon component with SVG icons
// Icons are either fill-based (from GitHub Primer) or stroke-based (custom)
// GitHub Primer icons are sourced from https://primer.style/foundations/icons/

export interface Props {
name: 'agents' | 'instructions' | 'skills' | 'hooks' | 'workflows' | 'plugins' | 'tools' | 'learning' | 'close' | 'copy' | 'download' | 'share' | 'external' | 'plus' | 'search' | 'chevron-down' | 'document' | 'lightning' | 'hook' | 'workflow' | 'plug' | 'wrench' | 'book' | 'robot' | 'sync';
size?: number;
class?: string;
}

const { name, size = 24, class: className = '' } = Astro.props;

// Icon definitions: { path: SVG path(s), fill: true for fill-based icons }
const icons: Record<string, { path: string; fill?: boolean }> = {
// Resource type icons - using GitHub Primer icons where available

// Agent icon - using GitHub Primer's agent-24 (sparkle over workflow)
// Source: https://primer.style/foundations/icons/agent-24
'robot': {
fill: true,
path: `<path d="M22.5 13.919v-.278a5.097 5.097 0 0 0-4.961-5.086.858.858 0 0 1-.754-.497l-.149-.327A6.414 6.414 0 0 0 10.81 4a6.133 6.133 0 0 0-6.13 6.32l.019.628a.863.863 0 0 1-.67.869A3.263 3.263 0 0 0 1.5 14.996v.108A3.397 3.397 0 0 0 4.896 18.5h1.577a.75.75 0 0 1 0 1.5H4.896A4.896 4.896 0 0 1 0 15.104v-.108a4.761 4.761 0 0 1 3.185-4.493l-.004-.137A7.633 7.633 0 0 1 10.81 2.5a7.911 7.911 0 0 1 7.176 4.58C21.36 7.377 24 10.207 24 13.641v.278a.75.75 0 0 1-1.5 0Z"/><path d="m12.306 11.77 3.374 3.375a.749.749 0 0 1 0 1.061l-3.375 3.375-.057.051a.751.751 0 0 1-1.004-.051.751.751 0 0 1-.051-1.004l.051-.057 2.845-2.845-2.844-2.844a.75.75 0 1 1 1.061-1.061ZM22.5 19.8H18a.75.75 0 0 1 0-1.5h4.5a.75.75 0 0 1 0 1.5Z"/>`
},

// Document icon - custom stroke-based
'document': {
path: `<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M14 2v6h6M16 13H8M16 17H8M10 9H8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

// Lightning icon - custom stroke-based (for skills)
'lightning': {
path: `<path d="M13 2 4.09 12.11a1.23 1.23 0 0 0 .13 1.72l.16.14a1.23 1.23 0 0 0 1.52 0L13 9.5V22l8.91-10.11a1.23 1.23 0 0 0-.13-1.72l-.16-.14a1.23 1.23 0 0 0-1.52 0L13 14.5V2Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

// Hook icon - using GitHub Primer's sync-24 (represents hooks/iterations)
// Source: https://primer.style/foundations/icons/sync-24
'hook': {
fill: true,
path: `<path d="M3.38 8A9.502 9.502 0 0 1 12 2.5a9.502 9.502 0 0 1 9.215 7.182.75.75 0 1 0 1.456-.364C21.473 4.539 17.15 1 12 1a10.995 10.995 0 0 0-9.5 5.452V4.75a.75.75 0 0 0-1.5 0V8.5a1 1 0 0 0 1 1h3.75a.75.75 0 0 0 0-1.5H3.38Zm-.595 6.318a.75.75 0 0 0-1.455.364C2.527 19.461 6.85 23 12 23c4.052 0 7.592-2.191 9.5-5.451v1.701a.75.75 0 0 0 1.5 0V15.5a1 1 0 0 0-1-1h-3.75a.75.75 0 0 0 0 1.5h2.37A9.502 9.502 0 0 1 12 21.5c-4.446 0-8.181-3.055-9.215-7.182Z"/>`
},

// Workflow icon - using GitHub Primer's workflow-24
// Source: https://primer.style/foundations/icons/workflow-24
// Also used by https://github.github.com/gh-aw/
'workflow': {
fill: true,
path: `<path d="M1 3a2 2 0 0 1 2-2h6.5a2 2 0 0 1 2 2v6.5a2 2 0 0 1-2 2H7v4.063C7 16.355 7.644 17 8.438 17H12.5v-2.5a2 2 0 0 1 2-2H21a2 2 0 0 1 2 2V21a2 2 0 0 1-2 2h-6.5a2 2 0 0 1-2-2v-2.5H8.437A2.939 2.939 0 0 1 5.5 15.562V11.5H3a2 2 0 0 1-2-2Zm2-.5a.5.5 0 0 0-.5.5v6.5a.5.5 0 0 0 .5.5h6.5a.5.5 0 0 0 .5-.5V3a.5.5 0 0 0-.5-.5ZM14.5 14a.5.5 0 0 0-.5.5V21a.5.5 0 0 0 .5.5H21a.5.5 0 0 0 .5-.5v-6.5a.5.5 0 0 0-.5-.5Z"/>`
},

// Plug icon - using GitHub Primer's plug-24
// Source: https://primer.style/foundations/icons/plug-24
'plug': {
fill: true,
path: `<path d="M7 11.5H2.938c-.794 0-1.438.644-1.438 1.437v8.313a.75.75 0 0 1-1.5 0v-8.312A2.939 2.939 0 0 1 2.937 10H7V6.151c0-.897.678-1.648 1.57-1.74l6.055-.626 1.006-1.174A1.752 1.752 0 0 1 16.96 2h1.29c.966 0 1.75.784 1.75 1.75V6h3.25a.75.75 0 0 1 0 1.5H20V14h3.25a.75.75 0 0 1 0 1.5H20v2.25a1.75 1.75 0 0 1-1.75 1.75h-1.29a1.75 1.75 0 0 1-1.329-.611l-1.006-1.174-6.055-.627A1.749 1.749 0 0 1 7 15.348Zm9.77-7.913v.001l-1.201 1.4a.75.75 0 0 1-.492.258l-6.353.657a.25.25 0 0 0-.224.249v9.196a.25.25 0 0 0 .224.249l6.353.657c.191.02.368.112.493.258l1.2 1.401a.252.252 0 0 0 .19.087h1.29a.25.25 0 0 0 .25-.25v-14a.25.25 0 0 0-.25-.25h-1.29a.252.252 0 0 0-.19.087Z"/>`
},

// Wrench icon - custom stroke-based (for tools)
'wrench': {
path: `<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

// Book icon - custom stroke-based (for learning)
'book': {
path: `<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

// Action icons - all custom stroke-based
'close': {
path: `<path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'copy': {
path: `<path d="M8 4h8a2 2 0 0 1 2 2v8M8 4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 4v10a2 2 0 0 0 2 2h8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'download': {
path: `<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'share': {
path: `<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8M16 6l-4-4-4 4M12 2v13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'external': {
path: `<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14 21 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'plus': {
path: `<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'search': {
path: `<circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="m21 21-4.35-4.35" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

'chevron-down': {
path: `<path d="m6 9 6 6 6-6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`
},

// Alias for hook - same as 'hook'
'sync': {
fill: true,
path: `<path d="M3.38 8A9.502 9.502 0 0 1 12 2.5a9.502 9.502 0 0 1 9.215 7.182.75.75 0 1 0 1.456-.364C21.473 4.539 17.15 1 12 1a10.995 10.995 0 0 0-9.5 5.452V4.75a.75.75 0 0 0-1.5 0V8.5a1 1 0 0 0 1 1h3.75a.75.75 0 0 0 0-1.5H3.38Zm-.595 6.318a.75.75 0 0 0-1.455.364C2.527 19.461 6.85 23 12 23c4.052 0 7.592-2.191 9.5-5.451v1.701a.75.75 0 0 0 1.5 0V15.5a1 1 0 0 0-1-1h-3.75a.75.75 0 0 0 0 1.5h2.37A9.502 9.502 0 0 1 12 21.5c-4.446 0-8.181-3.055-9.215-7.182Z"/>`
},
};

const iconData = icons[name] || { path: '' };
const isFill = iconData.fill ?? false;
const iconPath = iconData.path;
---

<svg
viewBox="0 0 24 24"
width={size}
height={size}
fill={isFill ? 'currentColor' : 'none'}
class={className}
aria-hidden="true"
set:html={iconPath}
/>
18 changes: 16 additions & 2 deletions website/src/components/PageHeader.astro
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
---
import Icon from './Icon.astro';

interface Props {
title: string;
description: string;
icon?: 'robot' | 'document' | 'lightning' | 'hook' | 'workflow' | 'plug' | 'wrench' | 'book';
}

const { title, description } = Astro.props;
const { title, description, icon } = Astro.props;
const contributingUrl = 'https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md';
---

<div class="page-header">
<div class="container">
<div class="page-header-row">
<div>
<h1><Fragment set:html={title} /></h1>
<h1>
{icon && <Icon name={icon} size={28} />}
<Fragment set:html={title} />
</h1>
<p><slot><Fragment set:html={description} /></slot></p>
</div>
<a href={contributingUrl} class="contribute-link" target="_blank" rel="noopener">
Expand All @@ -22,3 +28,11 @@ const contributingUrl = 'https://github.com/github/awesome-copilot/blob/main/CON
</div>
</div>
</div>

<style>
.page-header h1 {
display: flex;
align-items: center;
gap: 0.5rem;
}
</style>
Loading
Loading