Skip to content

Commit

Permalink
fix: menu typescript updates (#15447)
Browse files Browse the repository at this point in the history
This builds on #15361 to do a few more menu-related Typescript updates:

* MenuButton: Convert to Typescript.
* MenuContext: Specify type for context. There’s contradictory evidence though about whether payload
  is mandatory or optional.
* Menu: Minor cleanup including specifying that when x and y are arrays, the arrays contain exactly
  two numbers.
* MenuItem: Convert some “any” types into actual types, including converting MenuItemRadioGroup to
  a generic.  Also the same cleanup as above about x and y as arrays. Ignore spacing diffs.
* useAttachedMenu() - Convert to Typescript.

I had to add @ts-ignore to some of the PropTypes declarations for reasons I don't understand.
I'm not too worried about it since PropTypes declarations are essentially deprecated.

Also, I know the doc said not to convert internal files to Typescript but it didn’t seem feasible
to do this conversion without useAttachedMenu.js and MenuContext.ts having the right types,
and it didn’t seem feasible for them to have the right types without converting them to Typescript.

Menu, MenuButton and MenuItem were left out of the list on #12513 but I assume
they should be updated too.  Actually, I need MenuButton and MenuItem to be
updated before I can upgrade to Carbon 11.

Other notes:

I had to add @ts-ignore to the PropTypes declarations for reasons I don't
understand.  I'm not too worried about it since PropTypes declarations are
essentially deprecated.

Also, I know the doc said not to convert internal files to Typescript but it didn’t
seem feasible to do this conversion without useAttachedMenu.js and
MenuContext.ts having the right types, and it didn’t seem feasible for them
to have the right types without converting them to Typescript.
  • Loading branch information
wkeese committed Feb 16, 2024
1 parent 97c672a commit 00dc60f
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 256 deletions.
22 changes: 14 additions & 8 deletions packages/react/src/components/Menu/Menu.tsx
Expand Up @@ -8,6 +8,8 @@
import cx from 'classnames';
import PropTypes from 'prop-types';
import React, {
forwardRef,
ReactNode,
useContext,
useEffect,
useMemo,
Expand Down Expand Up @@ -36,7 +38,7 @@ interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
/**
* A collection of MenuItems to be rendered within this Menu.
*/
children?: React.ReactNode;
children?: ReactNode;

/**
* Additional CSS class names.
Expand All @@ -46,7 +48,7 @@ interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
/**
* A label describing the Menu.
*/
label?: string;
label: string;

/**
* Specify how the menu should align with the button element
Expand Down Expand Up @@ -85,20 +87,20 @@ interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
/**
* Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
*/
target?: any;
target?: HTMLElement;

/**
* Specify the x position of the Menu. Either pass a single number or an array with two numbers describing your activator's boundaries ([x1, x2])
*/
x?: number | (number | null | undefined)[];
x?: number | [number, number];

/**
* Specify the y position of the Menu. Either pass a single number or an array with two numbers describing your activator's boundaries ([y1, y2])
*/
y?: number | (number | null | undefined)[];
y?: number | [number, number];
}

const Menu = React.forwardRef<HTMLUListElement, MenuProps>(function Menu(
const Menu = forwardRef<HTMLUListElement, MenuProps>(function Menu(
{
children,
className,
Expand Down Expand Up @@ -149,7 +151,7 @@ const Menu = React.forwardRef<HTMLUListElement, MenuProps>(function Menu(
}, [childState, childDispatch]);

const menu = useRef<HTMLUListElement>(null);
const ref = useMergedRefs([forwardRef, menu]);
const ref = useMergedRefs<HTMLUListElement>([forwardRef, menu]);

const [position, setPosition] = useState([-1, -1]);
const focusableItems = childContext.state.items.filter(
Expand All @@ -163,7 +165,7 @@ const Menu = React.forwardRef<HTMLUListElement, MenuProps>(function Menu(
actionButtonWidth = w;
}

// Set RTL based on document direction or `LayoutDirection`
// Set RTL based on the document direction or `LayoutDirection`
const { direction } = useLayoutDirection();

function returnFocus() {
Expand Down Expand Up @@ -450,6 +452,7 @@ Menu.propTypes = {
/**
* A label describing the Menu.
*/
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
label: PropTypes.string,

/**
Expand Down Expand Up @@ -489,11 +492,13 @@ Menu.propTypes = {
/**
* Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
*/
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
target: PropTypes.object,

/**
* Specify the x position of the Menu. Either pass a single number or an array with two numbers describing your activator's boundaries ([x1, x2])
*/
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
x: PropTypes.oneOfType([
PropTypes.number,
PropTypes.arrayOf(PropTypes.number),
Expand All @@ -502,6 +507,7 @@ Menu.propTypes = {
/**
* Specify the y position of the Menu. Either pass a single number or an array with two numbers describing your activator's boundaries ([y1, y2])
*/
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
y: PropTypes.oneOfType([
PropTypes.number,
PropTypes.arrayOf(PropTypes.number),
Expand Down
24 changes: 16 additions & 8 deletions packages/react/src/components/Menu/MenuContext.ts
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { createContext, KeyboardEvent, RefObject } from 'react';

type ActionType = {
type: 'enableIcons' | 'registerItem';
Expand All @@ -18,9 +18,7 @@ type StateType = {
hasIcons: boolean;
size: 'xs' | 'sm' | 'md' | 'lg' | null;
items: any[];
requestCloseRoot: (
e: Pick<React.KeyboardEvent<HTMLUListElement>, 'type'>
) => void;
requestCloseRoot: (e: Pick<KeyboardEvent<HTMLUListElement>, 'type'>) => void;
};

const menuDefaultState: StateType = {
Expand Down Expand Up @@ -49,13 +47,23 @@ function menuReducer(state: StateType, action: ActionType) {
}
}

const MenuContext = React.createContext<{
type DispatchFuncProps = {
type: 'registerItem' | 'enableIcons';
payload: {
ref: RefObject<HTMLLIElement>;
disabled: boolean;
};
};

type MenuContextProps = {
state: StateType;
dispatch: React.Dispatch<any>;
}>({
dispatch: (props: DispatchFuncProps) => void;
};

const MenuContext = createContext<MenuContextProps>({
state: menuDefaultState,
// 'dispatch' is populated by the root menu
dispatch: () => {},
dispatch: (_: DispatchFuncProps) => {},
});

export { MenuContext, menuReducer };

0 comments on commit 00dc60f

Please sign in to comment.