66 */
77
88import PropTypes from 'prop-types' ;
9- import React , { useState } from 'react' ;
9+ import React , {
10+ forwardRef ,
11+ useState ,
12+ type KeyboardEvent ,
13+ type MouseEvent ,
14+ type ReactNode ,
15+ } from 'react' ;
1016import classNames from 'classnames' ;
11- import { IconButton } from '../IconButton' ;
17+ import { IconButton , type IconButtonProps } from '../IconButton' ;
1218import { usePrefix } from '../../internal/usePrefix' ;
19+ import { noopFn } from '../../internal/noopFn' ;
20+ import type { SwitchEventHandlersParams } from './Switch' ;
1321
14- const noopFn = ( ) => { } ;
22+ interface IconSwitchProps
23+ extends Omit < IconButtonProps , 'onClick' | 'onKeyDown' | 'label' | 'name' > {
24+ /**
25+ * The index of the `IconSwitch`.
26+ *
27+ * Reserved for usage in `ContentSwitcher`.
28+ */
29+ index ?: number ;
30+
31+ /**
32+ * The name of the `IconSwitch`.
33+ */
34+ name ?: string | number ;
35+
36+ /**
37+ * A handler that is invoked when a user clicks on the control.
38+ *
39+ * Reserved for usage in `ContentSwitcher`.
40+ */
41+ onClick ?: ( params : SwitchEventHandlersParams ) => void ;
42+
43+ /**
44+ * A handler that is invoked on the key down event for the control.
45+ *
46+ * Reserved for usage in `ContentSwitcher`.
47+ */
48+ onKeyDown ?: ( params : SwitchEventHandlersParams ) => void ;
1549
16- const IconSwitch = React . forwardRef ( function Switch ( props , tabRef ) {
50+ /**
51+ * Whether the `IconSwitch` is selected.
52+ *
53+ * Reserved for usage in `ContentSwitcher`.
54+ */
55+ selected ?: boolean ;
56+
57+ // TODO: Why isn't this prop named `label` to match the `IconButton` prop?
58+ /**
59+ * `Tooltip` text.
60+ */
61+ text ?: string ;
62+ }
63+
64+ const frFn = forwardRef < HTMLButtonElement , IconSwitchProps > ;
65+
66+ const IconSwitch = frFn ( ( props , ref ) => {
1767 const {
1868 align,
1969 children,
@@ -33,12 +83,13 @@ const IconSwitch = React.forwardRef(function Switch(props, tabRef) {
3383 const prefix = usePrefix ( ) ;
3484 const [ isHovered , setIsHovered ] = useState ( false ) ;
3585
36- const handleClick = ( e ) => {
37- e . preventDefault ( ) ;
86+ const handleClick = ( event : MouseEvent < HTMLButtonElement > ) => {
87+ event . preventDefault ( ) ;
3888 onClick ( { index, name, text } ) ;
3989 } ;
4090
41- const handleKeyDown = ( event ) => {
91+ const handleKeyDown = ( event : KeyboardEvent < HTMLButtonElement > ) => {
92+ // TODO: `which` was deprecated years ago. When can its usage be deleted?
4293 const key = event . key || event . which ;
4394
4495 onKeyDown ( { index, name, text, key } ) ;
@@ -64,22 +115,11 @@ const IconSwitch = React.forwardRef(function Switch(props, tabRef) {
64115 }
65116 ) ;
66117
67- const commonProps = {
68- onClick : handleClick ,
69- onKeyDown : handleKeyDown ,
70- className : classes ,
71- disabled,
72- align,
73- enterDelayMs,
74- leaveDelayMs,
75- size,
76- } ;
77-
78118 return (
79119 < IconButton
80120 label = { text }
81121 type = "button"
82- ref = { tabRef }
122+ ref = { ref }
83123 role = "tab"
84124 tabIndex = { selected || isHovered ? 0 : - 1 }
85125 onMouseEnter = { handleMouseEnter }
@@ -90,7 +130,14 @@ const IconSwitch = React.forwardRef(function Switch(props, tabRef) {
90130 aria-label = { text }
91131 wrapperClasses = { iconButtonClasses }
92132 { ...other }
93- { ...commonProps } >
133+ align = { align }
134+ className = { classes }
135+ disabled = { disabled }
136+ enterDelayMs = { enterDelayMs }
137+ leaveDelayMs = { leaveDelayMs }
138+ onClick = { handleClick }
139+ onKeyDown = { handleKeyDown }
140+ size = { size } >
94141 { children }
95142 </ IconButton >
96143 ) ;
@@ -114,17 +161,17 @@ IconSwitch.propTypes = {
114161 ] ) ,
115162
116163 /**
117- * Provide child elements to be rendered inside of the Switch
164+ * Children to be rendered inside of the `IconSwitch`.
118165 */
119166 children : PropTypes . node ,
120167
121168 /**
122- * Specify an optional className to be added to your Switch
169+ * Specify an optional className to be added to your `IconSwitch`.
123170 */
124171 className : PropTypes . string ,
125172
126173 /**
127- * Specify whether or not the Switch should be disabled
174+ * Whether the `IconSwitch` should be disabled.
128175 */
129176 disabled : PropTypes . bool ,
130177
@@ -134,8 +181,9 @@ IconSwitch.propTypes = {
134181 enterDelayMs : PropTypes . number ,
135182
136183 /**
137- * The index of your Switch in your ContentSwitcher that is used for event handlers.
138- * Reserved for usage in ContentSwitcher
184+ * The index of the `IconSwitch`.
185+ *
186+ * Reserved for usage in `ContentSwitcher`.
139187 */
140188 index : PropTypes . number ,
141189
@@ -145,34 +193,39 @@ IconSwitch.propTypes = {
145193 leaveDelayMs : PropTypes . number ,
146194
147195 /**
148- * Provide the name of your Switch that is used for event handlers
196+ * The name of the `IconSwitch`.
149197 */
150198 name : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number ] ) ,
151199
152200 /**
153201 * A handler that is invoked when a user clicks on the control.
154- * Reserved for usage in ContentSwitcher
202+ *
203+ * Reserved for usage in `ContentSwitcher`.
155204 */
156205 onClick : PropTypes . func ,
157206
158207 /**
159208 * A handler that is invoked on the key down event for the control.
160- * Reserved for usage in ContentSwitcher
209+ *
210+ * Reserved for usage in `ContentSwitcher`.
161211 */
162212 onKeyDown : PropTypes . func ,
163213
164214 /**
165- * Whether your Switch is selected. Reserved for usage in ContentSwitcher
215+ * Whether the `IconSwitch` is selected.
216+ *
217+ * Reserved for usage in `ContentSwitcher`.
166218 */
167219 selected : PropTypes . bool ,
168220
221+ // TODO: Icon only variant of what? Isn't the `IconSwitch` always icon only?
169222 /**
170223 * Passed in from `ContentSwitcher` to render icon-only variant
171224 */
172225 size : PropTypes . oneOf ( [ 'sm' , 'md' , 'lg' ] ) ,
173226
174227 /**
175- * Provide the visible text displayed by the Tooltip
228+ * `Tooltip` text.
176229 */
177230 text : PropTypes . string ,
178231} ;
0 commit comments