From 2748d5e8405a347825b56d6a266c0bcb0b9e726a Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 10 Aug 2026 16:06:00 +0200 Subject: [PATCH] refactor(toggle): migrate Toggle from Flow to TypeScript --- .../toggle/{Toggle.js => Toggle.js.flow} | 0 .../{Toggle.stories.js => Toggle.stories.tsx} | 1 - src/components/toggle/Toggle.tsx | 100 ++++++++++++++++++ .../{ToggleField.js => ToggleField.js.flow} | 2 +- src/components/toggle/ToggleField.tsx | 21 ++++ .../{Toggle.test.js => Toggle.test.tsx} | 5 +- ...ggleField.test.js => ToggleField.test.tsx} | 7 +- ...ggle.test.js.snap => Toggle.test.tsx.snap} | 0 ...test.js.snap => ToggleField.test.tsx.snap} | 0 .../toggle/{index.js => index.js.flow} | 0 src/components/toggle/index.ts | 4 + 11 files changed, 134 insertions(+), 6 deletions(-) rename src/components/toggle/{Toggle.js => Toggle.js.flow} (100%) rename src/components/toggle/{Toggle.stories.js => Toggle.stories.tsx} (99%) create mode 100644 src/components/toggle/Toggle.tsx rename src/components/toggle/{ToggleField.js => ToggleField.js.flow} (83%) create mode 100644 src/components/toggle/ToggleField.tsx rename src/components/toggle/__tests__/{Toggle.test.js => Toggle.test.tsx} (91%) rename src/components/toggle/__tests__/{ToggleField.test.js => ToggleField.test.tsx} (77%) rename src/components/toggle/__tests__/__snapshots__/{Toggle.test.js.snap => Toggle.test.tsx.snap} (100%) rename src/components/toggle/__tests__/__snapshots__/{ToggleField.test.js.snap => ToggleField.test.tsx.snap} (100%) rename src/components/toggle/{index.js => index.js.flow} (100%) create mode 100644 src/components/toggle/index.ts diff --git a/src/components/toggle/Toggle.js b/src/components/toggle/Toggle.js.flow similarity index 100% rename from src/components/toggle/Toggle.js rename to src/components/toggle/Toggle.js.flow diff --git a/src/components/toggle/Toggle.stories.js b/src/components/toggle/Toggle.stories.tsx similarity index 99% rename from src/components/toggle/Toggle.stories.js rename to src/components/toggle/Toggle.stories.tsx index 9e5344f559..f8a65420e2 100644 --- a/src/components/toggle/Toggle.stories.js +++ b/src/components/toggle/Toggle.stories.tsx @@ -1,4 +1,3 @@ -// @flow /* eslint-disable react-hooks/rules-of-hooks */ import * as React from 'react'; diff --git a/src/components/toggle/Toggle.tsx b/src/components/toggle/Toggle.tsx new file mode 100644 index 0000000000..677ad54df5 --- /dev/null +++ b/src/components/toggle/Toggle.tsx @@ -0,0 +1,100 @@ +import * as React from 'react'; +import classNames from 'classnames'; + +import './Toggle.scss'; + +export interface ToggleProps + extends Omit< + React.InputHTMLAttributes, + 'checked' | 'disabled' | 'onMouseEnter' | 'onMouseLeave' + > { + /** CSS class for the toggle container */ + className?: string; + /** Optional attribute used for targeting */ + 'data-target-id'?: string; + /** Description of the input */ + description?: React.ReactNode; + /** Whether the toggle is disabled. @TODO: eventually call this `disabled` */ + isDisabled?: boolean; + /** Toggle state. @TODO: eventually call this `checked` */ + isOn?: boolean; + /** If set to true, the toggle will be aligned to the right */ + isToggleRightAligned?: boolean; + /** Label displayed for the input */ + label: React.ReactNode; + /** Name of the input */ + name?: string; + /** blur callback function called with event as the argument */ + onBlur?: (e: React.FocusEvent) => void; + /** change callback function called with event as the argument */ + onChange?: (e: React.ChangeEvent) => void; + /** focus callback function called with event as the argument */ + onFocus?: (e: React.FocusEvent) => void; + /** mouse enter callback function called with event as the argument */ + onMouseEnter?: (e: React.MouseEvent) => void; + /** mouse leave callback function called with event as the argument */ + onMouseLeave?: (e: React.MouseEvent) => void; + /** optional value for the toggles checkbox */ + value?: React.InputHTMLAttributes['value']; +} + +const Toggle = React.forwardRef( + ( + { + className = '', + 'data-target-id': dataTargetId, + description, + isDisabled, + isOn, + isToggleRightAligned = false, + label, + name, + onBlur, + onChange, + onFocus, + onMouseEnter, + onMouseLeave, + ...rest + }, + ref, + ) => { + const classes = classNames('toggle-container', className, { + 'is-toggle-right-aligned': isToggleRightAligned, + }); + + const toggleElements = [ +
, +
+ {label} +
, + ]; + if (isToggleRightAligned) { + toggleElements.reverse(); + } + + return ( +
+ + {description ?
{description}
: null} +
+ ); + }, +); +Toggle.displayName = 'Toggle'; + +export default Toggle; diff --git a/src/components/toggle/ToggleField.js b/src/components/toggle/ToggleField.js.flow similarity index 83% rename from src/components/toggle/ToggleField.js rename to src/components/toggle/ToggleField.js.flow index 09f3ee9309..5d4d916e6e 100644 --- a/src/components/toggle/ToggleField.js +++ b/src/components/toggle/ToggleField.js.flow @@ -8,7 +8,7 @@ import type { ToggleProps } from './Toggle'; type Props = ToggleProps & FieldProps; -const ToggleField = ({ field, form, ...rest }: Props) => { +const ToggleField = ({ field, form, meta, ...rest }: Props) => { const { value } = field; return ; }; diff --git a/src/components/toggle/ToggleField.tsx b/src/components/toggle/ToggleField.tsx new file mode 100644 index 0000000000..b675550829 --- /dev/null +++ b/src/components/toggle/ToggleField.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import type { FieldProps } from 'formik'; + +import TogglePrimitive from './Toggle'; +import type { ToggleProps } from './Toggle'; + +export interface ToggleFieldProps extends Omit, FieldProps {} + +const ToggleField = ({ + field, + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- strip Formik form and meta bags from forwarded props + form, + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- strip Formik form and meta bags from forwarded props + meta, + ...rest +}: ToggleFieldProps) => { + const { value } = field; + return ; +}; + +export default ToggleField; diff --git a/src/components/toggle/__tests__/Toggle.test.js b/src/components/toggle/__tests__/Toggle.test.tsx similarity index 91% rename from src/components/toggle/__tests__/Toggle.test.js rename to src/components/toggle/__tests__/Toggle.test.tsx index 40312f6688..ce57668762 100644 --- a/src/components/toggle/__tests__/Toggle.test.js +++ b/src/components/toggle/__tests__/Toggle.test.tsx @@ -1,10 +1,13 @@ import * as React from 'react'; +import { shallow } from 'enzyme'; import sinon from 'sinon'; import Toggle from '..'; describe('components/toggle/Toggle', () => { - const getWrapper = (props = {}) => + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const getWrapper = (props: any = {}) => + // eslint-disable-next-line @typescript-eslint/no-empty-function shallow( {}} {...props} />); test('should correctly render default component', () => { diff --git a/src/components/toggle/__tests__/ToggleField.test.js b/src/components/toggle/__tests__/ToggleField.test.tsx similarity index 77% rename from src/components/toggle/__tests__/ToggleField.test.js rename to src/components/toggle/__tests__/ToggleField.test.tsx index 836d31667a..dfeb1abe6a 100644 --- a/src/components/toggle/__tests__/ToggleField.test.js +++ b/src/components/toggle/__tests__/ToggleField.test.tsx @@ -1,10 +1,11 @@ -// @flow - import * as React from 'react'; +import { shallow } from 'enzyme'; + import ToggleField from '../ToggleField'; describe('components/toggle/ToggleField', () => { - const getWrapper = (props = {}) => shallow(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const getWrapper = (props: any = {}) => shallow(); test.each([ [true, 'value'], diff --git a/src/components/toggle/__tests__/__snapshots__/Toggle.test.js.snap b/src/components/toggle/__tests__/__snapshots__/Toggle.test.tsx.snap similarity index 100% rename from src/components/toggle/__tests__/__snapshots__/Toggle.test.js.snap rename to src/components/toggle/__tests__/__snapshots__/Toggle.test.tsx.snap diff --git a/src/components/toggle/__tests__/__snapshots__/ToggleField.test.js.snap b/src/components/toggle/__tests__/__snapshots__/ToggleField.test.tsx.snap similarity index 100% rename from src/components/toggle/__tests__/__snapshots__/ToggleField.test.js.snap rename to src/components/toggle/__tests__/__snapshots__/ToggleField.test.tsx.snap diff --git a/src/components/toggle/index.js b/src/components/toggle/index.js.flow similarity index 100% rename from src/components/toggle/index.js rename to src/components/toggle/index.js.flow diff --git a/src/components/toggle/index.ts b/src/components/toggle/index.ts new file mode 100644 index 0000000000..a4652fde37 --- /dev/null +++ b/src/components/toggle/index.ts @@ -0,0 +1,4 @@ +export { default } from './Toggle'; +export { default as ToggleField } from './ToggleField'; +export type { ToggleProps } from './Toggle'; +export type { ToggleFieldProps } from './ToggleField';