Skip to content

Commit 119770e

Browse files
Migrate checkbox component (#17171)
* Migrate all checkbox inputs to the `CheckBoxInput` component (#16813) * [dashboard] migrate to CheckBoxInput (#16768) * [dashboard] remove CheckBox comp usage * [dashboard] remove `CheckBox` on team settings * [dashboard] remove border on checkbox click state * [dashboard] refactor code for `CheckboxInput` * removing values on checkboxes that don't need it * adjusting api a bit * simplify a bit by always setting value --------- Co-authored-by: Devansu Yadav <[email protected]>
1 parent 27979c9 commit 119770e

File tree

13 files changed

+191
-178
lines changed

13 files changed

+191
-178
lines changed

components/dashboard/src/admin/BlockedRepositories.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { AdminPageHeader } from "./AdminPageHeader";
1111
import { BlockedRepository } from "@gitpod/gitpod-protocol/lib/blocked-repositories-protocol";
1212
import ConfirmationModal from "../components/ConfirmationModal";
1313
import Modal from "../components/Modal";
14-
import CheckBox from "../components/CheckBox";
14+
import { CheckboxInputField } from "../components/forms/CheckboxInputField";
1515
import { ItemFieldContextMenu } from "../components/ItemsList";
1616
import { ContextMenuEntry } from "../components/ContextMenu";
1717
import Alert from "../components/Alert";
@@ -299,14 +299,15 @@ function Details(props: {
299299
}}
300300
/>
301301
</div>
302-
<CheckBox
303-
title={"Block Users"}
304-
desc={"Block any user that tries to open a workspace for a repository URL that matches this RegEx."}
302+
303+
<CheckboxInputField
304+
label="Block Users"
305+
hint="Block any user that tries to open a workspace for a repository URL that matches this RegEx."
305306
checked={props.br.blockUser}
306307
disabled={!props.update}
307-
onChange={(v) => {
308+
onChange={(checked) => {
308309
if (!!props.update) {
309-
props.update({ blockUser: v.target.checked });
310+
props.update({ blockUser: checked });
310311
}
311312
}}
312313
/>

components/dashboard/src/admin/Settings.tsx

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import React, { useContext } from "react";
88
import { TelemetryData, InstallationAdminSettings } from "@gitpod/gitpod-protocol";
99
import { AdminContext } from "../admin-context";
10-
import CheckBox from "../components/CheckBox";
10+
import { CheckboxInputField } from "../components/forms/CheckboxInputField";
1111
import { getGitpodService } from "../service/service";
1212
import { useEffect, useState } from "react";
1313
import InfoBox from "../components/InfoBox";
@@ -65,34 +65,27 @@ export default function Settings() {
6565
Read our Privacy Policy
6666
</a>
6767
</p>
68-
<CheckBox
69-
title="Enable usage telemetry"
70-
desc={
71-
<span>
72-
Enable usage telemetry on your Gitpod instance. A preview of your telemetry is available
73-
below.
74-
</span>
75-
}
68+
<CheckboxInputField
69+
label="Enable usage telemetry"
70+
hint="Enable usage telemetry on your Gitpod instance. A preview of your telemetry is available
71+
below."
7672
checked={adminSettings?.sendTelemetry ?? false}
77-
onChange={(evt) =>
73+
onChange={(checked) =>
7874
actuallySetTelemetryPrefs({
7975
...adminSettings,
80-
sendTelemetry: evt.target.checked,
76+
sendTelemetry: checked,
8177
} as InstallationAdminSettings)
8278
}
8379
/>
84-
<CheckBox
85-
title="Include customer ID in telemetry"
86-
desc={
87-
<span>
88-
Include an optional customer ID in usage telemetry to provide individualized support.
89-
</span>
90-
}
80+
81+
<CheckboxInputField
82+
label="Include customer ID in telemetry"
83+
hint="Include an optional customer ID in usage telemetry to provide individualized support."
9184
checked={adminSettings?.sendCustomerID ?? false}
92-
onChange={(evt) =>
85+
onChange={(checked) =>
9386
actuallySetTelemetryPrefs({
9487
...adminSettings,
95-
sendCustomerID: evt.target.checked,
88+
sendCustomerID: checked,
9689
} as InstallationAdminSettings)
9790
}
9891
/>

components/dashboard/src/admin/UserDetail.tsx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { AccountStatement, Subscription } from "@gitpod/gitpod-protocol/lib/acco
1616
import { Plans } from "@gitpod/gitpod-protocol/lib/plans";
1717
import dayjs from "dayjs";
1818
import { useEffect, useRef, useState } from "react";
19-
import CheckBox from "../components/CheckBox";
2019
import Modal from "../components/Modal";
2120
import { getGitpodService } from "../service/service";
2221
import { WorkspaceSearch } from "./WorkspacesSearch";
@@ -26,6 +25,7 @@ import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode";
2625
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution";
2726
import CaretDown from "../icons/CaretDown.svg";
2827
import ContextMenu from "../components/ContextMenu";
28+
import { CheckboxInputField, CheckboxListField } from "../components/forms/CheckboxInputField";
2929
import { CostCenterJSON, CostCenter_BillingStrategy } from "@gitpod/gitpod-protocol/lib/usage";
3030
import { Heading2, Subheading } from "../components/typography/headings";
3131

@@ -424,12 +424,20 @@ export default function UserDetail(p: { user: User }) {
424424
</button>,
425425
]}
426426
>
427-
<p>Edit feature access by adding or removing feature flags for this user.</p>
428-
<div className="flex flex-col">
427+
<CheckboxListField
428+
label="Edit feature access by adding or removing feature flags for this user."
429+
className="mt-0"
430+
>
429431
{flags.map((e) => (
430-
<CheckBox key={e.title} title={e.title} desc="" checked={!!e.checked} onChange={e.onClick} />
432+
<CheckboxInputField
433+
key={e.title}
434+
label={e.title}
435+
checked={!!e.checked}
436+
topMargin={false}
437+
onChange={e.onClick}
438+
/>
431439
))}
432-
</div>
440+
</CheckboxListField>
433441
</Modal>
434442
<Modal
435443
visible={editRoles}
@@ -441,12 +449,20 @@ export default function UserDetail(p: { user: User }) {
441449
</button>,
442450
]}
443451
>
444-
<p>Edit user permissions by adding or removing roles for this user.</p>
445-
<div className="flex flex-col">
452+
<CheckboxListField
453+
label="Edit user permissions by adding or removing roles for this user."
454+
className="mt-0"
455+
>
446456
{rop.map((e) => (
447-
<CheckBox key={e.title} title={e.title} desc="" checked={!!e.checked} onChange={e.onClick} />
457+
<CheckboxInputField
458+
key={e.title}
459+
label={e.title}
460+
checked={!!e.checked}
461+
topMargin={false}
462+
onChange={e.onClick}
463+
/>
448464
))}
449-
</div>
465+
</CheckboxListField>
450466
</Modal>
451467
</>
452468
);

components/dashboard/src/components/forms/CheckboxInputField.tsx

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,41 @@ import { useId } from "../../hooks/useId";
1010
import { InputField } from "./InputField";
1111
import { InputFieldHint } from "./InputFieldHint";
1212

13-
type CheckboxInputFieldProps = {
13+
type CheckboxListFieldProps = {
1414
label: string;
1515
error?: ReactNode;
1616
className?: string;
1717
};
18-
export const CheckboxInputField: FC<CheckboxInputFieldProps> = ({ label, error, className, children }) => {
18+
19+
// CheckboxListField is a wrapper for a list of related CheckboxInputField components.
20+
export const CheckboxListField: FC<CheckboxListFieldProps> = ({ label, error, className, children }) => {
1921
return (
2022
<InputField label={label} className={className} error={error}>
2123
<div className="space-y-2 ml-2">{children}</div>
2224
</InputField>
2325
);
2426
};
2527

26-
type CheckboxInputProps = {
28+
type CheckboxInputFieldProps = {
2729
id?: string;
28-
value: string;
30+
value?: string;
2931
checked: boolean;
3032
disabled?: boolean;
31-
label: string;
32-
hint?: string;
33+
label: ReactNode;
34+
hint?: ReactNode;
35+
error?: ReactNode;
36+
topMargin?: boolean;
3337
onChange: (checked: boolean) => void;
3438
};
35-
export const CheckboxInput: FC<CheckboxInputProps> = ({
39+
export const CheckboxInputField: FC<CheckboxInputFieldProps> = ({
3640
id,
3741
value,
3842
label,
3943
hint,
44+
error,
4045
checked,
4146
disabled = false,
47+
topMargin = true,
4248
onChange,
4349
}) => {
4450
const maybeId = useId();
@@ -52,33 +58,36 @@ export const CheckboxInput: FC<CheckboxInputProps> = ({
5258
);
5359

5460
return (
55-
<label className="flex space-x-2 justify-start items-start" htmlFor={elementId}>
56-
<input
57-
type="checkbox"
58-
className={classNames(
59-
"h-4 w-4 mt-0.5 rounded cursor-pointer border-2 dark:filter-invert",
60-
"focus:ring-2 focus:border-gray-900 ring-blue-400 dark:focus:border-gray-800",
61-
"border-gray-600 dark:border-gray-900 bg-transparent",
62-
{ "bg-gray-600 dark:bg-gray-900": checked },
63-
)}
64-
value={value}
65-
id={elementId}
66-
checked={checked}
67-
disabled={disabled}
68-
onChange={handleChange}
69-
/>
70-
<div className="flex flex-col">
71-
<span
61+
// Intentionally not passing label and hint to InputField because we want to render them differently for checkboxes.
62+
<InputField error={error} topMargin={topMargin}>
63+
<label className="flex space-x-2 justify-start items-start max-w-lg" htmlFor={elementId}>
64+
<input
65+
type="checkbox"
7266
className={classNames(
73-
"text-sm font-semibold cursor-pointer",
74-
disabled ? "text-gray-400 dark:text-gray-400" : "text-gray-600 dark:text-gray-100",
67+
"h-4 w-4 mt-0.5 rounded cursor-pointer border-2 dark:filter-invert",
68+
"focus:ring-2 ring-blue-400",
69+
"border-gray-600 dark:border-gray-900 bg-transparent",
70+
{ "bg-gray-600 dark:bg-gray-900": checked },
7571
)}
76-
>
77-
{label}
78-
</span>
72+
id={elementId}
73+
checked={checked}
74+
disabled={disabled}
75+
value={value}
76+
onChange={handleChange}
77+
/>
78+
<div className="flex flex-col">
79+
<span
80+
className={classNames(
81+
"text-sm font-semibold cursor-pointer",
82+
disabled ? "text-gray-400 dark:text-gray-400" : "text-gray-600 dark:text-gray-100",
83+
)}
84+
>
85+
{label}
86+
</span>
7987

80-
{hint && <InputFieldHint disabled={disabled}>{hint}</InputFieldHint>}
81-
</div>
82-
</label>
88+
{hint && <InputFieldHint disabled={disabled}>{hint}</InputFieldHint>}
89+
</div>
90+
</label>
91+
</InputField>
8392
);
8493
};

components/dashboard/src/components/forms/InputField.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,29 @@ type Props = {
1313
id?: string;
1414
hint?: ReactNode;
1515
error?: ReactNode;
16+
topMargin?: boolean;
1617
className?: string;
1718
};
1819

19-
export const InputField: FunctionComponent<Props> = memo(({ label, id, hint, error, className, children }) => {
20-
return (
21-
<div className={classNames("mt-4 flex flex-col space-y-2", className)}>
22-
{label && (
23-
<label
24-
className={classNames(
25-
"text-md font-semibold dark:text-gray-400",
26-
error ? "text-red-600" : "text-gray-600",
27-
)}
28-
htmlFor={id}
29-
>
30-
{label}
31-
</label>
32-
)}
33-
{children}
34-
{error && <span className="text-red-500 text-sm">{error}</span>}
35-
{hint && <InputFieldHint>{hint}</InputFieldHint>}
36-
</div>
37-
);
38-
});
20+
export const InputField: FunctionComponent<Props> = memo(
21+
({ label, id, hint, error, topMargin = true, className, children }) => {
22+
return (
23+
<div className={classNames("flex flex-col space-y-2", { "mt-4": topMargin }, className)}>
24+
{label && (
25+
<label
26+
className={classNames(
27+
"text-md font-semibold dark:text-gray-400",
28+
error ? "text-red-600" : "text-gray-600",
29+
)}
30+
htmlFor={id}
31+
>
32+
{label}
33+
</label>
34+
)}
35+
{children}
36+
{error && <span className="text-red-500 text-sm">{error}</span>}
37+
{hint && <InputFieldHint>{hint}</InputFieldHint>}
38+
</div>
39+
);
40+
},
41+
);

components/dashboard/src/onboarding/StepOrgInfo.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { User } from "@gitpod/gitpod-protocol";
88
import { FC, useCallback, useMemo, useState } from "react";
9-
import { CheckboxInput, CheckboxInputField } from "../components/forms/CheckboxInputField";
9+
import { CheckboxInputField, CheckboxListField } from "../components/forms/CheckboxInputField";
1010
import { SelectInputField } from "../components/forms/SelectInputField";
1111
import { TextInputField } from "../components/forms/TextInputField";
1212
import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutation";
@@ -189,13 +189,14 @@ export const StepOrgInfo: FC<Props> = ({ user, onComplete }) => {
189189
onBlur={websiteError.onBlur}
190190
/>
191191

192-
<CheckboxInputField label="I'm exploring Gitpod...">
192+
<CheckboxListField label="I'm exploring Gitpod...">
193193
{explorationReasonsOptions.map((o) => (
194-
<CheckboxInput
194+
<CheckboxInputField
195195
key={o.value}
196196
value={o.value}
197197
label={o.label}
198198
checked={explorationReasons.includes(o.value)}
199+
topMargin={false}
199200
onChange={(checked) => {
200201
if (checked) {
201202
addExplorationReason(o.value);
@@ -205,7 +206,7 @@ export const StepOrgInfo: FC<Props> = ({ user, onComplete }) => {
205206
}}
206207
/>
207208
))}
208-
</CheckboxInputField>
209+
</CheckboxListField>
209210

210211
{explorationReasons.includes(EXPLORE_REASON_WORK) && (
211212
<SelectInputField
@@ -223,13 +224,14 @@ export const StepOrgInfo: FC<Props> = ({ user, onComplete }) => {
223224
</SelectInputField>
224225
)}
225226

226-
<CheckboxInputField label="I'm signing up for Gitpod for...">
227+
<CheckboxListField label="I'm signing up for Gitpod for...">
227228
{signupGoalsOptions.map((o) => (
228-
<CheckboxInput
229+
<CheckboxInputField
229230
key={o.value}
230231
value={o.value}
231232
label={o.label}
232233
checked={signupGoals.includes(o.value)}
234+
topMargin={false}
233235
onChange={(checked) => {
234236
if (checked) {
235237
addSignupGoal(o.value);
@@ -239,7 +241,7 @@ export const StepOrgInfo: FC<Props> = ({ user, onComplete }) => {
239241
}}
240242
/>
241243
))}
242-
</CheckboxInputField>
244+
</CheckboxListField>
243245

244246
{signupGoals.includes(SIGNUP_GOALS_OTHER) && (
245247
<TextInputField

0 commit comments

Comments
 (0)