Skip to content

Commit

Permalink
refactor(list): Refactor list item management (#413)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Event handlers moved from list to list item. New props on list item for focus, follow href, toggle checkbox, and classnames/attributes passed down from list. Remove ID prop from list item.
  • Loading branch information
bonniezhou authored Nov 6, 2018
1 parent 003221a commit 1f563d3
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 407 deletions.
2 changes: 1 addition & 1 deletion packages/list/ListGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const ListGroup = (props) => {

ListGroup.propTypes = {
className: PropTypes.string,
children: PropTypes.element,
children: PropTypes.node,
tag: PropTypes.string,
};

Expand Down
63 changes: 46 additions & 17 deletions packages/list/ListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,26 @@ import classnames from 'classnames';
export default class ListItem extends Component {
listItemElement_ = React.createRef();

componentDidMount() {
const {init} = this.props;
init && init();
}

get listItemElement() {
return this.listItemElement_.current;
componentDidUpdate(prevProps) {
const {
shouldFocus,
shouldFollowHref,
shouldToggleCheckbox,
} = this.props;
if (shouldFocus !== prevProps.shouldFocus && shouldFocus) {
this.focus();
}
if (shouldFollowHref !== prevProps.shouldFollowHref && shouldFollowHref) {
this.followHref();
}
if (shouldToggleCheckbox !== prevProps.shouldToggleCheckbox && shouldToggleCheckbox) {
this.toggleCheckbox();
}
}

get classes() {
const {className} = this.props;
return classnames('mdc-list-item', className);
const {className, classNamesFromList} = this.props;
return classnames('mdc-list-item', className, classNamesFromList);
}

focus() {
Expand All @@ -64,19 +72,23 @@ export default class ListItem extends Component {
const {
/* eslint-disable */
className,
classNamesFromList,
childrenTabIndex,
init,
id,
shouldFocus,
shouldFollowHref,
shouldToggleCheckbox,
/* eslint-enable */
attributesFromList,
children,
...otherProps
} = this.props;

return (
<li
className={this.classes}
ref={this.listItemElement_}
{...otherProps}
{...attributesFromList} // overrides attributes in otherProps
ref={this.listItemElement_}
>
{React.Children.map(children, this.renderChild)}
</li>
Expand All @@ -93,15 +105,32 @@ export default class ListItem extends Component {
}

ListItem.propTypes = {
id: PropTypes.string,
childrenTabIndex: PropTypes.number,
children: PropTypes.node,
className: PropTypes.string,
init: PropTypes.func,
classNamesFromList: PropTypes.array,
attributesFromList: PropTypes.object,
childrenTabIndex: PropTypes.number,
tabIndex: PropTypes.number,
shouldFocus: PropTypes.bool,
shouldFollowHref: PropTypes.bool,
shouldToggleCheckbox: PropTypes.bool,
onKeyDown: PropTypes.func,
onClick: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
};

ListItem.defaultProps = {
id: '',
childrenTabIndex: -1,
className: '',
classNamesFromList: [],
attributesFromList: {},
childrenTabIndex: -1,
tabIndex: -1,
shouldFocus: false,
shouldFollowHref: false,
shouldToggleCheckbox: false,
onKeyDown: () => {},
onClick: () => {},
onFocus: () => {},
onBlur: () => {},
};
25 changes: 17 additions & 8 deletions packages/list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class MyApp extends Component {
}
```

> _NOTE_: Please use the `ListItem` component to specify list items. `List` will not recognize custom list item components.
## Variants

### Two-Line List
Expand Down Expand Up @@ -140,7 +142,9 @@ class MyApp extends Component {

### Single Selection

You can use the `singleSelection` Boolean prop for `List` to allow for selection of list items. You can also set the `selectedIndex` of the list programmatically.
You can use the `singleSelection` Boolean prop for `List` to allow for selection of list items. You can also set the `selectedIndex` of the list programmatically and include a `handleSelect` callback.

> _NOTE_: If you are inserting or removing list items, you must update the `selectedIndex` accordingly.
```js
class MyApp extends React.Component {
Expand All @@ -153,6 +157,7 @@ class MyApp extends React.Component {
<List
singleSelection
selectedIndex={this.state.selectedIndex}
handleSelect={(selectedIndex) => this.setState({selectedIndex})}
>
<ListItem>
<ListItemText primaryText='Photos'/>
Expand All @@ -176,27 +181,31 @@ class MyApp extends React.Component {
Prop Name | Type | Description
--- | --- | ---
className | String | Classes to be applied to the list element
nonInterative | Boolean | Disables interactivity affordances
nonInteractive | Boolean | Disables interactivity affordances
dense | Boolean | Styles the density of the list, making it appear more compact
avatarList | Boolean | Configures the leading tiles of each row to display images instead of icons. This will make the graphics of the list items larger
twoLine | Boolean | Styles the list with two lines
singleSelection | Boolean | Allows for single selection of list items
wrapFocus | Boolean | Sets the list to allow the up arrow on the first element to focus the last element of the list and vice versa
selectedIndex | Number | Toggles the selected state of the list item at the given index
handleSelect | Function(selectedIndex: Number) => void | Callback for handling a list item selection event
aria-orientation | String | Indicates the list orientation
onClick | Function(evt: Event) => void | Callback for handling a click event
onKeyDown | Function(evt: Event) => void | Callback for handling a keydown event
onFocus | Function(evt: Event) => void | Callback for handling a focus event
onBlur | Function(evt: Event) => void | Callback for handling a blur event

### ListItem

Prop Name | Type | Description
--- | --- | ---
id | String | Unique identifier for the list item. Defaults to the index
className | String | Classes to be applied to the list item element
classNamesFromList | Array<String> | Additional classes to be applied to the list item element, passed down from list
attributesFromList | Additional attributes to be applied to the list item element, passed down from list
childrenTabIndex | Number | Tab index to be applied to all children of the list item
init | Function() => void | Callback executed when list item mounts
shouldFocus | Whether to focus the list item
shouldFollowHref | Whether to follow the link indicated by the list item
shouldToggleCheckbox | Whether to toggle the checkbox on the list item
onClick | Function(evt: Event) => void | Callback for handling a click event
onKeyDown | Function(evt: Event) => void | Callback for handling a keydown event
onFocus | Function(evt: Event) => void | Callback for handling a focus event
onBlur | Function(evt: Event) => void | Callback for handling a blur event

### ListItemText

Expand Down
Loading

0 comments on commit 1f563d3

Please sign in to comment.