feat(site): add official badge to TemplateCard and ModuleCard (#26806)

Adds an `official` prop to both `TemplateCard` and `ModuleCard` in the
TemplateBuilder. When true (the default), a `BadgeCheckIcon` from
lucide-react is rendered inline next to the card name.

- `official` defaults to `true` since all current templates/modules are
official
- Pass `official={false}` for community entries to hide the badge
- Added `Community` and `CommunitySelected` stories for both components

> Generated by Coder Agents on behalf of @jeremyruppel

<img width="678" height="262" alt="Screenshot 2026-06-29 at 9 38 44 AM"
src="https://github.com/user-attachments/assets/51d1ddad-2bae-4ec3-a1bb-e518c86fa50c"
/>
This commit is contained in:
Jeremy Ruppel
2026-06-29 18:25:03 -04:00
committed by GitHub
parent 7daf3123cb
commit 431219a5e7
4 changed files with 60 additions and 3 deletions
@@ -39,6 +39,26 @@ export const NoIcon: Story = {
},
};
export const Community: Story = {
args: {
name: "Docker Containers",
description: "Provision Docker containers as Coder workspaces.",
iconUrl: "/icon/docker.svg",
official: false,
selected: false,
},
};
export const CommunitySelected: Story = {
args: {
name: "Docker Containers",
description: "Provision Docker containers as Coder workspaces.",
iconUrl: "/icon/docker.svg",
official: false,
selected: true,
},
};
export const LongDescription: Story = {
args: {
name: "Kubernetes Pods",
+10 -2
View File
@@ -1,4 +1,4 @@
import { CheckIcon } from "lucide-react";
import { BadgeCheckIcon, CheckIcon } from "lucide-react";
import { useId } from "react";
import { Link } from "#/components/Link/Link";
import { cn } from "#/utils/cn";
@@ -8,6 +8,7 @@ type ModuleCardProps = {
description: string;
iconUrl?: string;
detailsUrl?: string;
official?: boolean;
selected?: boolean;
onSelect?: () => void;
};
@@ -17,6 +18,7 @@ export const ModuleCard: React.FC<ModuleCardProps> = ({
description,
iconUrl,
detailsUrl,
official = true,
selected = false,
onSelect,
}) => {
@@ -65,8 +67,14 @@ export const ModuleCard: React.FC<ModuleCardProps> = ({
</div>
<div>
<h3 id={nameId} className="text-md font-semibold text-content-primary">
<h3
id={nameId}
className="flex items-center gap-1.5 text-md font-semibold text-content-primary"
>
{name}
{official && (
<BadgeCheckIcon className="size-4 text-highlight-sky shrink-0" />
)}
</h3>
<p className="text-sm font-normal text-content-secondary">
{description}
@@ -40,6 +40,26 @@ export const NoIcon: Story = {
},
};
export const Community: Story = {
args: {
name: "Docker Containers",
description: "Provision Docker containers as Coder workspaces.",
iconUrl: "/icon/docker.svg",
official: false,
selected: false,
},
};
export const CommunitySelected: Story = {
args: {
name: "Docker Containers",
description: "Provision Docker containers as Coder workspaces.",
iconUrl: "/icon/docker.svg",
official: false,
selected: true,
},
};
export const LongDescription: Story = {
args: {
name: "Kubernetes Pods",
@@ -1,3 +1,4 @@
import { BadgeCheckIcon } from "lucide-react";
import { useId } from "react";
import { Link } from "#/components/Link/Link";
import { cn } from "#/utils/cn";
@@ -7,6 +8,7 @@ type TemplateCardProps = {
description: string;
iconUrl?: string;
detailsUrl: string;
official?: boolean;
selected?: boolean;
onSelect?: () => void;
};
@@ -16,6 +18,7 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
description,
iconUrl,
detailsUrl,
official = true,
selected = false,
onSelect,
}) => {
@@ -63,8 +66,14 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
</div>
<div>
<h3 id={nameId} className="text-md font-semibold text-content-primary">
<h3
id={nameId}
className="flex items-center gap-1.5 text-md font-semibold text-content-primary"
>
{name}
{official && (
<BadgeCheckIcon className="size-4 text-highlight-sky shrink-0" />
)}
</h3>
<div>
<p className="text-sm font-normal text-content-secondary">