Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit a97e505

Browse files
committed
Improve type of AccessibleButton to accurately represent available props
1 parent bc30713 commit a97e505

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

src/components/views/elements/AccessibleButton.tsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
limitations under the License.
1515
*/
1616

17-
import React, { ReactHTML } from 'react';
17+
import React, { HTMLProps, InputHTMLAttributes, ReactHTML, ReactNode } from 'react';
1818
import classnames from 'classnames';
1919

2020
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
@@ -35,15 +35,30 @@ type AccessibleButtonKind = | 'primary'
3535
| 'confirm_sm'
3636
| 'cancel_sm';
3737

38+
/**
39+
* This type construct allows us to specifically pass those props down to the element we’re creating that the element
40+
* actually supports.
41+
*
42+
* e.g., if element is set to "a", we’ll support href and target, if it’s set to "input", we support type.
43+
*
44+
* To remain compatible with existing code, we’ll continue to support InputHTMLAttributes<Element>
45+
*/
46+
type DynamicHtmlElementProps<T extends keyof JSX.IntrinsicElements> =
47+
JSX.IntrinsicElements[T] extends HTMLProps<any> ? DynamicElementProps<T> : DynamicElementProps<"div">;
48+
type DynamicElementProps<T extends keyof JSX.IntrinsicElements> =
49+
Partial<Omit<JSX.IntrinsicElements[T], 'ref' | 'onClick' | 'onMouseDown' | 'onKeyUp' | 'onKeyDown'>>
50+
& Omit<InputHTMLAttributes<Element>, 'onClick'>;
51+
3852
/**
3953
* children: React's magic prop. Represents all children given to the element.
4054
* element: (optional) The base element type. "div" by default.
4155
* onClick: (required) Event handler for button activation. Should be
4256
* implemented exactly like a normal onClick handler.
4357
*/
44-
interface IProps extends React.InputHTMLAttributes<Element> {
58+
type IProps<T extends keyof JSX.IntrinsicElements> = DynamicHtmlElementProps<T> & {
4559
inputRef?: React.Ref<Element>;
46-
element?: keyof ReactHTML;
60+
element?: T;
61+
children?: ReactNode | undefined;
4762
// The kind of button, similar to how Bootstrap works.
4863
// See available classes for AccessibleButton for options.
4964
kind?: AccessibleButtonKind | string;
@@ -55,7 +70,7 @@ interface IProps extends React.InputHTMLAttributes<Element> {
5570
className?: string;
5671
triggerOnMouseDown?: boolean;
5772
onClick(e?: ButtonEvent): void | Promise<void>;
58-
}
73+
};
5974

6075
interface IAccessibleButtonProps extends React.InputHTMLAttributes<Element> {
6176
ref?: React.Ref<Element>;
@@ -69,7 +84,7 @@ interface IAccessibleButtonProps extends React.InputHTMLAttributes<Element> {
6984
* @param {Object} props react element properties
7085
* @returns {Object} rendered react
7186
*/
72-
export default function AccessibleButton({
87+
export default function AccessibleButton<T extends keyof JSX.IntrinsicElements>({
7388
element,
7489
onClick,
7590
children,
@@ -81,7 +96,7 @@ export default function AccessibleButton({
8196
onKeyUp,
8297
triggerOnMouseDown,
8398
...restProps
84-
}: IProps) {
99+
}: IProps<T>) {
85100
const newProps: IAccessibleButtonProps = restProps;
86101
if (disabled) {
87102
newProps["aria-disabled"] = true;

0 commit comments

Comments
 (0)