diff --git a/.sass-lint.yml b/.sass-lint.yml
index 174275eba..964332061 100644
--- a/.sass-lint.yml
+++ b/.sass-lint.yml
@@ -42,7 +42,9 @@ rules:
force-pseudo-nesting: 2
# Name Formats
- class-name-format: 2
+ # TODO: When inline linting is supported set as error (https://github.com/sasstools/sass-lint/pull/402) and ignore
+ # in Select.scss
+ class-name-format: 1
function-name-format: 2
mixin-name-format: 2
placeholder-name-format: 2
diff --git a/package.json b/package.json
index 1e7b1b1fb..36ce1a892 100644
--- a/package.json
+++ b/package.json
@@ -89,6 +89,7 @@
"dependencies": {
"lodash": "^3.10.1",
"react": "^0.14.6",
- "react-dom": "^0.14.6"
+ "react-dom": "^0.14.6",
+ "react-select": "^1.0.0-beta8"
}
}
diff --git a/src/components/Main.js b/src/components/Main.js
index 56e657303..c1aa2a558 100644
--- a/src/components/Main.js
+++ b/src/components/Main.js
@@ -8,21 +8,50 @@ import {
Tab,
Radio,
RadioGroup,
+ Select,
Toggle,
} from './distributionEntry';
require('styles/App.scss');
+const selectCountriesOptions = [
+ { value: 'au', label: 'Australia' },
+ { value: 'uk', label: 'United Kingdom' },
+ { value: 'us', label: 'United States' },
+ { value: 'lt', label: 'Lesotho', disabled: true },
+];
+
+const selectFlavoursOptions = [
+ { label: 'Chocolate', value: 'chocolate' },
+ { label: 'Vanilla', value: 'vanilla' },
+ { label: 'Strawberry', value: 'strawberry' },
+ { label: 'Caramel', value: 'caramel' },
+ { label: 'Cookies and Cream', value: 'cookiescream' },
+ { label: 'Peppermint', value: 'peppermint' },
+];
+
class AppComponent extends React.Component {
constructor(props) {
super(props);
+ this.setSelectedCountry = this.setSelectedCountry.bind(this);
+ this.setSelectedFlavours = this.setSelectedFlavours.bind(this);
this.toggleSimpleModal = this.toggleSimpleModal.bind(this);
this.state = {
+ selectedCountry: 'au',
+ selectedFlavours: 'vanilla',
showSimpleModal: false,
};
}
+ setSelectedCountry(newValue) {
+ this.setState({ selectedCountry: newValue.value });
+ }
+
+ setSelectedFlavours(newValue) {
+ this.setState({ selectedFlavours: newValue });
+ }
+
toggleSimpleModal() {
this.setState({ showSimpleModal: !this.state.showSimpleModal });
}
@@ -107,6 +136,7 @@ class AppComponent extends React.Component {
+
Checkboxes
@@ -120,6 +150,8 @@ class AppComponent extends React.Component {
+
+
Radio Buttons
@@ -149,10 +181,40 @@ class AppComponent extends React.Component {
+
Toggle
+
+
+
Select
+
+
+
+
+
+
+
);
}
diff --git a/src/components/distributionEntry.js b/src/components/distributionEntry.js
index 34fc11004..667ff5b9a 100644
--- a/src/components/distributionEntry.js
+++ b/src/components/distributionEntry.js
@@ -3,6 +3,7 @@
require('styles/_bootstrap-custom.scss');
require('styles/_icheck-custom.scss');
require('styles/_react-toggle-custom.scss');
+require('styles/components/Select.scss');
import Button from 'react-bootstrap/lib/Button';
import Checkbox from 'react-icheck/lib/Checkbox';
@@ -24,6 +25,8 @@ import {
Slicey,
} from 'alexandria-adslot';
+import Select from 'react-select';
+
module.exports = {
Alert,
Breadcrumb,
@@ -37,6 +40,7 @@ module.exports = {
Radio,
RadioGroup,
Search,
+ Select,
Slicey,
Tab,
Tabs,
diff --git a/src/styles/App.scss b/src/styles/App.scss
index be821ee2f..9bd537614 100644
--- a/src/styles/App.scss
+++ b/src/styles/App.scss
@@ -22,4 +22,8 @@ body {
> .btn-panel + .btn-panel {
margin-top: $etalon-spacing;
}
+
+ > .example-component-panel {
+ margin-bottom: $etalon-spacing / 2;
+ }
}
diff --git a/src/styles/components/Select.scss b/src/styles/components/Select.scss
new file mode 100644
index 000000000..f141253c8
--- /dev/null
+++ b/src/styles/components/Select.scss
@@ -0,0 +1,83 @@
+@import '../variable';
+
+// control options
+$select-input-border-color: $color-border-lighter;
+$select-input-border-radius: $border-radius-base;
+$select-input-border-focus: $select-input-border-color;
+$select-input-height: 30px;
+$select-padding-vertical: 4px;
+$select-padding-horizontal: 7px;
+$select-text-color: $color-text;
+
+// menu options
+$select-option-color: $color-text-light;
+$select-option-focused-color: $select-option-color;
+$select-option-focused-bg: $color-gray-white;
+
+// clear "x" button
+$select-clear-color: $color-text-light;
+$select-clear-hover-color: $color-negative;
+
+// arrow indicator
+$select-arrow-color: $color-text-light;
+$select-arrow-color-hover: $color-text;
+
+// multi-select item
+$select-item-gutter: 4px;
+$select-item-color: $color-text-inverse;
+$select-item-hover-color: $color-text-light;
+$select-item-bg: $color-gray-darker;
+$select-item-hover-bg: $select-item-bg;
+$select-item-font-size: 11px;
+$select-item-padding-vertical: 0;
+$select-item-padding-horizontal: 5px;
+$select-item-border-radius: 0;
+
+
+@import './node_modules/react-select/scss/default';
+
+
+.Select {
+ &:not(.is-disabled) {
+ .Select-control {
+ box-shadow: 0 1px 0 0 $color-border-light;
+
+ &:hover,
+ &:focus {
+ box-shadow: 0 2px 0 0 $color-border-light;
+ }
+ }
+
+ &.is-open,
+ &.is-focused {
+ &:not(.is-open) {
+ > .Select-control {
+ border-color: $color-border-lighter;
+ }
+ }
+ }
+ }
+
+ &--multi {
+ $multi-select-value-height: $select-input-height - ($select-item-padding-horizontal * 2);
+
+ .Select-value {
+ border: 0;
+ height: $multi-select-value-height;
+
+ &-icon,
+ &-label {
+ line-height: 1;
+ margin-top: 3px;
+ }
+
+ &-icon {
+ border: 0;
+ float: right;
+ font-size: $font-size-subheader;
+ text-align: left;
+ width: 13px;
+ }
+ }
+ }
+}
diff --git a/test/components/MainTest.js b/test/components/MainTest.js
index 378301327..7129aac8a 100644
--- a/test/components/MainTest.js
+++ b/test/components/MainTest.js
@@ -3,11 +3,13 @@
import createComponent from 'helpers/shallowRenderHelper';
import Main from 'components/Main';
-import { isElementOfType } from 'react-addons-test-utils';
+import React from 'react';
+import { isElementOfType, createRenderer } from 'react-addons-test-utils';
import {
Checkbox,
Radio,
RadioGroup,
+ Select,
Toggle,
} from '../../src/components/distributionEntry';
@@ -51,4 +53,60 @@ describe('MainComponent', () => {
const toggleComponent = toggleExampleContainer.props.children;
expect(isElementOfType(toggleComponent, Toggle)).to.equal(true);
});
+
+ it('should set and change values for single select', () => {
+ const getRenderOutputAndCheck = ({ renderer, expectedValue }) => {
+ const componentRenderOutput = renderer.getRenderOutput();
+
+ const selectElContainer = componentRenderOutput.props.children[20];
+ const selectComponent = selectElContainer.props.children;
+ expect(isElementOfType(selectComponent, Select)).to.equal(true);
+ expect(selectComponent.props.value).to.equal(expectedValue);
+
+ return { selectComponent };
+ };
+
+ const renderer = createRenderer();
+ renderer.render();
+
+ const { selectComponent } = getRenderOutputAndCheck({
+ renderer,
+ expectedValue: 'au',
+ });
+
+ selectComponent.props.onChange({ value: 'uk' });
+
+ getRenderOutputAndCheck({
+ renderer,
+ expectedValue: 'uk',
+ });
+ });
+
+ it('should set and change values for multi select', () => {
+ const getRenderOutputAndCheck = ({ renderer, expectedValue }) => {
+ const componentRenderOutput = renderer.getRenderOutput();
+
+ const selectElContainer = componentRenderOutput.props.children[21];
+ const selectComponent = selectElContainer.props.children;
+ expect(isElementOfType(selectComponent, Select)).to.equal(true);
+ expect(selectComponent.props.value).to.eql(expectedValue);
+
+ return { selectComponent };
+ };
+
+ const renderer = createRenderer();
+ renderer.render();
+
+ const { selectComponent } = getRenderOutputAndCheck({
+ renderer,
+ expectedValue: 'vanilla',
+ });
+
+ selectComponent.props.onChange('vanilla,chocolate');
+
+ getRenderOutputAndCheck({
+ renderer,
+ expectedValue: 'vanilla,chocolate',
+ });
+ });
});