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 67d9385ea..0b36a4727 100644
--- a/package.json
+++ b/package.json
@@ -90,6 +90,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..166d7562a 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,52 +136,73 @@ class AppComponent extends React.Component {
+
Checkboxes
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
Radio Buttons
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
Toggle
-
-
-
+ Left Right
+
+
+ Select
+
+
+
+
+
);
}
diff --git a/src/components/distributionEntry.js b/src/components/distributionEntry.js
index 139609bee..ee9e027f6 100644
--- a/src/components/distributionEntry.js
+++ b/src/components/distributionEntry.js
@@ -2,6 +2,7 @@
require('styles/_bootstrap-custom.scss');
require('styles/_icheck-custom.scss');
+require('styles/_react-select-custom.scss');
require('styles/_react-toggle-custom.scss');
import Button from 'react-bootstrap/lib/Button';
@@ -24,6 +25,8 @@ import {
Totals,
} 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 1dccc6b15..781d4ef98 100644
--- a/src/styles/App.scss
+++ b/src/styles/App.scss
@@ -23,4 +23,8 @@ body {
> .btn-panel + .btn-panel {
margin-top: $spacing-etalon;
}
+
+ > br {
+ line-height: $spacing-etalon;
+ }
}
diff --git a/src/styles/_react-select-custom.scss b/src/styles/_react-select-custom.scss
new file mode 100644
index 000000000..8b3c9291c
--- /dev/null
+++ b/src/styles/_react-select-custom.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 $color-border-light;
+
+ &:hover,
+ &:focus {
+ box-shadow: 0 2px $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/src/styles/bootstrapOverrides/Button.scss b/src/styles/bootstrapOverrides/Button.scss
index cd7ab52b5..54fb6e091 100644
--- a/src/styles/bootstrapOverrides/Button.scss
+++ b/src/styles/bootstrapOverrides/Button.scss
@@ -67,7 +67,7 @@
}
.btn {
- box-shadow: 0 1px 0 $color-border-light;
+ box-shadow: 0 1px $color-border-light;
margin-right: 5px;
// Make border the same colour as the fill.
@@ -86,7 +86,7 @@
&:hover,
&:focus {
- box-shadow: 0 2px 0 $color-border-light;
+ box-shadow: 0 2px $color-border-light;
transform: translateY(-1px);
}
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',
+ });
+ });
});