Skip to content

Commit

Permalink
fix(menu): set the initial state correctly (#1732)
Browse files Browse the repository at this point in the history
  • Loading branch information
nadiia committed Aug 12, 2019
1 parent 486d16a commit 3f9434f
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 21 deletions.
5 changes: 4 additions & 1 deletion src/menu/__tests__/menu-stateful.scenario.js
Expand Up @@ -29,11 +29,14 @@ const ITEMS = [

export const component = () => (
<StatefulMenu
initialState={{
highlightedIndex: 5,
}}
items={ITEMS}
overrides={{
List: {
style: {
height: '100px',
height: '300px',
width: '350px',
},
},
Expand Down
8 changes: 6 additions & 2 deletions src/menu/stateful-container.js
Expand Up @@ -23,8 +23,9 @@ export default class MenuStatefulContainer extends React.Component<
StatefulContainerStateT,
> {
static defaultProps = {
// keeping it in defaultProps to satisfy Flow
initialState: {
// Defaults to -1 so no item is highlighted
// We start the index at -1 to indicate that no highlighting exists initially
highlightedIndex: -1,
isFocused: false,
activedescendantId: null,
Expand All @@ -41,7 +42,10 @@ export default class MenuStatefulContainer extends React.Component<
getChildMenu: () => {},
};

state: StatefulContainerStateT = {...this.props.initialState};
state: StatefulContainerStateT = {
...this.constructor.defaultProps.initialState,
...this.props.initialState,
};

// We need to have access to the root component user renders
// to correctly facilitate keyboard scrolling behavior
Expand Down
17 changes: 1 addition & 16 deletions src/menu/stateful-menu.js
Expand Up @@ -12,24 +12,9 @@ import Menu from './menu.js';
import {NestedMenuContext} from './nested-menus.js';
import StatefulContainer from './stateful-container.js';

import type {StatefulMenuPropsT, StateReducerFnT} from './types.js';
import type {StatefulMenuPropsT} from './types.js';

export default class StatefulMenu extends React.PureComponent<StatefulMenuPropsT> {
static defaultProps = {
// Mostly to satisfy flow
initialState: {
activedescendantId: null,
isFocused: false,
// We start the index at -1 to indicate that no highlighting exists initially
highlightedIndex: -1,
},
stateReducer: ((changeType, changes) => changes: StateReducerFnT),
onItemSelect: () => {},
getRequiredItemProps: () => ({}),
children: () => null,
overrides: {},
};

render() {
const {overrides, ...props} = this.props;
return (
Expand Down
39 changes: 37 additions & 2 deletions src/menu/types.js
Expand Up @@ -80,6 +80,16 @@ export type StatefulContainerStateT = {
isFocused: boolean,
};

export type InitialStateT = {
// id of the currently highlighted item (from keyboard control)
activedescendantId?: ?string,
// index of currently highlighted item (from keyboard control)
highlightedIndex?: number,
// indicates when the menu can be navigated by keyboard and affects menu item option rendering
// see https://github.com/uber-web/baseui/issues/993 for a description.
isFocused?: boolean,
};

export type RenderPropsT = StatefulContainerStateT & {
items: ItemsT,
getRequiredItemProps: GetRequiredItemPropsFnT,
Expand All @@ -96,7 +106,7 @@ export type StatefulContainerPropsT = {
/** List of menu items. */
items: ItemsT,
/** Initial state of the stateful menu. */
initialState: StatefulContainerStateT,
initialState: InitialStateT,
/** State reducer to intercept state changes and return new internal state */
stateReducer: StateReducerFnT,
/** Function to get props for each rendered item. This will have some defaults needed for keyboard
Expand Down Expand Up @@ -158,7 +168,32 @@ export type SharedStatelessPropsT = {
unfocusMenu?: () => mixed,
};

export type StatefulMenuPropsT = StatefulContainerPropsT & MenuPropsT;
export type StatefulMenuPropsT = {
/** List of menu items. */
items: ItemsT,
/** Initial state of the stateful menu. */
initialState?: InitialStateT,
/** State reducer to intercept state changes and return new internal state */
stateReducer?: StateReducerFnT,
/** Function to get props for each rendered item. This will have some defaults needed for keyboard
* bindings to work properly. Every rendered item should call this.
*/
getRequiredItemProps?: GetRequiredItemPropsFnT,
/** Callback executed on menu item clicks. */
onItemSelect?: OnItemSelectFnT,
/** Ref for the menu container element. Used to capture key events for navigation */
rootRef?: RootRefT,
/** Child as function pattern. */
children?: RenderPropsT => React.Node,
addMenuToNesting?: (ref: {current: HTMLElement | null}) => void,
removeMenuFromNesting?: (ref: {current: HTMLElement | null}) => void,
getParentMenu?: (ref: {current: HTMLElement | null}) => ?{
current: HTMLElement | null,
},
getChildMenu?: (ref: {current: HTMLElement | null}) => ?{
current: HTMLElement | null,
},
} & MenuPropsT;

export type StatefulMenuProfilePropsT = StatefulContainerPropsT &
MenuProfilePropsT;
Expand Down

0 comments on commit 3f9434f

Please sign in to comment.