Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release-rc4
Browse files Browse the repository at this point in the history
  • Loading branch information
fallion committed Feb 28, 2018
2 parents 1acc961 + 69f3a78 commit 28d9286
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 4 deletions.
5 changes: 4 additions & 1 deletion blkn/.babelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"presets": ["react", "env"],
"plugins": ["styled-jsx/babel"]
"plugins": [
"styled-jsx/babel",
"transform-class-properties"
]
}
3 changes: 3 additions & 0 deletions blkn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@
"author": "kiwi.com",
"license": "MIT",
"dependencies": {
"classnames": "^2.2.5",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-icons": "^2.2.7",
"styled-jsx": "^2.2.4"
},
"devDependencies": {
"@storybook/addon-actions": "^3.3.14",
"@storybook/react": "^3.3.13",
"babel-cli": "^6.26.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"concurrently": "^3.5.1",
Expand Down
27 changes: 27 additions & 0 deletions blkn/src/Select/__tests__/Select.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// @flow

import * as React from "react";
import { shallow } from "enzyme";
import Select from "../";

const objectOptions = [
{ value: "1", label: "One" },
{ value: "2", label: "Two" },
{ value: "3", label: "Three" },
{ value: "4", label: "Four" },
{ visible: false, value: "hidden-five", label: "Hidden Five" },
{ disabled: true, value: "disabled-six", label: "Disabled Six" },
];

const mockChange = jest.fn();
describe("Select", () => {
const component = shallow(<Select value="1" options={objectOptions} onChange={mockChange} />);
it("should match snapshot", () => {
expect(component).toMatchSnapshot();
});
it("should set component state and run onChange callback", () => {
component.find("select").simulate("change", { target: { value: objectOptions[0].value } });
expect(component.state().value).toBe(objectOptions[0].value);
expect(mockChange.mock.calls.length).toBe(1);
});
});
76 changes: 76 additions & 0 deletions blkn/src/Select/__tests__/__snapshots__/Select.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Select should match snapshot 1`] = `
<div
className="jsx-2198933393"
>
<label
className="jsx-2198933393"
>
<select
className="jsx-2198933393 "
onChange={[Function]}
required={true}
value="1"
>
<option
className="jsx-2198933393 placeholder"
disabled={true}
value=""
/>
<option
disabled={false}
key="option-1"
label="One"
value="1"
>
One
</option>
<option
disabled={false}
key="option-2"
label="Two"
value="2"
>
Two
</option>
<option
disabled={false}
key="option-3"
label="Three"
value="3"
>
Three
</option>
<option
disabled={false}
key="option-4"
label="Four"
value="4"
>
Four
</option>
<option
disabled={true}
key="option-disabled-six"
label="Disabled Six"
value="disabled-six"
>
Disabled Six
</option>
</select>
<span
className="jsx-2198933393 dropdown-icon"
>
<FaChevronDown
fill="#46515e"
height={20}
/>
</span>
</label>
<JSXStyle
css="label.jsx-2198933393{font-family:Roboto;line-height:1.43;position:relative;color:#46515e;}select.jsx-2198933393{font-size:16px;border-radius:3px;background-color:white;border:solid 1px #bac7d5;line-height:1.25;padding:12px 16px;color:#46515e;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding-right:3em;width:100%;}select.UnSelected.jsx-2198933393{color:#7f91a8;}select.jsx-2198933393::-ms-expand{display:none;}select.hasError.jsx-2198933393{border-color:#d21c1c;}option[value=\\"\\"][disabled].jsx-2198933393{display:none;}.dropdown-icon.jsx-2198933393{position:absolute;right:1em;top:0px;pointer-events:none;}"
styleId="2198933393"
/>
</div>
`;
138 changes: 138 additions & 0 deletions blkn/src/Select/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// @flow
import * as React from "react";
import css from "styled-jsx/css";
import ChevronDown from "react-icons/lib/fa/chevron-down";
import classnames from "classnames";
import Typography from "./../Typography";
import { fontColors } from "../constants";

const WHITE_COLOR = "white";

const HASERROR_CLASS = "hasError";
const UNSELECTED_CLASS = "UnSelected";

type Option = {
value: string,
label?: string,
disabled?: boolean,
visible?: boolean, // eslint-disable-line react/no-unused-prop-types
};
type Props = {
disabled?: boolean,
error?: string,
label?: string,
onChange: (SyntheticInputEvent<HTMLSelectElement>) => any,
options: Array<Option>,
placeholder?: string,
required?: boolean,
value: string,
};
type State = {
value: string,
};

const style = css`
label {
font-family: Roboto;
line-height: 1.43;
position: relative;
color: ${fontColors.primary};
}
select {
font-size: 16px;
border-radius: 3px;
background-color: ${WHITE_COLOR};
border: solid 1px ${fontColors.input};
line-height: 1.25;
padding: 12px 16px;
color: ${fontColors.primary};
appearance: none;
padding-right: 3em;
width: 100%;
}
select.${UNSELECTED_CLASS} {
color: ${fontColors.secondary};
}
/*for IE10*/
select::-ms-expand {
display: none;
}
select.${HASERROR_CLASS} {
border-color: ${fontColors.error};
}
option[value=""][disabled] {
display: none;
}
.dropdown-icon {
position: absolute;
right: 1em;
top: 0px;
pointer-events: none;
}
`;

class Select extends React.Component<Props, State> {
state = {
value: this.props.value,
};
handleChange = (e: SyntheticInputEvent<HTMLSelectElement>) => {
this.setState({ value: e.target.value });
this.props.onChange(e);
};
feedbackLine = () =>
this.props.error && (
<div>
<Typography size="small" type="error">
{this.props.error}
</Typography>
</div>
);
renderOption = ({ value, label, disabled, visible = true }: Option) => {
if (visible) {
return (
<option key={`option-${value}`} value={value} label={label || value} disabled={!!disabled}>
{label || value}
</option>
);
}
return null;
};
render() {
const { disabled, label, options, error, placeholder, required = true } = this.props;
const { value } = this.state;
return (
<div>
<label>
{label && (
<div>
<Typography size="normal" type={value ? "input" : "primary"}>
{label}
</Typography>
</div>
)}
<select
disabled={disabled}
value={value}
required={!!required}
onChange={this.handleChange}
className={classnames(error && HASERROR_CLASS, !value && UNSELECTED_CLASS)}
>
{
<option disabled value="" label={placeholder} className="placeholder">
{placeholder}
</option>
}
{options.map(this.renderOption)}
</select>
<span className="dropdown-icon">
<ChevronDown fill={fontColors.primary} height={20} />
</span>
</label>
{this.feedbackLine()}
<style jsx>{style}</style>
</div>
);
}
}

export default Select;
3 changes: 2 additions & 1 deletion blkn/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { default as Button } from "./Button";
export { default as InputText } from "./InputText";
export { default as InputTextarea } from "./InputTextarea";
export { default as Checkbox } from "./Checkbox";
export { default as Typography } from "./Typography";
export { default as Header } from "./Container/Header";
export { default as Section } from "./Container/Section";
export { default as Select } from "./Select";
export { default as Typography } from "./Typography";
56 changes: 56 additions & 0 deletions blkn/stories/Select.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import { action } from "@storybook/addon-actions";

import Select from "../src/Select";

const objectOptions = [
{ value: 1, label: "One" },
{ value: 2, label: "Two" },
{ value: 3, label: "Three" },
{ value: 4, label: "Four" },
];

const hiddenOptions = [
{ value: "one", label: "One" },
{ value: "two", label: "Two" },
{ value: "three", label: "Three" },
{ visible: false, value: "hidden-four", label: "Hidden Four" },
];
const disabledOptions = [
{ value: "one", label: "One" },
{ value: "two", label: "Two" },
{ value: "three", label: "Three" },
{ disabled: true, value: "hidden-four", label: "Hidden Four" },
];

storiesOf("Select", module)
.add("Default", () => <Select value="" options={objectOptions} onChange={action("onChange")} />)
.add("Default with placeholder", () => (
<Select
value=""
placeholder="MyPlaceHolder"
options={objectOptions}
onChange={action("onChange")}
/>
))
.add("Hidden 'Four' option", () => (
<Select value="" options={hiddenOptions} onChange={action("onChange")} />
))
.add("Disabled 'Four' option", () => (
<Select value="" options={disabledOptions} onChange={action("onChange")} />
))
.add("With error feedback", () => (
<Select
value=""
options={objectOptions}
error="Error message here"
onChange={action("onChange")}
/>
))
.add("With label NOT filled", () => (
<Select label="Choose number" value="" options={objectOptions} onChange={action("onChange")} />
))
.add("With label filled", () => (
<Select label="Choose number" value="2" options={objectOptions} onChange={action("onChange")} />
));
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7588,8 +7588,8 @@ svgo@^0.7.0:
whet.extend "~0.9.9"

svgo@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.0.4.tgz#b4c6c275316bc35022a5413a724abfd78bd26b9f"
version "1.0.5"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.0.5.tgz#7040364c062a0538abacff4401cea6a26a7a389a"
dependencies:
coa "~2.0.1"
colors "~1.1.2"
Expand Down

0 comments on commit 28d9286

Please sign in to comment.