Skip to content

Commit

Permalink
Add /repro route (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
delucis authored Dec 4, 2024
1 parent dcf7b7a commit 5b3bddc
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 19 deletions.
3 changes: 3 additions & 0 deletions astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const NETLIFY_PREVIEW_SITE = process.env.CONTEXT !== 'production' && process.env
export default defineConfig({
site: NETLIFY_PREVIEW_SITE || 'https://astro.new',
prefetch: true,
redirects: {
'/repro/': '/repro/getting-started',
},
integrations: [
tailwind({
applyBaseStyles: false,
Expand Down
24 changes: 18 additions & 6 deletions src/components/Hero.astro
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
---
import houstonOmg from '../assets/houston_omg.webp';
interface Props {
title?: string;
infoBoxTitle?: string;
}
const {
title = 'It’s go time with Astro',
infoBoxTitle = 'Get started with a new Astro project!',
} = Astro.props;
---

<section class="flex flex-col items-center gap-16 py-16 lg:flex-row" aria-labelledby="hero-heading">
<h2
class="heading-2 text-pretty text-center text-5xl/tight sm:text-6xl/tight lg:max-w-lg lg:text-left"
id="hero-heading"
>
It’s go time with Astro
{title}
</h2>
<div class="w-[640px] max-w-full rounded-md bg-blue-purple-gradient p-px shadow-md @container">
<section
class="flex flex-col overflow-hidden rounded-md bg-astro-gray-700 px-6 @sm:flex-row @sm:gap-6"
>
<div class="flex flex-1 flex-col gap-4 py-6 text-astro-gray-200">
<h3 class="font-medium text-white">Get started with a new Astro project!</h3>
<p>
Open any of these templates in your choice of online code editor, or view the source code
on GitHub.
</p>
<h3 class="font-medium text-white">{infoBoxTitle}</h3>
<slot name="infobox-content">
<p>
Open any of these templates in your choice of online code editor, or view the source
code on GitHub.
</p>
</slot>
</div>
<img
src={houstonOmg.src}
Expand Down
48 changes: 35 additions & 13 deletions src/components/RepoCard.astro
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
---
import { Image } from 'astro:assets';
import Icon from 'astro-icon';
import fallbackImage from '../assets/previews/minimal.webp';
import type { Example } from '../data/examples.js';
import CopyButton from './CopyButton.astro';
import ProjectLauncher from './ProjectLauncher.astro';
import RepoCardLink from './RepoCardLink.astro';
import StackBlitzButton from './StackBlitzButton.astro';
export type Props = Example & { aboveTheFold: boolean };
export type Props = Example & { aboveTheFold: boolean; minimal?: boolean; recommended?: boolean };
const {
minimal = false,
recommended = false,
title,
name,
sourceUrl,
Expand All @@ -31,7 +35,7 @@ const headingId = `template-${createAstroTemplate}`;
aria-labelledby={headingId}
>
<div class="noise z-0"></div>
<div class="aspect-video bg-astro-gray-700">
<div class="relative aspect-video bg-astro-gray-700">
<Image
transition:name={name}
transition:animate="initial"
Expand All @@ -42,21 +46,39 @@ const headingId = `template-${createAstroTemplate}`;
sizes="(min-width 1280px) 390px,(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"
class="object-cover object-left-top outline outline-1 -outline-offset-1 outline-astro-gray-100/10 s-full"
/>
{
recommended && (
<span class="absolute left-0 top-0 flex items-center gap-2 bg-astro-gray-700/70 p-3 leading-none">
<Icon name="star" size={16} aria-hidden="true" />
Recommended
</span>
)
}
</div>
<div class="flex flex-col gap-4 p-5">
<h2 class="heading-4" id={headingId}>{title}</h2>
<p class="flex flex-wrap gap-2">
{
previewEmbedUrl && (
<RepoCardLink as="a" href={previewEmbedUrl} icon="eye" data-astro-prefetch>
Preview
{
!minimal && (
<p class="flex flex-wrap gap-2">
{previewEmbedUrl && (
<RepoCardLink as="a" href={previewEmbedUrl} icon="eye" data-astro-prefetch>
Preview
</RepoCardLink>
)}
<RepoCardLink as="a" href={sourceUrl} icon="github">
Source code
</RepoCardLink>
)
}
<RepoCardLink as="a" href={sourceUrl} icon="github">Source code</RepoCardLink>
<CopyButton {createAstroTemplate} />
</p>
<CopyButton {createAstroTemplate} />
</p>
)
}
<hr class="border-astro-gray-100/10" />
<ProjectLauncher {...{ idxUrl, stackblitzUrl, codesandboxUrl, gitpodUrl }} />
{
minimal ? (
<StackBlitzButton {stackblitzUrl} />
) : (
<ProjectLauncher {...{ idxUrl, stackblitzUrl, codesandboxUrl, gitpodUrl }} />
)
}
</div>
</article>
21 changes: 21 additions & 0 deletions src/components/StackBlitzButton.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
import Icon from 'astro-icon';
import type { Example } from '../data/examples.ts';
type Props = Pick<Example, 'stackblitzUrl'>;
const { stackblitzUrl } = Astro.props;
---

<div
class="relative flex h-10 w-max min-w-0 max-w-full overflow-clip rounded-full bg-blue-purple-gradient"
>
<a
href={stackblitzUrl}
target="_blank"
rel="noopener noreferrer"
class="flex items-center gap-2 bg-black/15 px-4 text-sm transition hover:backdrop-brightness-75"
>
<Icon name="stackblitz" size={16} aria-hidden="true" /> Open in StackBlitz
</a>
</div>
1 change: 1 addition & 0 deletions src/icons/star.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
170 changes: 170 additions & 0 deletions src/pages/repro/[tab].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
import type { GetStaticPaths } from 'astro';
import seoBanner from '../../assets/seo-banner.webp';
import GridGradientsAndNoise from '../../components/GridGradientsAndNoise.astro';
import Head from '../../components/Head.astro';
import Header from '../../components/Header.astro';
import Hero from '../../components/Hero.astro';
import RepoCard from '../../components/RepoCard.astro';
import { getCategorizedExamples } from '../../data/examples.js';
import { joinPath } from '../../utils/path.js';
export const getStaticPaths = (async () => {
const examples = await getCategorizedExamples();
return [...examples.entries()].map(([tab]) => ({
params: { tab },
props: { examples, currentExample: tab, basePath: '/repro' },
}));
}) satisfies GetStaticPaths;
const currentExample = Astro.props.currentExample || 'getting-started';
const exampleGroup = Astro.props.examples.get(currentExample);
if (!exampleGroup) {
throw new Error(`No examples found for "${currentExample}"`);
}
// Show minimal repro option first.
if (exampleGroup.slug === 'getting-started') {
exampleGroup.items = exampleGroup.items.toSorted((a, b) =>
a.name === 'minimal' ? -1 : b.name === 'minimal' ? 1 : 0,
);
}
const pathname = Astro.url.pathname.replace(/\/$/, '');
const resolvedSeoBanner = new URL(seoBanner.src, Astro.site).toString();
---

<html lang="en" class="overflow-x-hidden bg-astro-gray-700 text-astro-gray-100">
<head>
<Head
title={`Create a new reproduction: ${exampleGroup.title}`}
description="Quickly create a minimal reproduction for your Astro bug report!"
image={{ src: resolvedSeoBanner, alt: '' }}
canonicalURL={new URL(pathname, `https://astro.new`)}
/>
</head>

<body>
<a
href="#main-heading"
class="sr-only left-2 top-2 z-50 inline-flex justify-center rounded-full border border-astro-gray-100/20 bg-astro-gray-700 font-semibold text-white focus:not-sr-only focus:absolute focus:w-fit focus:px-4 focus:py-2"
>
Skip to content
</a>
<Header />

<div class="noise-container overflow-x-hidden supports-[overflow-x:clip]:overflow-x-clip">
<GridGradientsAndNoise />

<div class="container">
<Hero
title="Let’s get that bug fixed!"
infoBoxTitle="A minimal reproduction is the start of a beautiful journey"
>
<Fragment slot="infobox-content">
<p>
Open any of these templates in StackBlitz to get started creating a minimal
reproduction for your bug report.
</p>
<p>
Want more guidance? Read our guide to <a
class="link underline underline-offset-[3px]"
href="https://docs.astro.build/en/guides/troubleshooting/#creating-minimal-reproductions"
>“Creating minimal reproductions”</a
>.
</p>
</Fragment>
</Hero>
</div>

<main class="container" aria-labelledby="main-heading">
<nav class="flex overflow-auto whitespace-nowrap border-b border-astro-gray-100/20">
{
[...Astro.props.examples.values()].map((group) => (
<a
href={joinPath(Astro.props.basePath, group.slug)}
aria-current={group.slug === currentExample ? 'page' : undefined}
data-astro-prefetch
class="inline-block rounded-t-lg from-astro-blue/50 to-emerald-300/50 px-4 py-2 text-sm transition hover:backdrop-brightness-50 aria-[current]:bg-gradient-to-tr"
>
{group.title}
</a>
))
}
</nav>

<h1 id="main-heading" class="sr-only">{exampleGroup.title}</h1>

<ul class="mb-24 mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3 lg:gap-6">
{
exampleGroup.items.map((example, index) => (
<li>
<RepoCard
recommended={example.name === 'minimal'}
minimal
aboveTheFold={index < 3}
{...example}
/>
</li>
))
}
</ul>
</main>
</div>

<footer
class="container flex flex-col items-center gap-x-8 gap-y-2 border-t border-astro-gray-100/20 p-8 sm:flex-row sm:px-12"
>
<a href="https://astro.build/privacy" class="link text-astro-gray-200"> Privacy Policy</a>
<a href="https://astro.build/terms" class="link text-astro-gray-200"> Terms and Conditions</a>
<address class="not-italic text-astro-gray-200 sm:ml-auto">
MIT License &copy; {new Date().getFullYear()} Astro Contributors
</address>
</footer>

<style>
.container {
@apply mx-auto max-w-screen-xl px-4 md:px-8;
}
.bg-radial-gradient {
background-image: radial-gradient(closest-side, var(--tw-gradient-stops));
}

@media (forced-colors: active) {
a[aria-current='page'] {
background-color: Highlight;
}
}
</style>

<style is:global>
:focus {
outline: none;
}
:focus-visible {
@apply ring-2 ring-astro-purple;
}
</style>

<script>
// find all internal links, this will pickup all redirects handled by the redirect function
document.querySelectorAll<HTMLAnchorElement>("a[href^='/']").forEach((link) => {
link.addEventListener('click', () => {
window.fathom.trackPageview({
url: link.href,
});
});
});

declare global {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Window {
fathom: {
trackPageview: (options: { url: string }) => void;
};
}
}
</script>
</body>
</html>

0 comments on commit 5b3bddc

Please sign in to comment.