Selectable dropdown list
This commit is contained in:
12
website/.vscode/launch.json
vendored
Normal file
12
website/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": "0.1.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Chrome: Launch",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"webRoot": "${workspaceFolder}/src"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -112,6 +112,16 @@ export class UserForm extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { binder } = this.state
|
const { binder } = this.state
|
||||||
|
const teams = [
|
||||||
|
{ id: 1, name: 'Sign of the Times' },
|
||||||
|
{ id: 2, name: 'Trash Monsters' },
|
||||||
|
{ id: 3, name: 'The Bigger Picker Uppers' },
|
||||||
|
{ id: 4, name: 'Carcass Masters' },
|
||||||
|
{ id: 5, name: 'Dust Bunnies' },
|
||||||
|
{ id: 6, name: 'Pavement Busters' },
|
||||||
|
{ id: 7, name: 'Don\'t Hug That Tree' },
|
||||||
|
{ id: 8, name: 'Broken Swingers' },
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form style={{ width: '100%', height: '100%', overflow: 'scroll' }} id='userForm' onSubmit={this.handleSubmit}>
|
<form style={{ width: '100%', height: '100%', overflow: 'scroll' }} id='userForm' onSubmit={this.handleSubmit}>
|
||||||
@@ -145,9 +155,9 @@ export class UserForm extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
</Column.Item>
|
</Column.Item>
|
||||||
<Column.Item>
|
<Column.Item>
|
||||||
<DropdownList render={(item) => (
|
<DropdownList items={teams} render={(item) => (
|
||||||
<DropdownList.Item style={{ paddingLeft: 8 }}>
|
<DropdownList.Item key={item.id} style={{ paddingLeft: 8 }}>
|
||||||
<DropdownList.Text>Team Name</DropdownList.Text>
|
<DropdownList.Text>{item.name}</DropdownList.Text>
|
||||||
</DropdownList.Item>
|
</DropdownList.Item>
|
||||||
)} />
|
)} />
|
||||||
</Column.Item>
|
</Column.Item>
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ export class Box extends Component {
|
|||||||
background: PropTypes.string,
|
background: PropTypes.string,
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
inputRef: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {
|
let {
|
||||||
children, background,
|
children, background, inputRef, border, style, radius,
|
||||||
borderTop, borderBottom, borderLeft, borderRight,
|
borderTop, borderBottom, borderLeft, borderRight,
|
||||||
border, style, radius,
|
|
||||||
radiusTopLeft, radiusTopRight, radiusBottomLeft, radiusBottomRight } = this.props
|
radiusTopLeft, radiusTopRight, radiusBottomLeft, radiusBottomRight } = this.props
|
||||||
const stringify = (border) => {
|
const stringify = (border) => {
|
||||||
if (!border) {
|
if (!border) {
|
||||||
@@ -66,8 +66,9 @@ export class Box extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={[
|
<div
|
||||||
{
|
ref={inputRef}
|
||||||
|
style={[{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
@@ -79,10 +80,7 @@ export class Box extends Component {
|
|||||||
borderTopRightRadius,
|
borderTopRightRadius,
|
||||||
borderBottomLeftRadius,
|
borderBottomLeftRadius,
|
||||||
borderBottomRightRadius,
|
borderBottomRightRadius,
|
||||||
},
|
}, background && { backgroundColor: background }, style ]}>
|
||||||
background && { backgroundColor: background },
|
|
||||||
style,
|
|
||||||
]}>
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import autobind from 'autobind-decorator'
|
|||||||
@Radium
|
@Radium
|
||||||
export class DropdownList extends Component {
|
export class DropdownList extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
data: PropTypes.array,
|
items: PropTypes.array,
|
||||||
render: PropTypes.func.isRequired,
|
render: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ export class DropdownList extends Component {
|
|||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
open: false,
|
open: false,
|
||||||
|
selectedItem: (props.items && props.items.length > 0) ? props.items[0] : {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,14 +27,15 @@ export class DropdownList extends Component {
|
|||||||
this.setState({ open: !this.state.open })
|
this.setState({ open: !this.state.open })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleItemClick(e, item) {
|
||||||
|
this.setState({ selectedItem: item, open: false })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { data, render } = this.props
|
const { render, items } = this.props
|
||||||
const { open } = this.state
|
const { open, selectedItem } = this.state
|
||||||
const dropDownIconSize = 20
|
const border = { width: sizeInfo.dropdownBorderWidth, color: colorInfo.dropdownBorder }
|
||||||
const dropdownIconMargin = 8
|
|
||||||
const dropdownBackground = 'white'
|
|
||||||
const selectedItem = data ? data[0] : <span />
|
|
||||||
const border = { width: sizeInfo.listBorderWidth, color: colorInfo.listBorder }
|
|
||||||
|
|
||||||
let dropdown = null
|
let dropdown = null
|
||||||
|
|
||||||
@@ -44,23 +46,33 @@ export class DropdownList extends Component {
|
|||||||
borderRight={border}
|
borderRight={border}
|
||||||
borderBottom={border}
|
borderBottom={border}
|
||||||
radius={{ bottomLeft: sizeInfo.formBoxRadius, bottomRight: sizeInfo.formBoxRadius }}
|
radius={{ bottomLeft: sizeInfo.formBoxRadius, bottomRight: sizeInfo.formBoxRadius }}
|
||||||
background={dropdownBackground}
|
background={colorInfo.dropdownBackground}
|
||||||
style={{
|
style={{
|
||||||
height: 200,
|
height: (this.itemHeight - sizeInfo.dropdownBorderWidth * 2) * sizeInfo.dropdownItems,
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
}}
|
fontSize: fontInfo.size.large,
|
||||||
/>
|
fontFamily: fontInfo.family,
|
||||||
|
overflowY: 'scroll',
|
||||||
|
}}>
|
||||||
|
{ items && items.map((item) => (React.cloneElement(render(item), { onClick: (e) => (this.handleItemClick(e, item)), hover: true }))) }
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Box
|
<Box
|
||||||
|
inputRef={(e) => {
|
||||||
|
if (e) {
|
||||||
|
const r = e.getBoundingClientRect()
|
||||||
|
this.itemHeight = r.bottom - r.top
|
||||||
|
}
|
||||||
|
}}
|
||||||
borderTop={border}
|
borderTop={border}
|
||||||
borderLeft={border}
|
borderLeft={border}
|
||||||
borderRight={border}
|
borderRight={border}
|
||||||
borderBottom={open ? { width: sizeInfo.listBorderWidth, color: 'transparent' } : { width: sizeInfo.listBorderWidth, color: colorInfo.listBorder }}
|
borderBottom={open ? { width: sizeInfo.dropdownBorderWidth, color: 'transparent' } : border}
|
||||||
radius={open ? { topLeft: sizeInfo.formBoxRadius, topRight: sizeInfo.formBoxRadius } : sizeInfo.formBoxRadius}
|
radius={open ? { topLeft: sizeInfo.formBoxRadius, topRight: sizeInfo.formBoxRadius } : sizeInfo.formBoxRadius}
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -69,15 +81,15 @@ export class DropdownList extends Component {
|
|||||||
fontFamily: fontInfo.family,
|
fontFamily: fontInfo.family,
|
||||||
}}>
|
}}>
|
||||||
<div style={{ flexGrow: 1 }}>
|
<div style={{ flexGrow: 1 }}>
|
||||||
{render(selectedItem)}
|
{(React.cloneElement(render(selectedItem), { hover: false }))}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img src={open ? upArrowImage : downArrowImage}
|
<img src={open ? upArrowImage : downArrowImage}
|
||||||
style={{
|
style={{
|
||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
width: dropDownIconSize,
|
width: sizeInfo.dropDownIconSize,
|
||||||
height: dropDownIconSize,
|
height: sizeInfo.dropDownIconSize,
|
||||||
margin: dropdownIconMargin,
|
margin: sizeInfo.dropdownIconMargin,
|
||||||
}}
|
}}
|
||||||
onClick={this.handleClick} />
|
onClick={this.handleClick} />
|
||||||
</div>
|
</div>
|
||||||
@@ -93,21 +105,19 @@ DropdownList.Item = Radium(class ListItem extends Component {
|
|||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
|
hover: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, active, onClick } = this.props
|
const { children, active, hover, onClick } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={[
|
||||||
width: '100%',
|
{ width: '100%', background: active ? colorInfo.listBackgroundActive : 'transparent' },
|
||||||
height: '100%',
|
hover && { ':hover': { background: colorInfo.listBackgroundHover } },
|
||||||
background: active ? colorInfo.listBackgroundActive : 'transparent',
|
]}
|
||||||
':hover': {
|
onClick={onClick}>
|
||||||
background: colorInfo.listBackgroundHover
|
|
||||||
},
|
|
||||||
}} onClick={onClick}>
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ let colorInfo = {
|
|||||||
checkboxUnchecked: '#A0A0A0',
|
checkboxUnchecked: '#A0A0A0',
|
||||||
checkboxUncheckedHover: '#808080',
|
checkboxUncheckedHover: '#808080',
|
||||||
checkmark: '#FFFFFF',
|
checkmark: '#FFFFFF',
|
||||||
|
|
||||||
|
listBackground: '#FFFFFF',
|
||||||
|
listBackgroundActive: '#E7E5E5',
|
||||||
|
|
||||||
|
dropdownBackground: '#FFFFFF',
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(colorInfo, {
|
Object.assign(colorInfo, {
|
||||||
@@ -34,10 +39,10 @@ Object.assign(colorInfo, {
|
|||||||
panelButtonBackgroundActive: colorInfo.headerButtonBackgroundActive,
|
panelButtonBackgroundActive: colorInfo.headerButtonBackgroundActive,
|
||||||
panelDisabledButtonBackground: colorInfo.buttonDisabledBackground,
|
panelDisabledButtonBackground: colorInfo.buttonDisabledBackground,
|
||||||
|
|
||||||
listBackground: '#FFFFFF',
|
|
||||||
listBackgroundHover: colorInfo.headerButtonBackgroundHover,
|
listBackgroundHover: colorInfo.headerButtonBackgroundHover,
|
||||||
listBackgroundActive: '#E7E5E5',
|
|
||||||
listBorder: colorInfo.headerBorder,
|
listBorder: colorInfo.headerBorder,
|
||||||
|
|
||||||
|
dropdownBorder: colorInfo.headerBorder,
|
||||||
})
|
})
|
||||||
|
|
||||||
const sizeInfo = {
|
const sizeInfo = {
|
||||||
@@ -80,6 +85,11 @@ const sizeInfo = {
|
|||||||
listIcon: 25,
|
listIcon: 25,
|
||||||
listIconMargin: '5px 10px 5px 10px',
|
listIconMargin: '5px 10px 5px 10px',
|
||||||
|
|
||||||
|
dropDownIconSize: 20,
|
||||||
|
dropdownIconMargin: 5,
|
||||||
|
dropdownItems: 6,
|
||||||
|
dropdownBorderWidth: 1,
|
||||||
|
|
||||||
modalWidth: 450,
|
modalWidth: 450,
|
||||||
modalShadowWidth: 25,
|
modalShadowWidth: 25,
|
||||||
modalMessageIcon: 150,
|
modalMessageIcon: 150,
|
||||||
|
|||||||
Reference in New Issue
Block a user