diff --git a/site/src/components/Conditionals/ChooseOne.stories.tsx b/site/src/components/Conditionals/ChooseOne.stories.tsx index f2fc75fd43379..a6c1bf8483c3f 100644 --- a/site/src/components/Conditionals/ChooseOne.stories.tsx +++ b/site/src/components/Conditionals/ChooseOne.stories.tsx @@ -11,6 +11,7 @@ export const FirstIsTrue: Story = () => ( The first one shows. The second one does not show. + The default does not show. ) @@ -18,6 +19,7 @@ export const SecondIsTrue: Story = () => ( The first one does not show. The second one shows. + The default does not show. ) @@ -25,12 +27,20 @@ export const AllAreTrue: Story = () => ( Only the first one shows. The second one does not show. + The default does not show. ) export const NoneAreTrue: Story = () => ( The first one does not show. - The second shows because it is the fallback. + The second one does not show. + The default shows. + +) + +export const OneCond: Story = () => ( + + An only child renders. ) diff --git a/site/src/components/Conditionals/ChooseOne.tsx b/site/src/components/Conditionals/ChooseOne.tsx index 71b28d95db84a..4eca8130bb33d 100644 --- a/site/src/components/Conditionals/ChooseOne.tsx +++ b/site/src/components/Conditionals/ChooseOne.tsx @@ -1,18 +1,17 @@ import { Children, PropsWithChildren } from "react" export interface CondProps { - condition: boolean + condition?: boolean } /** * Wrapper component that attaches a condition to a child component so that ChooseOne can - * determine which child to render. The last Cond in a ChooseOne is the fallback case; set - * its `condition` to `true` to avoid confusion. - * @param condition boolean expression indicating whether the child should be rendered + * determine which child to render. The last Cond in a ChooseOne is the fallback case and + * should not have a condition. + * @param condition boolean expression indicating whether the child should be rendered, or undefined * @returns child. Note that Cond alone does not enforce the condition; it should be used inside ChooseOne. */ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export const Cond = ({ children, condition }: PropsWithChildren): JSX.Element => { +export const Cond = ({ children }: PropsWithChildren): JSX.Element => { return <>{children} } @@ -20,10 +19,24 @@ export const Cond = ({ children, condition }: PropsWithChildren): JSX * Wrapper component for rendering exactly one of its children. Wrap each child in Cond to associate it * with a condition under which it should be rendered. If no conditions are met, the final child * will be rendered. - * @returns one of its children + * @returns one of its children, or null if there are no children + * @throws an error if its last child has a condition prop, or any non-final children do not have a condition prop */ -export const ChooseOne = ({ children }: PropsWithChildren): JSX.Element => { +export const ChooseOne = ({ children }: PropsWithChildren): JSX.Element | null => { const childArray = Children.toArray(children) as JSX.Element[] - const chosen = childArray.find((child) => child.props.condition) - return chosen ?? childArray[childArray.length - 1] + if (childArray.length === 0) { + return null + } + const conditionedOptions = childArray.slice(0, childArray.length - 1) + const defaultCase = childArray[childArray.length - 1] + if (defaultCase.props.condition !== undefined) { + throw new Error( + "The last Cond in a ChooseOne was given a condition prop, but it is the default case.", + ) + } + if (conditionedOptions.some((cond) => cond.props.condition === undefined)) { + throw new Error("A non-final Cond in a ChooseOne does not have a condition prop.") + } + const chosen = conditionedOptions.find((child) => child.props.condition) + return chosen ?? defaultCase } diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index 64a3518a80871..af2d3e9de6fcd 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -139,7 +139,7 @@ export const TemplatesPageView: FC - + @@ -173,7 +173,7 @@ export const TemplatesPageView: FC - + {props.templates?.map((template) => { const templatePageLink = `/templates/${template.name}` const hasIcon = template.icon && template.icon !== ""