Skip to content

Commit

Permalink
feat(hybridDropdown): add HybridSelect and HybridOption components (#704
Browse files Browse the repository at this point in the history
)

* feat(hybridDropdown): add HybridSelect and HybridOption components

* feat(hybridDropdown): add test cases

* remove Fragment

* refactor function hybridselectexample

* documentation: grammatical fix

* feat(hybridDropDown): seperate style file
  • Loading branch information
chiragg928 authored Feb 11, 2021
1 parent bcce254 commit 06df37f
Show file tree
Hide file tree
Showing 10 changed files with 1,744 additions and 98 deletions.
132 changes: 35 additions & 97 deletions catalog/pages/inputs/HybridSelectExample.js
Original file line number Diff line number Diff line change
@@ -1,121 +1,59 @@
// this components was created for hybrid dropdown demonstration purpose
import React, { Component } from "react";
import styled from "styled-components";
import {
Select,
DropDownGroup,
DropDownOption,
DropDownLabel
DropDownLabel,
HybridSelect,
HybridOption
} from "../../../src/components/Input";

const HybridSelectWrapper = styled.div`
position: relative;
`;

export default class HybridSelectExample extends Component {
state = {
showNativeSelect: true,
selectedValue: [],
isOpen: false,
mouseOnDropdown: false
};

// onChange function called when value of dropdown is changed
onChange = value => {
this.setState({ selectedValue: value });
};

// update function called when value of native select is changed
updateValue = e => {
this.setState({ selectedValue: [e.target.value] }); // saving value in array to match dropdown's format
};

// To show native select
showNativeSelect = () => {
// Updating value when we know mouse left dropdown
this.setState({ mouseOnDropdown: false });
if (!this.state.isOpen) {
this.setState({ showNativeSelect: true });
}
value: []
};

// To hide native select - called when mouse enters native select
hideNativeSelect = () => {
this.setState({ showNativeSelect: false, mouseOnDropdown: true });
};

// Set isOpen state to true when dropdown menu opens
dropdownMenuOpen = () => {
this.setState({ isOpen: true });
};

// Set isOpen state to false when dropdown menu closes
dropdownMenuClose = () => {
this.setState({ isOpen: false }, () => {
if (!this.state.mouseOnDropdown) {
this.showNativeSelect();
}
});
};
onChange = value => this.setState({ value });

render() {
const { showNativeSelect, selectedValue } = this.state;
const { value } = this.state;
return (
<HybridSelectWrapper>
<DropDownLabel id="selectLabel" htmlFor="selectElement" size="large">
<>
<DropDownLabel id="selectLabel" htmlFor="demoSelect" size="large">
Hybrid Select
</DropDownLabel>
<Select
id="selectElement"
size="large"
hybrid
fullWidth
showSelect={showNativeSelect}
value={selectedValue[0]}
onChange={this.updateValue}
onMouseEnter={this.hideNativeSelect}
aria-label="Select an option"
>
<option value="" aria-label="">
Select an option
</option>
<option value="0">Option One</option>
<option value="1">Option Two</option>
<option value="2">Option Three</option>
<option value="3">Option Four</option>
<option value="4">Option Five</option>
</Select>
<DropDownGroup
<HybridSelect
size="large"
placeholder="Select an option"
hybrid
fullWidth
value={selectedValue}
valueOverride={selectedValue}
hideDropdown={showNativeSelect}
fullWidth // for hybrid select use fullWidth true and control width using hybridWrapperProps
value={value}
onChange={this.onChange}
dropdownMenuOpen={this.dropdownMenuOpen}
dropdownMenuClose={this.dropdownMenuClose}
onMouseLeave={this.showNativeSelect}
aria-describedby="selectLabel"
selectProps={{ id: "demoSelect" }}
>
<DropDownOption value="0" index={0}>
<HybridOption
value="0"
index={0}
optionText="Option One"
optionProps={{ className: "classOnSelectOption" }}
>
Option One
</DropDownOption>
<DropDownOption value="1" index={1}>
</HybridOption>
<HybridOption
value="1"
index={1}
dropdownOptionProps={{ className: "classOnDropdownOption" }}
>
Option Two
</DropDownOption>
<DropDownOption value="2" index={2}>
Option Three
</DropDownOption>
<DropDownOption value="3" index={3}>
</HybridOption>
<HybridOption value="2" index={2} optionText="Option Three">
{/* Add prop optionText while children is not plain text */}
<div>Option Three</div>
</HybridOption>
<HybridOption value="3" index={3}>
Option Four
</DropDownOption>
<DropDownOption value="4" index={4}>
</HybridOption>
<HybridOption value="4" index={4}>
Option Five
</DropDownOption>
</DropDownGroup>
</HybridSelectWrapper>
</HybridOption>
</HybridSelect>
</>
);
}
}
4 changes: 4 additions & 0 deletions catalog/pages/inputs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
DropDownOption,
DropDownLabel,
Select,
HybridSelect,
HybridOption,
Toggle,
ButtonGroup,
QtySelector
Expand Down Expand Up @@ -47,6 +49,8 @@ export default {
DropDownOption,
DropDownLabel,
Select,
HybridSelect,
HybridOption,
HybridSelectExample,
Toggle,
ToggleWrapperExample,
Expand Down
76 changes: 75 additions & 1 deletion catalog/pages/inputs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,81 @@ span: 6
</Select>
</Column>
</Row>
<Spacing top={{small: "normal"}} />
</Container>
</ThemeProvider>
```

## Hybrid Select

### Props

```table
span: 6
rows:
- Prop: value
Type: array
Default: "[ ]"
Notes: Specifies array of initial string values
- Prop: onChange
Type: function
Default: null
Notes: Invoked with an array of updatedSelection when an option is selected by the user
- Prop: placeholder
Type: string
Default: ""
Notes: Shows placeholder in dropdown and adds a blank option in native select
- Prop: showOptionPlaceholder
Type: boolean
Default: "`true`"
Notes: Set this to false in order to hide blank option from native select
- Prop: optionPlaceholderProps
Type: object
Default: "{ }"
Notes: Extra props passed to the blank option in native select
- Prop: hybridWrapperProps
Type: object
Default: "{ }"
Notes: Extra props passed to the wrapper of dropdown and select
- Prop: selectProps
Type: object
Default: "{ }"
Notes: Extra props passed only to the select
- Prop: dropdownProps
Type: object
Default: "{ }"
Notes: Extra props passed only to the dropdown
```

## Hybrid Option

### Props

```table
span: 6
rows:
- Prop: value
Type: string
Default: N/A
Notes: Required
- Prop: optionText
Type: string
Default: ""
Notes: When passed this text will be used in option and children will be ignored
- Prop: optionProps
Type: object
Default: "{ }"
Notes: Extra props passed only to the options of select
- Prop: dropdownOptionProps
Type: object
Default: "{ }"
Notes: Extra props passed only to the options of dropdown
```

```react
span: 6
---
<ThemeProvider theme={{ themeName: 'tm' }}>
<Container>
<Row >
<Column medium={4}>
<HybridSelectExample />
Expand Down
7 changes: 7 additions & 0 deletions src/components/Input/HybridDropDown/HybridDropDown.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from "styled-components";

const HybridSelectWrapper = styled.div`
position: relative;
`;

export default HybridSelectWrapper;
52 changes: 52 additions & 0 deletions src/components/Input/HybridDropDown/HybridOption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import DropDownOption from "../DropDown/DropDownOption";

class HybridOption extends PureComponent {
renderNativeOption = (optionText, children, props) => (
<option {...props}> {optionText || children} </option>
);

renderDropDownOption = (children, props) => (
<DropDownOption {...props}> {children} </DropDownOption>
);

render() {
const {
optionFor,
optionText,
optionProps,
dropdownOptionProps,
children,
...props
} = this.props;
if (optionFor === "select") {
return this.renderNativeOption(optionText, children, {
...props,
...optionProps
});
}
return this.renderDropDownOption(children, {
...props,
...dropdownOptionProps
});
}
}
HybridOption.propTypes = {
value: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
optionText: PropTypes.string,
optionFor: PropTypes.string,
/* eslint-disable react/forbid-prop-types */
optionProps: PropTypes.object,
dropdownOptionProps: PropTypes.object
/* eslint-enable react/forbid-prop-types */
};
HybridOption.defaultProps = {
optionText: "",
optionFor: "select",
optionProps: {},
dropdownOptionProps: {}
};

export default HybridOption;
Loading

0 comments on commit 06df37f

Please sign in to comment.