diff --git a/packages/form/src/toggle/InputToggle.tsx b/packages/form/src/toggle/InputToggle.tsx index d4a7a4b8d4..9d6fb965b3 100644 --- a/packages/form/src/toggle/InputToggle.tsx +++ b/packages/form/src/toggle/InputToggle.tsx @@ -14,6 +14,7 @@ import { bem } from "@react-md/utils"; import { Label } from "../label/Label"; import { useFocusState } from "../useFocusState"; import { ToggleContainer } from "./ToggleContainer"; +import { InputToggleIcon } from "./InputToggleIcon"; /** * The props for a checkbox or radio input element. @@ -261,20 +262,16 @@ export const InputToggle = forwardRef( onBlur={onBlur} className={cn(block("input"), inputClassName)} /> - {icon} - + {ripples} {children} diff --git a/packages/form/src/toggle/InputToggleIcon.tsx b/packages/form/src/toggle/InputToggleIcon.tsx new file mode 100644 index 0000000000..4c6ebf51f9 --- /dev/null +++ b/packages/form/src/toggle/InputToggleIcon.tsx @@ -0,0 +1,75 @@ +import React, { forwardRef, HTMLAttributes, ReactElement } from "react"; +import cn from "classnames"; +import { bem } from "@react-md/utils"; + +/** + * @remarks \@since 2.8.0 + */ +export interface InputToggleIconProps extends HTMLAttributes { + /** + * Boolean if the icon should use circle styles. This should normally be + * enabled for radio input types. + */ + circle?: boolean; + + /** + * Boolean if the disabled styles should be applied. + */ + disabled?: boolean; + + /** + * Boolean if using an overlay for the different icon states. + */ + overlay?: boolean; + + /** + * Boolean if the icon should gain the checked state. + */ + checked?: boolean; + + /** + * Boolean if using the indeterminate checkbox state. + */ + indeterminate?: boolean; +} + +const styles = bem("rmd-toggle"); + +/** + * @remarks \@since 2.8.0 + */ +export const InputToggleIcon = forwardRef< + HTMLSpanElement, + InputToggleIconProps +>(function InputToggleIcon( + { + circle = false, + disabled = false, + overlay = false, + checked = false, + indeterminate = false, + className, + children, + ...props + }: InputToggleIconProps, + ref +): ReactElement | null { + return ( + + {children} + + ); +}); diff --git a/packages/form/src/toggle/Switch.tsx b/packages/form/src/toggle/Switch.tsx index 82e63ee9f6..17652524cb 100644 --- a/packages/form/src/toggle/Switch.tsx +++ b/packages/form/src/toggle/Switch.tsx @@ -6,10 +6,10 @@ import React, { } from "react"; import cn from "classnames"; import { TextIconSpacing } from "@react-md/icon"; -import { bem } from "@react-md/utils"; import { Label } from "../label/Label"; import { ToggleContainer } from "./ToggleContainer"; +import { SwitchTrack } from "./SwitchTrack"; export interface SwitchProps extends Omit, "type" | "readOnly"> { @@ -97,8 +97,6 @@ export interface SwitchProps children?: ReactNode; } -const block = bem("rmd-switch"); - export const Switch = forwardRef(function Switch( { style, @@ -137,32 +135,24 @@ export const Switch = forwardRef(function Switch( className={labelClassName} htmlFor={id} error={error} - disabled={ - typeof labelDisabled === "boolean" ? labelDisabled : disabled - } + disabled={labelDisabled ?? disabled} > {label} } iconAfter={!iconAfter} > - - - - + + {children} + ); diff --git a/packages/form/src/toggle/SwitchTrack.tsx b/packages/form/src/toggle/SwitchTrack.tsx new file mode 100644 index 0000000000..3e644dbfc4 --- /dev/null +++ b/packages/form/src/toggle/SwitchTrack.tsx @@ -0,0 +1,100 @@ +import React, { + CSSProperties, + forwardRef, + HTMLAttributes, + InputHTMLAttributes, +} from "react"; +import cn from "classnames"; +import { bem, PropsWithRef } from "@react-md/utils"; + +const styles = bem("rmd-switch"); + +/** @remarks \@since 2.8.0 */ +export interface SwitchTrackProps + extends InputHTMLAttributes { + /** + * If an `id` is provided, the track will contain a checkbox input element and + * render the "ball" as a `