Commit 85146b0b authored by Yannis Barlas's avatar Yannis Barlas

Merge branch 'ui-component-list' into 'master'

feat(list-component): a component that renders items in a list

See merge request !354
parents 4da6102b 7c2a4179
Pipeline #8423 passed with stages
in 18 minutes and 3 seconds
import React from 'react'
import { get } from 'lodash'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { withHandlers } from 'recompose'
import { override } from '@pubsweet/ui-toolkit'
// #region styles
const Root = styled.div.attrs({
'data-test-id': props => props['data-test-id'] || 'list-root',
})`
display: flex;
flex-direction: column;
${override('ui.List')};
`
const Item = styled.div.attrs({
// we could make a helper for this
'data-test-id': props => props['data-test-id'] || 'list-item',
})`
${override('ui.List.Item')};
`
// #endregion
const DefaultListItem = withHandlers({
onItemClick: ({ onItemClick }) => item => () => {
typeof onItemClick === 'function' && onItemClick(item)
},
})(({ onItemClick, ...item }) => (
<Item onClick={onItemClick(item)}>{item.name}</Item>
))
const List = ({
children,
items = [],
itemKey = 'id',
component: Component = DefaultListItem,
...rest
}) => (
<Root>
{items.map(item => (
<Component key={get(item, itemKey)} {...item} {...rest} />
))}
</Root>
)
List.propTypes = {
items: PropTypes.array.isRequired,
itemKey: PropTypes.string,
onItemClick: PropTypes.func,
}
export default List
A component that displays items in a vertical list. Can be customized with a custom list item component.
* Items as props
```js
const items = [{ id: 1, name: 'First item' }, { id: 2, name: 'Second item' }]
;<List items={items} />
```
* Use custom keys (in case your items don't have an id or you just want to be different)
```js
const items = [{ id: 1, name: 'First item' }, { id: 2, name: 'Second item' }]
;<List items={items} itemKey="name" />
```
* Pass function on each item click
```js
const items = [{ id: 1, name: 'First item' }, { id: 2, name: 'Second item' }]
;<List
items={items}
onItemClick={item => console.log('I clicked on: ', item)}
/>
```
* Custom item component
Pass the item component as a render prop.
```js
const items = [{ id: 1, name: 'First item' }, { id: 2, name: 'Second item' }]
const CustomItem = item => (
<span style={{ backgroundColor: 'lavender', fontSize: '20px' }}>
<b>{item.id}</b>
{` ${item.name}`}
</span>
)
;<List items={items} component={CustomItem} />
```
......@@ -9,6 +9,7 @@ export { default as CheckboxGroup } from './CheckboxGroup'
export { default as EditableValue } from './EditableValue'
export { default as Files } from './Files'
export { default as FileUploadList } from './FileUploadList'
export { default as List } from './List'
export { default as Menu } from './Menu'
export { default as PlainButton } from './PlainButton'
export { default as RadioGroup } from './RadioGroup'
......
import React from 'react'
import { shallow } from 'enzyme'
import { List } from '../src/molecules'
describe('<List>', () => {
it('renders', () => {
const wrapper = shallow(<List />)
expect(wrapper).toMatchSnapshot()
})
it('displays all the items', () => {
const items = [
{ id: 1, name: 'First name' },
{ id: 2, name: 'Second name' },
]
const wrapper = shallow(<List items={items} />)
expect(wrapper.children()).toHaveLength(2)
})
})
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<List> renders 1`] = `
ShallowWrapper {
"length": 1,
Symbol(enzyme.__root__): [Circular],
Symbol(enzyme.__unrendered__): <List />,
Symbol(enzyme.__renderer__): Object {
"batchedUpdates": [Function],
"getNode": [Function],
"render": [Function],
"simulateEvent": [Function],
"unmount": [Function],
},
Symbol(enzyme.__node__): Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [],
},
"ref": null,
"rendered": Array [],
"type": [Function],
},
Symbol(enzyme.__nodes__): Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [],
},
"ref": null,
"rendered": Array [],
"type": [Function],
},
],
Symbol(enzyme.__options__): Object {
"adapter": ReactSixteenAdapter {
"options": Object {
"enableComponentDidUpdateOnSetState": true,
},
},
},
}
`;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment