Skip to content

Commit 6d487a9

Browse files
authored
Add FormSwitch (#928)
1 parent 83b4a30 commit 6d487a9

File tree

5 files changed

+64
-24
lines changed

5 files changed

+64
-24
lines changed

apps/cyberstorm-storybook/stories/components/Switch.stories.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,40 @@ const meta = {
1010
const Template: StoryFn<typeof Switch> = (args) => <Switch {...args} />;
1111

1212
const SameStateSwitchTemplate: StoryFn<typeof Switch> = () => {
13-
const [state, setState] = useState(false);
13+
const [value, setValue] = useState(false);
1414
return (
1515
<div>
1616
<div>
17-
<Switch state={state} onChange={setState} />
17+
<Switch value={value} onChange={setValue} />
1818
</div>
1919
<div>
20-
<Switch state={state} onChange={setState} />
20+
<Switch value={value} onChange={setValue} />
2121
</div>
2222
</div>
2323
);
2424
};
2525
const SwitchLabelIdTemplate: StoryFn<typeof Switch> = () => {
26-
const [state, setState] = useState(false);
26+
const [value, setValue] = useState(false);
2727
return (
2828
<>
2929
<label htmlFor="my-switch">My switch</label>
30-
<Switch state={state} onChange={setState} id="my-switch" />
30+
<Switch value={value} onChange={setValue} id="my-switch" />
3131
</>
3232
);
3333
};
3434
const SwitchNestedLabelTemplate: StoryFn<typeof Switch> = () => {
35-
const [state, setState] = useState(false);
35+
const [value, setValue] = useState(false);
3636
return (
3737
<label>
3838
My switch
39-
<Switch state={state} onChange={setState} />
39+
<Switch value={value} onChange={setValue} />
4040
</label>
4141
);
4242
};
4343

4444
const RegularSwitch = Template.bind({});
4545
const DisabledSwitch = Template.bind({});
46-
DisabledSwitch.args = { state: false, disabled: true };
46+
DisabledSwitch.args = { value: false, disabled: true };
4747
const SameStateSwitch = SameStateSwitchTemplate.bind({});
4848
const SwitchNestedLabel = SwitchNestedLabelTemplate.bind({});
4949
const SwitchLabelId = SwitchLabelIdTemplate.bind({});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"use client";
2+
3+
import { z, ZodObject } from "zod";
4+
import { ZodRawShape } from "zod/lib/types";
5+
import { Path, useController } from "react-hook-form";
6+
import styles from "./FormTextInput.module.css";
7+
import { Switch } from "@thunderstore/cyberstorm";
8+
9+
export type FormSwitchProps<
10+
Schema extends ZodObject<Z>,
11+
Z extends ZodRawShape
12+
> = {
13+
// The schema is required to allow TS to infer valid values for the name field
14+
schema: Schema;
15+
name: Path<z.infer<Schema>>;
16+
placeholder?: string;
17+
};
18+
export function FormSwitch<Schema extends ZodObject<Z>, Z extends ZodRawShape>({
19+
name,
20+
}: FormSwitchProps<Schema, Z>) {
21+
const {
22+
field,
23+
fieldState: { error },
24+
formState: { isSubmitting, disabled },
25+
} = useController({ name });
26+
27+
return (
28+
<>
29+
<Switch {...field} disabled={isSubmitting || disabled} />
30+
{error && <span className={styles.errorMessage}>{error.message}</span>}
31+
</>
32+
);
33+
}
34+
35+
FormSwitch.displayName = "FormSwitch";

packages/cyberstorm-forms/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ export { useFormToaster } from "./useFormToaster";
22
export { FormSubmitButton } from "./components/FormSubmitButton";
33
export { FormSelectSearch } from "./components/FormSelectSearch";
44
export { FormMultiSelectSearch } from "./components/FormMultiSelectSearch";
5+
export { FormSwitch } from "./components/FormSwitch";
56
export { FormTextInput } from "./components/FormTextInput";
67
export { CreateTeamForm } from "./forms/CreateTeamForm";

packages/cyberstorm/src/components/Layout/Settings/Connections/Connections.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ function Connection(props: ConnectionProps) {
9898
</div>
9999
</div>
100100
) : null}
101-
<Switch state={connection !== undefined} />
101+
<Switch value={connection !== undefined} />
102102
</div>
103103
</div>
104104
</div>

packages/cyberstorm/src/components/Switch/Switch.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,29 @@
33
import { Dispatch, SetStateAction } from "react";
44
import styles from "./Switch.module.css";
55
import * as RadixSwitch from "@radix-ui/react-switch";
6+
import React from "react";
67

78
export interface SwitchProps {
8-
state: boolean;
9+
value: boolean;
910
onChange?: Dispatch<SetStateAction<boolean>>;
1011
disabled?: boolean;
1112
id?: string;
1213
}
1314

14-
export function Switch(props: SwitchProps) {
15-
const { state, onChange, disabled = false, id } = props;
16-
return (
17-
<RadixSwitch.Root
18-
className={styles.root}
19-
disabled={disabled}
20-
onCheckedChange={onChange}
21-
checked={state}
22-
id={id}
23-
>
24-
<RadixSwitch.Thumb className={styles.thumb} />
25-
</RadixSwitch.Root>
26-
);
27-
}
15+
export const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(
16+
function Switch(props, ref) {
17+
const { value, onChange, disabled = false, id } = props;
18+
return (
19+
<RadixSwitch.Root
20+
className={styles.root}
21+
disabled={disabled}
22+
onCheckedChange={onChange}
23+
checked={value}
24+
id={id}
25+
ref={ref}
26+
>
27+
<RadixSwitch.Thumb className={styles.thumb} />
28+
</RadixSwitch.Root>
29+
);
30+
}
31+
);

0 commit comments

Comments
 (0)