Skip to content

Commit 8900812

Browse files
refactor(site): Highlight immutable parameters and do a few tweaks (#6490)
1 parent fe10ba1 commit 8900812

File tree

7 files changed

+346
-351
lines changed

7 files changed

+346
-351
lines changed

site/src/components/HorizontalForm/HorizontalForm.tsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from "components/FormFooter/FormFooter"
66
import { Stack } from "components/Stack/Stack"
77
import { FC, HTMLProps, PropsWithChildren } from "react"
8+
import { combineClasses } from "util/combineClasses"
89

910
export const HorizontalForm: FC<
1011
PropsWithChildren & HTMLProps<HTMLFormElement>
@@ -21,12 +22,16 @@ export const HorizontalForm: FC<
2122
}
2223

2324
export const FormSection: FC<
24-
PropsWithChildren & { title: string; description: string | JSX.Element }
25-
> = ({ children, title, description }) => {
25+
PropsWithChildren & {
26+
title: string
27+
description: string | JSX.Element
28+
className?: string
29+
}
30+
> = ({ children, title, description, className }) => {
2631
const styles = useStyles()
2732

2833
return (
29-
<div className={styles.formSection}>
34+
<div className={combineClasses([styles.formSection, className])}>
3035
<div className={styles.formSectionInfo}>
3136
<h2 className={styles.formSectionInfoTitle}>{title}</h2>
3237
<div className={styles.formSectionInfoDescription}>{description}</div>

site/src/components/RichParameterInput/RichParameterInput.stories.tsx

+71-2
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@ const createTemplateVersionParameter = (
2929
validation_regex: "",
3030
validation_min: 0,
3131
validation_max: 0,
32-
validation_monotonic: "",
33-
32+
validation_monotonic: "increasing",
33+
description_plaintext: "",
3434
...partial,
3535
}
3636
}
3737

3838
export const Basic = Template.bind({})
3939
Basic.args = {
4040
initialValue: "initial-value",
41+
id: "project_name",
4142
parameter: createTemplateVersionParameter({
4243
name: "project_name",
4344
description:
@@ -48,6 +49,7 @@ Basic.args = {
4849
export const NumberType = Template.bind({})
4950
NumberType.args = {
5051
initialValue: "4",
52+
id: "number_parameter",
5153
parameter: createTemplateVersionParameter({
5254
name: "number_parameter",
5355
type: "number",
@@ -58,6 +60,7 @@ NumberType.args = {
5860
export const BooleanType = Template.bind({})
5961
BooleanType.args = {
6062
initialValue: "false",
63+
id: "bool_parameter",
6164
parameter: createTemplateVersionParameter({
6265
name: "bool_parameter",
6366
type: "bool",
@@ -68,6 +71,7 @@ BooleanType.args = {
6871
export const OptionsType = Template.bind({})
6972
OptionsType.args = {
7073
initialValue: "first_option",
74+
id: "options_parameter",
7175
parameter: createTemplateVersionParameter({
7276
name: "options_parameter",
7377
type: "string",
@@ -94,3 +98,68 @@ OptionsType.args = {
9498
],
9599
}),
96100
}
101+
102+
export const IconLabel = Template.bind({})
103+
IconLabel.args = {
104+
initialValue: "initial-value",
105+
id: "project_name",
106+
parameter: createTemplateVersionParameter({
107+
name: "project_name",
108+
description:
109+
"Customize the name of a Google Cloud project that will be created!",
110+
icon: "/emojis/1f30e.png",
111+
}),
112+
}
113+
114+
export const NoDescription = Template.bind({})
115+
NoDescription.args = {
116+
initialValue: "",
117+
id: "region",
118+
parameter: createTemplateVersionParameter({
119+
name: "Region",
120+
description: "",
121+
description_plaintext: "",
122+
type: "string",
123+
mutable: false,
124+
default_value: "",
125+
icon: "/emojis/1f30e.png",
126+
options: [
127+
{
128+
name: "Pittsburgh",
129+
description: "",
130+
value: "us-pittsburgh",
131+
icon: "/emojis/1f1fa-1f1f8.png",
132+
},
133+
{
134+
name: "Helsinki",
135+
description: "",
136+
value: "eu-helsinki",
137+
icon: "/emojis/1f1eb-1f1ee.png",
138+
},
139+
{
140+
name: "Sydney",
141+
description: "",
142+
value: "ap-sydney",
143+
icon: "/emojis/1f1e6-1f1fa.png",
144+
},
145+
],
146+
}),
147+
}
148+
149+
export const DescriptionWithLinks = Template.bind({})
150+
DescriptionWithLinks.args = {
151+
initialValue: "",
152+
id: "coder-repository-directory",
153+
parameter: createTemplateVersionParameter({
154+
name: "Coder Repository Directory",
155+
description:
156+
"The directory specified will be created and [coder/coder](https://github.com/coder/coder) will be automatically cloned into it 🪄.",
157+
description_plaintext:
158+
"The directory specified will be created and coder/coder (https://github.com/coder/coder) will be automatically cloned into it 🪄.",
159+
type: "string",
160+
mutable: true,
161+
default_value: "~/coder",
162+
icon: "",
163+
options: [],
164+
}),
165+
}

site/src/components/RichParameterInput/RichParameterInput.tsx

+51-51
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import FormControlLabel from "@material-ui/core/FormControlLabel"
22
import Radio from "@material-ui/core/Radio"
33
import RadioGroup from "@material-ui/core/RadioGroup"
44
import { makeStyles } from "@material-ui/core/styles"
5-
import TextField from "@material-ui/core/TextField"
5+
import TextField, { TextFieldProps } from "@material-ui/core/TextField"
66
import { Stack } from "components/Stack/Stack"
77
import { FC, useState } from "react"
88
import { TemplateVersionParameter } from "../../api/typesGenerated"
@@ -14,54 +14,48 @@ const isBoolean = (parameter: TemplateVersionParameter) => {
1414
}
1515

1616
export interface ParameterLabelProps {
17-
index: number
17+
id: string
1818
parameter: TemplateVersionParameter
1919
}
2020

21-
const ParameterLabel: FC<ParameterLabelProps> = ({ index, parameter }) => {
21+
const ParameterLabel: FC<ParameterLabelProps> = ({ id, parameter }) => {
2222
const styles = useStyles()
23+
const hasDescription = parameter.description && parameter.description !== ""
2324

2425
return (
25-
<span>
26-
<span className={styles.labelNameWithIcon}>
26+
<label htmlFor={id}>
27+
<Stack direction="row" alignItems="center">
2728
{parameter.icon && (
28-
<span className={styles.iconWrapper}>
29+
<span className={styles.labelIconWrapper}>
2930
<img
30-
className={styles.icon}
31+
className={styles.labelIcon}
3132
alt="Parameter icon"
3233
src={parameter.icon}
33-
style={{
34-
pointerEvents: "none",
35-
}}
3634
/>
3735
</span>
3836
)}
39-
<span className={styles.labelName}>
40-
<label htmlFor={`rich_parameter_values[${index}].value`}>
41-
{parameter.name}
42-
</label>
43-
</span>
44-
</span>
45-
{parameter.description && (
46-
<span className={styles.labelDescription}>
47-
<MemoizedMarkdown>{parameter.description}</MemoizedMarkdown>
48-
</span>
49-
)}
50-
{!parameter.mutable && (
51-
<div className={styles.labelImmutable}>
52-
This parameter cannot be changed after creating workspace.
53-
</div>
54-
)}
55-
</span>
37+
38+
{hasDescription ? (
39+
<Stack spacing={0.5}>
40+
<span className={styles.labelCaption}>{parameter.name}</span>
41+
<span className={styles.labelPrimary}>
42+
<MemoizedMarkdown>{parameter.description}</MemoizedMarkdown>
43+
</span>
44+
</Stack>
45+
) : (
46+
<span className={styles.labelPrimary}>{parameter.name}</span>
47+
)}
48+
</Stack>
49+
</label>
5650
)
5751
}
5852

59-
export interface RichParameterInputProps {
53+
export type RichParameterInputProps = TextFieldProps & {
6054
index: number
61-
disabled?: boolean
6255
parameter: TemplateVersionParameter
6356
onChange: (value: string) => void
6457
initialValue?: string
58+
id: string
6559
}
6660

6761
export const RichParameterInput: FC<RichParameterInputProps> = ({
@@ -70,16 +64,16 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
7064
onChange,
7165
parameter,
7266
initialValue,
73-
...props
67+
...fieldProps
7468
}) => {
7569
const styles = useStyles()
7670

7771
return (
7872
<Stack direction="column" spacing={0.75}>
79-
<ParameterLabel index={index} parameter={parameter} />
73+
<ParameterLabel id={fieldProps.id} parameter={parameter} />
8074
<div className={styles.input}>
8175
<RichParameterField
82-
{...props}
76+
{...fieldProps}
8377
index={index}
8478
disabled={disabled}
8579
onChange={onChange}
@@ -140,7 +134,7 @@ const RichParameterField: React.FC<RichParameterInputProps> = ({
140134
value={option.value}
141135
control={<Radio color="primary" size="small" disableRipple />}
142136
label={
143-
<span>
137+
<span className={styles.radioOption}>
144138
{option.icon && (
145139
<img
146140
className={styles.optionIcon}
@@ -180,24 +174,25 @@ const RichParameterField: React.FC<RichParameterInputProps> = ({
180174
)
181175
}
182176

183-
const iconSize = 20
184-
const optionIconSize = 24
177+
const optionIconSize = 20
185178

186179
const useStyles = makeStyles((theme) => ({
187-
labelName: {
180+
label: {
181+
marginBottom: theme.spacing(0.5),
182+
},
183+
labelCaption: {
188184
fontSize: 14,
189185
color: theme.palette.text.secondary,
190-
display: "block",
191-
marginBottom: theme.spacing(1.0),
192186
},
193-
labelNameWithIcon: {
194-
marginBottom: theme.spacing(0.5),
195-
},
196-
labelDescription: {
187+
labelPrimary: {
197188
fontSize: 16,
198189
color: theme.palette.text.primary,
199-
display: "block",
200190
fontWeight: 600,
191+
192+
"& p": {
193+
margin: 0,
194+
lineHeight: "20px", // Keep the same as ParameterInput
195+
},
201196
},
202197
labelImmutable: {
203198
marginTop: theme.spacing(0.5),
@@ -213,18 +208,23 @@ const useStyles = makeStyles((theme) => ({
213208
alignItems: "center",
214209
gap: theme.spacing(1),
215210
},
216-
iconWrapper: {
217-
float: "left",
211+
labelIconWrapper: {
212+
width: theme.spacing(2.5),
213+
height: theme.spacing(2.5),
214+
display: "block",
218215
},
219-
icon: {
220-
maxHeight: iconSize,
221-
width: iconSize,
222-
marginRight: theme.spacing(1.0),
216+
labelIcon: {
217+
width: "100%",
218+
height: "100%",
219+
objectFit: "contain",
220+
},
221+
radioOption: {
222+
display: "flex",
223+
alignItems: "center",
224+
gap: theme.spacing(1.5),
223225
},
224226
optionIcon: {
225227
maxHeight: optionIconSize,
226228
width: optionIconSize,
227-
marginRight: theme.spacing(1.0),
228-
float: "left",
229229
},
230230
}))

site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ describe("CreateWorkspacePage", () => {
179179

180180
const secondParameterField = await screen.findByLabelText(
181181
MockTemplateVersionParameter2.name,
182+
{ exact: false },
182183
)
183184
expect(secondParameterField).toBeDefined()
184185

@@ -212,6 +213,7 @@ describe("CreateWorkspacePage", () => {
212213

213214
const thirdParameterField = await screen.findByLabelText(
214215
MockTemplateVersionParameter3.name,
216+
{ exact: false },
215217
)
216218
expect(thirdParameterField).toBeDefined()
217219
fireEvent.change(thirdParameterField, {

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx

+29
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,35 @@ RichParameters.args = {
133133
MockTemplateVersionParameter1,
134134
MockTemplateVersionParameter2,
135135
MockTemplateVersionParameter3,
136+
{
137+
name: "Region",
138+
description: "",
139+
description_plaintext: "",
140+
type: "string",
141+
mutable: false,
142+
default_value: "",
143+
icon: "/emojis/1f30e.png",
144+
options: [
145+
{
146+
name: "Pittsburgh",
147+
description: "",
148+
value: "us-pittsburgh",
149+
icon: "/emojis/1f1fa-1f1f8.png",
150+
},
151+
{
152+
name: "Helsinki",
153+
description: "",
154+
value: "eu-helsinki",
155+
icon: "/emojis/1f1eb-1f1ee.png",
156+
},
157+
{
158+
name: "Sydney",
159+
description: "",
160+
value: "ap-sydney",
161+
icon: "/emojis/1f1e6-1f1fa.png",
162+
},
163+
],
164+
},
136165
],
137166
createWorkspaceErrors: {},
138167
}

0 commit comments

Comments
 (0)