From 431219a5e7b5a545677f02b9847dbb36b27e971b Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Mon, 29 Jun 2026 18:25:03 -0400 Subject: [PATCH] feat(site): add official badge to TemplateCard and ModuleCard (#26806) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Screenshot 2026-06-29 at 9 38 44 AM --- .../TemplateBuilder/ModuleCard.stories.tsx | 20 +++++++++++++++++++ site/src/pages/TemplateBuilder/ModuleCard.tsx | 12 +++++++++-- .../TemplateBuilder/TemplateCard.stories.tsx | 20 +++++++++++++++++++ .../pages/TemplateBuilder/TemplateCard.tsx | 11 +++++++++- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/site/src/pages/TemplateBuilder/ModuleCard.stories.tsx b/site/src/pages/TemplateBuilder/ModuleCard.stories.tsx index 7012ed25e6..084909b158 100644 --- a/site/src/pages/TemplateBuilder/ModuleCard.stories.tsx +++ b/site/src/pages/TemplateBuilder/ModuleCard.stories.tsx @@ -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", diff --git a/site/src/pages/TemplateBuilder/ModuleCard.tsx b/site/src/pages/TemplateBuilder/ModuleCard.tsx index dcbce79217..a1199b90d1 100644 --- a/site/src/pages/TemplateBuilder/ModuleCard.tsx +++ b/site/src/pages/TemplateBuilder/ModuleCard.tsx @@ -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 = ({ description, iconUrl, detailsUrl, + official = true, selected = false, onSelect, }) => { @@ -65,8 +67,14 @@ export const ModuleCard: React.FC = ({
-

+

{name} + {official && ( + + )}

{description} diff --git a/site/src/pages/TemplateBuilder/TemplateCard.stories.tsx b/site/src/pages/TemplateBuilder/TemplateCard.stories.tsx index 77ecebec4d..3d56a941dc 100644 --- a/site/src/pages/TemplateBuilder/TemplateCard.stories.tsx +++ b/site/src/pages/TemplateBuilder/TemplateCard.stories.tsx @@ -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", diff --git a/site/src/pages/TemplateBuilder/TemplateCard.tsx b/site/src/pages/TemplateBuilder/TemplateCard.tsx index 74b0992352..5650a3358b 100644 --- a/site/src/pages/TemplateBuilder/TemplateCard.tsx +++ b/site/src/pages/TemplateBuilder/TemplateCard.tsx @@ -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 = ({ description, iconUrl, detailsUrl, + official = true, selected = false, onSelect, }) => { @@ -63,8 +66,14 @@ export const TemplateCard: React.FC = ({

-

+

{name} + {official && ( + + )}