Skip to content

Commit 8e0b658

Browse files
nikitadubykNikita Dubyk
andauthored
fix(toggleswitch component): added forwardRef to ToggleSwitch component (#1198)
fix #1078 Co-authored-by: Nikita Dubyk <[email protected]>
1 parent f186ec8 commit 8e0b658

File tree

1 file changed

+70
-65
lines changed

1 file changed

+70
-65
lines changed
Lines changed: 70 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { ComponentProps, FC, KeyboardEvent } from 'react';
2-
import { useId } from 'react';
1+
import type { ComponentProps, KeyboardEvent } from 'react';
2+
import { useId, forwardRef } from 'react';
33
import { twMerge } from 'tailwind-merge';
44
import { mergeDeep } from '../../helpers/merge-deep';
55
import { getTheme } from '../../theme-store';
@@ -26,7 +26,7 @@ export interface FlowbiteToggleSwitchToggleTheme {
2626
};
2727
}
2828

29-
export type ToggleSwitchProps = Omit<ComponentProps<'button'>, 'onChange'> & {
29+
export type ToggleSwitchProps = Omit<ComponentProps<'button'>, 'onChange' | 'ref'> & {
3030
checked: boolean;
3131
color?: keyof FlowbiteColors;
3232
sizing?: keyof FlowbiteTextInputSizes;
@@ -35,72 +35,77 @@ export type ToggleSwitchProps = Omit<ComponentProps<'button'>, 'onChange'> & {
3535
theme?: DeepPartial<FlowbiteToggleSwitchTheme>;
3636
};
3737

38-
export const ToggleSwitch: FC<ToggleSwitchProps> = ({
39-
checked,
40-
className,
41-
color = 'blue',
42-
sizing = 'md',
43-
disabled,
44-
label,
45-
name,
46-
onChange,
47-
theme: customTheme = {},
48-
...props
49-
}) => {
50-
const id = useId();
51-
const theme = mergeDeep(getTheme().toggleSwitch, customTheme);
38+
export const ToggleSwitch = forwardRef<HTMLInputElement, ToggleSwitchProps>(
39+
(
40+
{
41+
checked,
42+
className,
43+
color = 'blue',
44+
sizing = 'md',
45+
disabled,
46+
label,
47+
name,
48+
onChange,
49+
theme: customTheme = {},
50+
...props
51+
},
52+
ref,
53+
) => {
54+
const id = useId();
55+
const theme = mergeDeep(getTheme().toggleSwitch, customTheme);
5256

53-
const toggle = (): void => onChange(!checked);
57+
const toggle = (): void => onChange(!checked);
5458

55-
const handleClick = (): void => {
56-
toggle();
57-
};
59+
const handleClick = (): void => {
60+
toggle();
61+
};
5862

59-
const handleOnKeyDown = (event: KeyboardEvent<HTMLButtonElement>): void => {
60-
if (event.code == 'Enter') {
61-
event.preventDefault();
62-
}
63-
};
63+
const handleOnKeyDown = (event: KeyboardEvent<HTMLButtonElement>): void => {
64+
if (event.code == 'Enter') {
65+
event.preventDefault();
66+
}
67+
};
6468

65-
return (
66-
<>
67-
{name && checked ? (
68-
<input checked={checked} hidden name={name} readOnly type="checkbox" className="sr-only" />
69-
) : null}
70-
<button
71-
aria-checked={checked}
72-
aria-labelledby={`${id}-flowbite-toggleswitch-label`}
73-
disabled={disabled}
74-
id={`${id}-flowbite-toggleswitch`}
75-
onClick={handleClick}
76-
onKeyDown={handleOnKeyDown}
77-
role="switch"
78-
tabIndex={0}
79-
type="button"
80-
className={twMerge(theme.root.base, theme.root.active[disabled ? 'off' : 'on'], className)}
81-
{...props}
82-
>
83-
<div
84-
data-testid="flowbite-toggleswitch-toggle"
85-
className={twMerge(
86-
theme.toggle.base,
87-
theme.toggle.checked[checked ? 'on' : 'off'],
88-
checked && theme.toggle.checked.color[color],
89-
theme.toggle.sizes[sizing],
90-
)}
91-
/>
92-
{label?.length ? (
93-
<span
94-
data-testid="flowbite-toggleswitch-label"
95-
id={`${id}-flowbite-toggleswitch-label`}
96-
className={theme.root.label}
97-
>
98-
{label}
99-
</span>
69+
return (
70+
<>
71+
{name && checked ? (
72+
<input ref={ref} checked={checked} hidden name={name} readOnly type="checkbox" className="sr-only" />
10073
) : null}
101-
</button>
102-
</>
103-
);
104-
};
74+
<button
75+
aria-checked={checked}
76+
aria-labelledby={`${id}-flowbite-toggleswitch-label`}
77+
disabled={disabled}
78+
id={`${id}-flowbite-toggleswitch`}
79+
onClick={handleClick}
80+
onKeyDown={handleOnKeyDown}
81+
role="switch"
82+
tabIndex={0}
83+
type="button"
84+
className={twMerge(theme.root.base, theme.root.active[disabled ? 'off' : 'on'], className)}
85+
{...props}
86+
>
87+
<div
88+
data-testid="flowbite-toggleswitch-toggle"
89+
className={twMerge(
90+
theme.toggle.base,
91+
theme.toggle.checked[checked ? 'on' : 'off'],
92+
checked && theme.toggle.checked.color[color],
93+
theme.toggle.sizes[sizing],
94+
)}
95+
/>
96+
{label?.length ? (
97+
<span
98+
data-testid="flowbite-toggleswitch-label"
99+
id={`${id}-flowbite-toggleswitch-label`}
100+
className={theme.root.label}
101+
>
102+
{label}
103+
</span>
104+
) : null}
105+
</button>
106+
</>
107+
);
108+
},
109+
);
105110

106111
ToggleSwitch.displayName = 'ToggleSwitch';

0 commit comments

Comments
 (0)