mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
feat(site/src/pages/TemplateBuilder): add alternatives box to base template step (#26878)
Adds an "Alternatives to create a template" section below the navigation controls on the base infrastructure selection step of the Template Builder wizard. The box is only shown on the first step and contains four outline buttons linking to other template creation paths: - **Start from scratch** -> Coder docs tutorial (external) - **Upload an existing template** -> `/starter-templates` (internal) - **Browse community templates** -> Registry templates (external) - **Use template agent skill** -> Registry skills (external) External links open in a new tab with an external-link icon. Closes [DEVEX-564](https://linear.app/codercom/issue/DEVEX-564) > [!NOTE] > This PR was authored by Coder Agents on behalf of @jeremyruppel. <details> <summary>Implementation plan</summary> ### 1. `TemplateAlternatives.tsx` (new) - Presentational component rendering a bordered container with label and four `Button` components (variant `outline`, size `sm`) - External links use `ExternalLinkIcon` from lucide-react and open in `_blank` - Internal link uses React Router `Link` ### 2. `TemplateBuilderPageView.tsx` (modified) - Import and render `<TemplateAlternatives />` below navigation controls, conditionally when `currentStep.id === "base-infra"` ### 3. `TemplateAlternatives.stories.tsx` (new) - Default Storybook story for the component </details>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { TemplateAlternatives } from "./TemplateAlternatives";
|
||||
|
||||
const meta: Meta<typeof TemplateAlternatives> = {
|
||||
title: "pages/TemplateBuilder/TemplateAlternatives",
|
||||
component: TemplateAlternatives,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof TemplateAlternatives>;
|
||||
|
||||
export const Default: Story = {};
|
||||
@@ -0,0 +1,59 @@
|
||||
import { ExternalLinkIcon } from "lucide-react";
|
||||
import type { FC } from "react";
|
||||
import { Link } from "react-router";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
|
||||
interface AlternativeLink {
|
||||
label: string;
|
||||
href: string;
|
||||
external: boolean;
|
||||
}
|
||||
|
||||
const alternatives: readonly AlternativeLink[] = [
|
||||
{
|
||||
label: "Start from scratch",
|
||||
href: "https://coder.com/docs/tutorials/template-from-scratch",
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
label: "Upload an existing template",
|
||||
href: "/starter-templates",
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
label: "Browse community templates",
|
||||
href: "https://registry.coder.com/templates",
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
label: "Use template agent skill",
|
||||
href: "https://registry.coder.com/skills",
|
||||
external: true,
|
||||
},
|
||||
];
|
||||
|
||||
export const TemplateAlternatives: FC = () => {
|
||||
return (
|
||||
<div className="p-6 border border-solid rounded-lg mt-6">
|
||||
<p className="text-sm text-content-secondary mb-4">
|
||||
Alternatives to create a template:
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{alternatives.map((alt) =>
|
||||
alt.external ? (
|
||||
<Button key={alt.label} variant="outline" size="sm" asChild>
|
||||
<a href={alt.href} target="_blank" rel="noreferrer">
|
||||
{alt.label}
|
||||
<ExternalLinkIcon />
|
||||
</a>
|
||||
</Button>
|
||||
) : (
|
||||
<Button key={alt.label} variant="outline" size="sm" asChild>
|
||||
<Link to={alt.href}>{alt.label}</Link>
|
||||
</Button>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
type StepId,
|
||||
WIZARD_STEPS,
|
||||
} from "./steps";
|
||||
import { TemplateAlternatives } from "./TemplateAlternatives";
|
||||
import { TemplateCustomizationsStep } from "./TemplateCustomizationsStep";
|
||||
import {
|
||||
initialWizardState,
|
||||
@@ -152,6 +153,8 @@ export const TemplateBuilderPageView: FC<TemplateBuilderPageViewProps> = ({
|
||||
{isLastStep ? "Create Template" : "Continue"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{currentStep.id === "base-infra" && <TemplateAlternatives />}
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
|
||||
Reference in New Issue
Block a user