Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

Commit 1f563d3

Browse files
authored
refactor(list): Refactor list item management (#413)
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.
1 parent 003221a commit 1f563d3

File tree

8 files changed

+490
-407
lines changed

8 files changed

+490
-407
lines changed

packages/list/ListGroup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const ListGroup = (props) => {
4141

4242
ListGroup.propTypes = {
4343
className: PropTypes.string,
44-
children: PropTypes.element,
44+
children: PropTypes.node,
4545
tag: PropTypes.string,
4646
};
4747

packages/list/ListItem.js

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,26 @@ import classnames from 'classnames';
2727
export default class ListItem extends Component {
2828
listItemElement_ = React.createRef();
2929

30-
componentDidMount() {
31-
const {init} = this.props;
32-
init && init();
33-
}
34-
35-
get listItemElement() {
36-
return this.listItemElement_.current;
30+
componentDidUpdate(prevProps) {
31+
const {
32+
shouldFocus,
33+
shouldFollowHref,
34+
shouldToggleCheckbox,
35+
} = this.props;
36+
if (shouldFocus !== prevProps.shouldFocus && shouldFocus) {
37+
this.focus();
38+
}
39+
if (shouldFollowHref !== prevProps.shouldFollowHref && shouldFollowHref) {
40+
this.followHref();
41+
}
42+
if (shouldToggleCheckbox !== prevProps.shouldToggleCheckbox && shouldToggleCheckbox) {
43+
this.toggleCheckbox();
44+
}
3745
}
3846

3947
get classes() {
40-
const {className} = this.props;
41-
return classnames('mdc-list-item', className);
48+
const {className, classNamesFromList} = this.props;
49+
return classnames('mdc-list-item', className, classNamesFromList);
4250
}
4351

4452
focus() {
@@ -64,19 +72,23 @@ export default class ListItem extends Component {
6472
const {
6573
/* eslint-disable */
6674
className,
75+
classNamesFromList,
6776
childrenTabIndex,
68-
init,
69-
id,
77+
shouldFocus,
78+
shouldFollowHref,
79+
shouldToggleCheckbox,
7080
/* eslint-enable */
81+
attributesFromList,
7182
children,
7283
...otherProps
7384
} = this.props;
7485

7586
return (
7687
<li
7788
className={this.classes}
78-
ref={this.listItemElement_}
7989
{...otherProps}
90+
{...attributesFromList} // overrides attributes in otherProps
91+
ref={this.listItemElement_}
8092
>
8193
{React.Children.map(children, this.renderChild)}
8294
</li>
@@ -93,15 +105,32 @@ export default class ListItem extends Component {
93105
}
94106

95107
ListItem.propTypes = {
96-
id: PropTypes.string,
97-
childrenTabIndex: PropTypes.number,
98108
children: PropTypes.node,
99109
className: PropTypes.string,
100-
init: PropTypes.func,
110+
classNamesFromList: PropTypes.array,
111+
attributesFromList: PropTypes.object,
112+
childrenTabIndex: PropTypes.number,
113+
tabIndex: PropTypes.number,
114+
shouldFocus: PropTypes.bool,
115+
shouldFollowHref: PropTypes.bool,
116+
shouldToggleCheckbox: PropTypes.bool,
117+
onKeyDown: PropTypes.func,
118+
onClick: PropTypes.func,
119+
onFocus: PropTypes.func,
120+
onBlur: PropTypes.func,
101121
};
102122

103123
ListItem.defaultProps = {
104-
id: '',
105-
childrenTabIndex: -1,
106124
className: '',
125+
classNamesFromList: [],
126+
attributesFromList: {},
127+
childrenTabIndex: -1,
128+
tabIndex: -1,
129+
shouldFocus: false,
130+
shouldFollowHref: false,
131+
shouldToggleCheckbox: false,
132+
onKeyDown: () => {},
133+
onClick: () => {},
134+
onFocus: () => {},
135+
onBlur: () => {},
107136
};

packages/list/README.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class MyApp extends Component {
4949
}
5050
```
5151

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

5456
### Two-Line List
@@ -140,7 +142,9 @@ class MyApp extends Component {
140142

141143
### Single Selection
142144

143-
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.
145+
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.
146+
147+
> _NOTE_: If you are inserting or removing list items, you must update the `selectedIndex` accordingly.
144148
145149
```js
146150
class MyApp extends React.Component {
@@ -153,6 +157,7 @@ class MyApp extends React.Component {
153157
<List
154158
singleSelection
155159
selectedIndex={this.state.selectedIndex}
160+
handleSelect={(selectedIndex) => this.setState({selectedIndex})}
156161
>
157162
<ListItem>
158163
<ListItemText primaryText='Photos'/>
@@ -176,27 +181,31 @@ class MyApp extends React.Component {
176181
Prop Name | Type | Description
177182
--- | --- | ---
178183
className | String | Classes to be applied to the list element
179-
nonInterative | Boolean | Disables interactivity affordances
184+
nonInteractive | Boolean | Disables interactivity affordances
180185
dense | Boolean | Styles the density of the list, making it appear more compact
181186
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
182187
twoLine | Boolean | Styles the list with two lines
183188
singleSelection | Boolean | Allows for single selection of list items
184189
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
185190
selectedIndex | Number | Toggles the selected state of the list item at the given index
191+
handleSelect | Function(selectedIndex: Number) => void | Callback for handling a list item selection event
186192
aria-orientation | String | Indicates the list orientation
187-
onClick | Function(evt: Event) => void | Callback for handling a click event
188-
onKeyDown | Function(evt: Event) => void | Callback for handling a keydown event
189-
onFocus | Function(evt: Event) => void | Callback for handling a focus event
190-
onBlur | Function(evt: Event) => void | Callback for handling a blur event
191193

192194
### ListItem
193195

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

201210
### ListItemText
202211

0 commit comments

Comments
 (0)