feat: add beta labels for dynamic params (#17985)

<img width="820" alt="Screenshot 2025-05-23 at 18 48 56"
src="https://github.com/user-attachments/assets/5b781501-3817-4be1-8143-f03f8cb88901"
/>

<img width="790" alt="Screenshot 2025-05-23 at 18 48 32"
src="https://github.com/user-attachments/assets/541ad77e-fd37-4f52-ae2c-7b1f698c23fc"
/>
This commit is contained in:
Jaayden Halko
2025-05-23 15:51:31 -04:00
committed by GitHub
parent ce4c8c7451
commit 196eccb457
4 changed files with 102 additions and 16 deletions
@@ -18,6 +18,7 @@ export const featureStageBadgeTypes = {
type FeatureStageBadgeProps = Readonly<
Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
contentType: keyof typeof featureStageBadgeTypes;
labelText?: string;
size?: "sm" | "md" | "lg";
showTooltip?: boolean;
}
@@ -25,6 +26,7 @@ type FeatureStageBadgeProps = Readonly<
export const FeatureStageBadge: FC<FeatureStageBadgeProps> = ({
contentType,
labelText = "",
size = "md",
showTooltip = true, // This is a temporary until the deprecated popover is removed
...delegatedProps
@@ -43,7 +45,8 @@ export const FeatureStageBadge: FC<FeatureStageBadgeProps> = ({
{...delegatedProps}
>
<span style={visuallyHidden}> (This is a</span>
<span css={styles.badgeLabel}>
<span className="first-letter:uppercase">
{labelText && `${labelText} `}
{featureStageBadgeTypes[contentType]}
</span>
<span style={visuallyHidden}> feature)</span>
@@ -105,13 +108,6 @@ const styles = {
backgroundColor: theme.branding.featureStage.hover.background,
}),
badgeLabel: {
// Have to set display mode to anything other than inline, or else the
// CSS capitalization algorithm won't capitalize the element
display: "inline-block",
textTransform: "capitalize",
},
badgeLargeText: {
fontSize: "1rem",
},
@@ -7,6 +7,7 @@ import { Button } from "components/Button/Button";
import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge";
import { Input } from "components/Input/Input";
import { Label } from "components/Label/Label";
import { Link } from "components/Link/Link";
import { Pill } from "components/Pill/Pill";
import {
Select,
@@ -17,9 +18,21 @@ import {
} from "components/Select/Select";
import { Spinner } from "components/Spinner/Spinner";
import { Switch } from "components/Switch/Switch";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
import { type FormikContextType, useFormik } from "formik";
import { ArrowLeft, CircleAlert, TriangleAlert } from "lucide-react";
import {
ArrowLeft,
CircleAlert,
CircleHelp,
TriangleAlert,
Undo2,
} from "lucide-react";
import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters";
import {
DynamicParameter,
@@ -36,6 +49,7 @@ import {
useRef,
useState,
} from "react";
import { docs } from "utils/docs";
import { nameValidator } from "utils/formUtils";
import type { AutofillBuildParameter } from "utils/richParameters";
import * as Yup from "yup";
@@ -337,7 +351,7 @@ export const CreateWorkspacePageViewExperimental: FC<
</button>
</div>
<div className="flex flex-col gap-6 max-w-screen-md mx-auto">
<header className="flex flex-col items-start gap-2 mt-10">
<header className="flex flex-col items-start gap-3 mt-10">
<div className="flex items-center gap-2">
<Avatar
variant="icon"
@@ -351,17 +365,45 @@ export const CreateWorkspacePageViewExperimental: FC<
: template.name}
</p>
</div>
<h1 className="text-3xl font-semibold m-0">New workspace</h1>
<span className="flex flex-row items-center gap-2">
<h1 className="text-3xl font-semibold m-0">New workspace</h1>
<FeatureStageBadge
className="mt-1"
contentType={"beta"}
labelText="Dynamic parameters"
/>
<TooltipProvider delayDuration={100}>
<Tooltip>
<TooltipTrigger asChild>
<CircleHelp className="size-icon-xs text-content-secondary" />
</TooltipTrigger>
<TooltipContent className="max-w-xs text-sm">
Dynamic Parameters enhances Coder's existing parameter system
with real-time validation, conditional parameter behavior, and
richer input types.
<br />
<Link
href={docs(
"/admin/templates/extending-templates/parameters#enable-dynamic-parameters-early-access",
)}
>
View docs
</Link>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</span>
{template.deprecated && <Pill type="warning">Deprecated</Pill>}
{experimentalFormContext && (
<Button
size="sm"
variant="subtle"
variant="outline"
onClick={experimentalFormContext.toggleOptedOut}
>
Go back to the classic workspace creation flow
<Undo2 />
Use the classic workspace creation flow
</Button>
)}
</header>
@@ -501,6 +543,13 @@ export const CreateWorkspacePageViewExperimental: FC<
<p className="text-sm text-content-secondary m-0">
These are the settings used by your template. Immutable
parameters cannot be modified once the workspace is created.
<Link
href={docs(
"/admin/templates/extending-templates/parameters#enable-dynamic-parameters-early-access",
)}
>
View docs
</Link>
</p>
</hgroup>
{diagnostics.length > 0 && (
@@ -12,7 +12,14 @@ import { EmptyState } from "components/EmptyState/EmptyState";
import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge";
import { Link } from "components/Link/Link";
import { Loader } from "components/Loader/Loader";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import { useEffectEvent } from "hooks/hookPolyfills";
import { CircleHelp, Undo2 } from "lucide-react";
import type { FC } from "react";
import {
useCallback,
@@ -161,7 +168,7 @@ const WorkspaceParametersPageExperimental: FC = () => {
}
return (
<div className="flex flex-col gap-6 max-w-screen-md mx-auto">
<div className="flex flex-col gap-6 max-w-screen-md">
<Helmet>
<title>{pageTitle(workspace.name, "Parameters")}</title>
</Helmet>
@@ -169,7 +176,31 @@ const WorkspaceParametersPageExperimental: FC = () => {
<header className="flex flex-col items-start gap-2">
<span className="flex flex-row items-center gap-2">
<h1 className="text-3xl m-0">Workspace parameters</h1>
<FeatureStageBadge contentType={"beta"} />
<FeatureStageBadge
className="mt-1"
contentType={"beta"}
labelText="Dynamic parameters"
/>
<TooltipProvider delayDuration={100}>
<Tooltip>
<TooltipTrigger asChild>
<CircleHelp className="size-icon-xs text-content-secondary" />
</TooltipTrigger>
<TooltipContent className="max-w-xs text-sm">
Dynamic Parameters enhances Coder's existing parameter system
with real-time validation, conditional parameter behavior, and
richer input types.
<br />
<Link
href={docs(
"/admin/templates/extending-templates/parameters#enable-dynamic-parameters-early-access",
)}
>
View docs
</Link>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</span>
{experimentalFormContext && (
<Button
@@ -177,7 +208,8 @@ const WorkspaceParametersPageExperimental: FC = () => {
variant="outline"
onClick={experimentalFormContext.toggleOptedOut}
>
Go back to the classic workspace parameters view
<Undo2 />
Use the classic workspace parameters
</Button>
)}
</header>
@@ -5,6 +5,7 @@ import type {
} from "api/typesGenerated";
import { Alert } from "components/Alert/Alert";
import { Button } from "components/Button/Button";
import { Link } from "components/Link/Link";
import { Spinner } from "components/Spinner/Spinner";
import { useFormik } from "formik";
import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters";
@@ -14,6 +15,7 @@ import {
useValidationSchemaForDynamicParameters,
} from "modules/workspaces/DynamicParameter/DynamicParameter";
import type { FC } from "react";
import { docs } from "utils/docs";
export type WorkspaceParametersPageViewExperimentalProps = {
workspace: Workspace;
parameters: PreviewParameter[];
@@ -139,6 +141,13 @@ export const WorkspaceParametersPageViewExperimental: FC<
<p className="text-sm text-content-secondary m-0">
These are the settings used by your template. Immutable
parameters cannot be modified once the workspace is created.
<Link
href={docs(
"/admin/templates/extending-templates/parameters#enable-dynamic-parameters-early-access",
)}
>
View docs
</Link>
</p>
</hgroup>
{standardParameters.map((parameter, index) => {