From 06df37fedcdea981ffd0d555dac3c0c7d04bee4f Mon Sep 17 00:00:00 2001 From: Chirag Ghanghas Date: Thu, 11 Feb 2021 17:13:46 +0530 Subject: [PATCH] feat(hybridDropdown): add HybridSelect and HybridOption components (#704) * 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 --- catalog/pages/inputs/HybridSelectExample.js | 132 +- catalog/pages/inputs/index.js | 4 + catalog/pages/inputs/index.md | 76 +- .../HybridDropDown/HybridDropDown.styles.js | 7 + .../Input/HybridDropDown/HybridOption.js | 52 + .../Input/HybridDropDown/HybridSelect.js | 172 +++ .../Input/__tests__/HybridDropDown.spec.js | 104 ++ .../__snapshots__/HybridDropDown.spec.js.snap | 1291 +++++++++++++++++ src/components/Input/index.js | 2 + src/index.tsx | 2 + 10 files changed, 1744 insertions(+), 98 deletions(-) create mode 100644 src/components/Input/HybridDropDown/HybridDropDown.styles.js create mode 100644 src/components/Input/HybridDropDown/HybridOption.js create mode 100644 src/components/Input/HybridDropDown/HybridSelect.js create mode 100644 src/components/Input/__tests__/HybridDropDown.spec.js create mode 100644 src/components/Input/__tests__/__snapshots__/HybridDropDown.spec.js.snap diff --git a/catalog/pages/inputs/HybridSelectExample.js b/catalog/pages/inputs/HybridSelectExample.js index 289af92e3..4c43524be 100644 --- a/catalog/pages/inputs/HybridSelectExample.js +++ b/catalog/pages/inputs/HybridSelectExample.js @@ -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 ( - - + <> + Hybrid Select - - - + Option One - - + + Option Two - - - Option Three - - + + + {/* Add prop optionText while children is not plain text */} +
Option Three
+
+ Option Four -
- + + Option Five - -
-
+ + + ); } } diff --git a/catalog/pages/inputs/index.js b/catalog/pages/inputs/index.js index e7de6445d..a067251cb 100644 --- a/catalog/pages/inputs/index.js +++ b/catalog/pages/inputs/index.js @@ -12,6 +12,8 @@ import { DropDownOption, DropDownLabel, Select, + HybridSelect, + HybridOption, Toggle, ButtonGroup, QtySelector @@ -47,6 +49,8 @@ export default { DropDownOption, DropDownLabel, Select, + HybridSelect, + HybridOption, HybridSelectExample, Toggle, ToggleWrapperExample, diff --git a/catalog/pages/inputs/index.md b/catalog/pages/inputs/index.md index a683944ec..409b7dcf1 100644 --- a/catalog/pages/inputs/index.md +++ b/catalog/pages/inputs/index.md @@ -973,7 +973,81 @@ span: 6 - + + +``` + +## 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 +--- + + diff --git a/src/components/Input/HybridDropDown/HybridDropDown.styles.js b/src/components/Input/HybridDropDown/HybridDropDown.styles.js new file mode 100644 index 000000000..9b06938e9 --- /dev/null +++ b/src/components/Input/HybridDropDown/HybridDropDown.styles.js @@ -0,0 +1,7 @@ +import styled from "styled-components"; + +const HybridSelectWrapper = styled.div` + position: relative; +`; + +export default HybridSelectWrapper; diff --git a/src/components/Input/HybridDropDown/HybridOption.js b/src/components/Input/HybridDropDown/HybridOption.js new file mode 100644 index 000000000..4dcb76fc9 --- /dev/null +++ b/src/components/Input/HybridDropDown/HybridOption.js @@ -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) => ( + + ); + + renderDropDownOption = (children, props) => ( + {children} + ); + + 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; diff --git a/src/components/Input/HybridDropDown/HybridSelect.js b/src/components/Input/HybridDropDown/HybridSelect.js new file mode 100644 index 000000000..e83de725f --- /dev/null +++ b/src/components/Input/HybridDropDown/HybridSelect.js @@ -0,0 +1,172 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import HybridSelectWrapper from "./HybridDropDown.styles"; +import DropDownGroup from "../DropDown/DropDownGroup"; +import Select from "../Select/Select"; + +class HybridSelect extends Component { + state = { + showNativeSelect: true, + isOpen: false, + mouseOnDropdown: false + }; + + // onMouseEnter function called when mouse enters native select + onMouseEnter = e => { + const { onMouseEnter } = this.props; + this.hideNativeSelect(); + if (onMouseEnter) { + onMouseEnter(e); + } + }; + + // onMouseLeave function called when mouse leave dropdown + onMouseLeave = e => { + const { onMouseLeave } = this.props; + this.showNativeSelect(); + if (onMouseLeave) { + onMouseLeave(e); + } + }; + + // onChange function called when value is changed + onChange = value => { + const { onChange } = this.props; + if (onChange) { + onChange(value); + } + }; + + // update function called when value of native select is changed + updateValue = e => { + this.onChange([e.target.value]); // passing 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 }); + } + }; + + // 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 = () => { + const { dropdownMenuOpen } = this.props; + this.setState({ isOpen: true }); + if (dropdownMenuOpen) { + dropdownMenuOpen(); + } + }; + + // Set isOpen state to false when dropdown menu closes + dropdownMenuClose = () => { + const { dropdownMenuClose } = this.props; + this.setState({ isOpen: false }, () => { + if (!this.state.mouseOnDropdown) { + this.showNativeSelect(); + } + }); + if (dropdownMenuClose) { + dropdownMenuClose(); + } + }; + + // To add optionFor prop to the children + renderChildren = (extraProps, children) => { + const childrenWithExtraProps = React.Children.map(children, child => { + if (React.isValidElement(child)) { + return React.cloneElement(child, extraProps); + } + return child; + }); + return childrenWithExtraProps; + }; + + render() { + const { showNativeSelect } = this.state; + const { + placeholder, + value, + valueOverride, + showOptionPlaceholder, + optionPlaceholderProps, + hybridWrapperProps, + selectProps, + dropdownProps, + selectRef, + children, + ...props + } = this.props; + + return ( + + + + {this.renderChildren({ optionFor: "dropdown" }, children)} + + + ); + } +} + +HybridSelect.propTypes = { + value: PropTypes.arrayOf(PropTypes.string), + children: PropTypes.node.isRequired, + onChange: PropTypes.func, + placeholder: PropTypes.string, + showOptionPlaceholder: PropTypes.bool, + /* eslint-disable react/forbid-prop-types */ + optionPlaceholderProps: PropTypes.object, + hybridWrapperProps: PropTypes.object, + selectProps: PropTypes.object, + dropdownProps: PropTypes.object + /* eslint-enable react/forbid-prop-types */ +}; + +HybridSelect.defaultProps = { + value: [], + onChange: null, + placeholder: "", + showOptionPlaceholder: true, + optionPlaceholderProps: {}, + hybridWrapperProps: {}, + selectProps: {}, + dropdownProps: {} +}; + +export default HybridSelect; diff --git a/src/components/Input/__tests__/HybridDropDown.spec.js b/src/components/Input/__tests__/HybridDropDown.spec.js new file mode 100644 index 000000000..73081c50c --- /dev/null +++ b/src/components/Input/__tests__/HybridDropDown.spec.js @@ -0,0 +1,104 @@ +import React from "react"; +import renderer from "react-test-renderer"; +import { renderIntoDocument, cleanup, fireEvent } from "react-testing-library"; +import HybridSelect from "../HybridDropDown/HybridSelect"; +import HybridOption from "../HybridDropDown/HybridOption"; + +describe("HybridDropDown", () => { + function testComponentHTML(props = {}) { + return ( + + + Option One + + + Option Two + + + Option Three + + + Option Four + + + Option Five + + + ); + } + function renderTestComponent(props = {}) { + return renderIntoDocument(testComponentHTML(props)); + } + afterEach(cleanup); + afterAll(cleanup); + + it("renders default hybridDropdown", () => { + expect(renderTestComponent()).toMatchSnapshot(); + }); + + it("renders hybridDropdown with placeholder", () => { + expect( + renderTestComponent({ placeholder: "Select an option" }) + ).toMatchSnapshot(); + }); + + it("should call onMouseEnter", () => { + const onMouseEnter = jest.fn(); + const { getByTestId } = renderTestComponent({ onMouseEnter }); + + fireEvent.mouseEnter(getByTestId("test-hybridselect")); + + expect(onMouseEnter).toHaveBeenCalledTimes(1); + }); + + it("should call onChange when option is clicked", () => { + const onChange = jest.fn(); + const dropdownMenuOpen = jest.fn(); + const { getByTestId } = renderTestComponent({ onChange, dropdownMenuOpen }); + + fireEvent.click(getByTestId("test-hybridoption")); + + expect(onChange).toHaveBeenCalledTimes(1); + expect(onChange).toHaveBeenCalledWith(["2"]); + }); + + it("should call onChange when updateValue is called", () => { + const instance = renderer.create(testComponentHTML()).getInstance(); + const spyOnChange = jest.spyOn(instance, "onChange"); + instance.updateValue({ target: { value: "1" } }); + expect(spyOnChange).toHaveBeenCalledTimes(1); + expect(spyOnChange).toHaveBeenCalledWith(["1"]); + spyOnChange.mockRestore(); + }); + + it("should show native select when dropdown close and mouse leave", () => { + const instance = renderer + .create(testComponentHTML({ dropdownMenuClose: jest.fn() })) + .getInstance(); + instance.onMouseEnter(); + instance.dropdownMenuOpen(); + instance.dropdownMenuClose(); + instance.onMouseLeave(); + expect(instance.state.showNativeSelect).toBe(true); + }); + + it("should not show native select when mouse leave dropdown before dropdown close", () => { + const instance = renderer + .create(testComponentHTML({ onMouseLeave: jest.fn() })) + .getInstance(); + instance.onMouseEnter(); + instance.dropdownMenuOpen(); + instance.onMouseLeave(); + expect(instance.state.showNativeSelect).toBe(false); + instance.dropdownMenuClose(); + expect(instance.state.showNativeSelect).toBe(true); + }); +}); diff --git a/src/components/Input/__tests__/__snapshots__/HybridDropDown.spec.js.snap b/src/components/Input/__tests__/__snapshots__/HybridDropDown.spec.js.snap new file mode 100644 index 000000000..3b4b5f15c --- /dev/null +++ b/src/components/Input/__tests__/__snapshots__/HybridDropDown.spec.js.snap @@ -0,0 +1,1291 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`HybridDropDown renders default hybridDropdown 1`] = ` +Object { + "container": .c0 { + position: relative; +} + +.c3 { + height: 44px; + background-color: rgba(255,255,255,1); + border-radius: 2px; + position: relative; + padding: 0px; + box-sizing: border-box; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + cursor: pointer; + -webkit-transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + z-index: 0; +} + +.c3.dropdown--small { + height: 36px; +} + +.c3.full-width { + width: 100%; +} + +.c3.dropdown--border { + border: solid 1px #999999; + padding: 1px; + text-align: left; +} + +.c3.dropdown--no-border { + border: solid 2px rgba(255,255,255,1); + text-align: right; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -ms-flex-pack: end; + justify-content: flex-end; +} + +.c3.dropdown--active { + margin: 0; + padding: 1px; + border: solid 1px #999999; + border-radius: 2px; + z-index: 10; + -webkit-transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease; + transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease; +} + +.dropdown--disabled .c3 { + cursor: not-allowed; + color: rgba(38,38,38,0.4); + -webkit-transition: none; + transition: none; +} + +.dropdown--disabled .c3:not(.dropdown--no-border) { + border-color: rgba(38,38,38,0.4); +} + +.dropdown--disabled .c3 .dropdown__chevron--disabled { + opacity: 0.4; +} + +.dropdown--open-upward .c3 { + border-radius: 2px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12); +} + +.c3:hover:not(.dropdown__label--disabled) { + border: solid 2px #026cdf; + padding: 0; +} + +.c8 { + position: absolute; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + background-color: rgba(255,255,255,1); + border-radius: 2px; + white-space: nowrap; + margin-top: 2px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12); + box-sizing: border-box; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + width: auto; + overflow: hidden; + z-index: 9; + border-color: #999999; + border-style: solid; + border-width: 0; + max-height: 0; + -webkit-transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s ease 0.3s,padding-top 0s ease 0.3s, padding-bottom 0s ease 0.3s; + transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s ease 0.3s,padding-top 0s ease 0.3s, padding-bottom 0s ease 0.3s; +} + +.c8:focus { + box-shadow: 0 0 5px 0 #026cdf; +} + +.c8.dropdown--clicked { + padding-top: 4px; + padding-bottom: 8px; + border-width: 1px; + max-height: 606px; + -webkit-transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s,padding-top 0s,padding-bottom 0s; + transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s,padding-top 0s,padding-bottom 0s; +} + +.c8.dropdown--overflow { + overflow-y: auto; +} + +.dropdown--open-upward .c8 { + bottom: 46px; + border-radius: 2px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12); +} + +.dropdown--open-upward .c8.dropdown__items--small { + bottom: 35px; +} + +.c4 { + display: none; +} + +.c2 { + position: relative; + display: inline-block; + color: #262626; + outline: none; + border-radius: 2px; +} + +.c2:focus { + box-shadow: 0 0 5px 0 #026cdf; +} + +.c2.full-width { + width: 100%; + display: block; +} + +.c2.hybrid { + display: none; +} + +.c2.hybrid.full-width { + display: none; +} + +.c7 { + color: #999999; + -webkit-transition: opacity 0.1s cubic-bezier(0.455,0.03,0.515,0.955); + transition: opacity 0.1s cubic-bezier(0.455,0.03,0.515,0.955); + margin-right: 14px; + min-width: 16px; +} + +.dropdown--small .c7 { + margin-right: 14px; +} + +.dropdown--border:hover .c7:not(.dropdown__chevron--disabled) { + margin-right: 14px; +} + +.dropdown--small.dropdown--border:hover .c7:not(.dropdown__chevron--disabled) { + margin-right: 12px; +} + +.c7.dropdown__icon--hide { + opacity: 0; +} + +.c6 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 14px; + white-space: nowrap; + width: 85%; + overflow: hidden; + text-overflow: ellipsis; + margin: 0 14px; +} + +.dropdown--small .c6 { + font-size: 14px; + margin: 0 12px; +} + +.dropdown--large .c6 { + font-size: 16px; +} + +.dropdown--no-border .c6 { + margin-right: 14px; +} + +.dropdown--no-border .c6.dropdown--small .dropdown--no-border .c5 { + margin-left: 12px; +} + +.dropdown--large.dropdown--border .c6 { + margin-left: 14px; +} + +.dropdown--small.dropdown--border .c6 { + margin-left: 12px; +} + +.dropdown--active.dropdown--no-border .c6 { + margin-right: 14px; +} + +.dropdown--active.dropdown--no-border .c6.dropdown--small .dropdown--active.dropdown--no-border .c5 { + margin-left: 12px; +} + +.dropdown--active.dropdown--no-border:hover .c6:not(.dropdown__text--disabled) { + margin-right: 14px; +} + +.dropdown--small.dropdown--border:hover .c6:not(.dropdown__text--disabled) { + margin-left: 12px; +} + +.dropdown--large.dropdown--border:hover .c6:not(.dropdown__text--disabled) { + margin-left: 14px; +} + +.c6 svg { + margin-right: 12px; +} + +.c9 { + min-height: -webkit-min-content; + min-height: -moz-min-content; + min-height: min-content; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + opacity: 0; + -webkit-transition: opacity 0.3s cubic-bezier(0.455,0.03,0.515,0.955); + transition: opacity 0.3s cubic-bezier(0.455,0.03,0.515,0.955); +} + +.dropdown--clicked .c9 { + -webkit-transition-delay: 0.1s; + transition-delay: 0.1s; + opacity: 1; +} + +.c1 { + position: relative; + display: inline-block; + box-sizing: border-box; + cursor: pointer; + outline: none; + color: #262626; + background-color: rgba(255,255,255,1); + border-radius: 2px; + height: 44px; + padding: 0 44px 0 14px; + font-size: 16px; + -webkit-transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position-y: 50%; + background-position-x: calc(100% - 15px); +} + +.c1.select--small { + height: 36px; + padding: 0 42px 0 13px; + font-size: 14px; +} + +.c1.select--disabled { + cursor: not-allowed; + opacity: 1; + color: rgba(38,38,38,0.4); +} + +.c1.select--disabled:not(.select--chevron--disabled) { + background-image: url('data:image/svg+xml;utf8,'); +} + +.c1:focus { + box-shadow: 0 0 5px 0 #026cdf; +} + +.c1.select--border { + border: solid 1px #999999; + padding: 1px 45px 1px 15px; +} + +.c1.select--border.select--small { + padding: 1px 42px 1px 13px; +} + +.c1.select--border.select--disabled { + border-color: rgba(38,38,38,0.4); +} + +.c1.select--no-border { + border: solid 2px rgba(255,255,255,1); + background-position-x: calc(100% - 14px); +} + +.c1.select--chevron--disabled { + background-image: none; + padding: 0 15px 0 15px; +} + +.c1.select--chevron--disabled.select--small { + padding: 0 12px 0 13px; +} + +.c1.select--chevron--disabled.select--no-border { + padding: 0 14px 0 14px; +} + +.c1.select--chevron--disabled.select--no-border.select--small { + padding: 0 13px 0 12px; +} + +.c1.select--full--width { + width: 100%; +} + +.c1.hybrid { + display: inline-block; + -webkit-transition: none; + transition: none; +} + +.c1:hover:not(.select--disabled) { + border: solid 2px #026cdf; + background-position-x: calc(100% - 14px); + padding: 0 44px 0 14px; +} + +.c1:hover:not(.select--disabled).select--small { + background-position-x: calc(100% - 12px); + padding: 0 39px 0 12px; +} + +.c1:hover:not(.select--disabled).select--no-border.select--small { + background-position-x: calc(100% - 14px); + padding: 0 42px 0 13px; +} + +.c1:hover:not(.select--disabled).select--chevron--disabled { + padding: 0 14px 0 14px; +} + +.c1:hover:not(.select--disabled).select--chevron--disabled.select--small { + padding: 0 11px 0 12px; +} + +.c1:hover:not(.select--disabled).select--chevron--disabled.select--no-border.select--small { + padding: 0 13px 0 12px; +} + +.c1:hover:not(.select--disabled).select--full--width { + background-position-x: calc(100% - 14px); +} + +.c10 { + cursor: pointer; + box-sizing: border-box; +} + +.dropdown__items .c10 { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 36px; + margin: 4px 8px 0 8px; + padding: 7px 10px; + font-size: 14px; + text-align: left; + border: none; + background-color: rgba(255,255,255,1); + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + overflow-x: hidden; + text-overflow: ellipsis; + color: #262626; + line-height: 1.25; +} + +.dropdown__items .c10:focus { + background-color: #026cdf; + color: rgba(255,255,255,1); + outline: none; + border-radius: 2px; +} + +.dropdown__items .c10.dropdown__selected { + color: #262626; + background-color: #ebebeb; + border-radius: 2px; +} + +.dropdown__items.dropdown__items--small .c10 { + height: 32px; + font-size: 14px; + line-height: 1.3; +} + +.dropdown__items.dropdown__items--large .c10 { + font-size: 16px; +} + +
+
+ +
+
+
, + "debug": [Function], + "getAllByAltText": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getAllByValue": [Function], + "getByAltText": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "getByValue": [Function], + "queryAllByAltText": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryAllByValue": [Function], + "queryByAltText": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "queryByValue": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`HybridDropDown renders hybridDropdown with placeholder 1`] = ` +Object { + "container": .c0 { + position: relative; +} + +.c3 { + height: 44px; + background-color: rgba(255,255,255,1); + border-radius: 2px; + position: relative; + padding: 0px; + box-sizing: border-box; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + cursor: pointer; + -webkit-transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + z-index: 0; +} + +.c3.dropdown--small { + height: 36px; +} + +.c3.full-width { + width: 100%; +} + +.c3.dropdown--border { + border: solid 1px #999999; + padding: 1px; + text-align: left; +} + +.c3.dropdown--no-border { + border: solid 2px rgba(255,255,255,1); + text-align: right; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -ms-flex-pack: end; + justify-content: flex-end; +} + +.c3.dropdown--active { + margin: 0; + padding: 1px; + border: solid 1px #999999; + border-radius: 2px; + z-index: 10; + -webkit-transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease; + transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease; +} + +.dropdown--disabled .c3 { + cursor: not-allowed; + color: rgba(38,38,38,0.4); + -webkit-transition: none; + transition: none; +} + +.dropdown--disabled .c3:not(.dropdown--no-border) { + border-color: rgba(38,38,38,0.4); +} + +.dropdown--disabled .c3 .dropdown__chevron--disabled { + opacity: 0.4; +} + +.dropdown--open-upward .c3 { + border-radius: 2px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12); +} + +.c3:hover:not(.dropdown__label--disabled) { + border: solid 2px #026cdf; + padding: 0; +} + +.c8 { + position: absolute; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + background-color: rgba(255,255,255,1); + border-radius: 2px; + white-space: nowrap; + margin-top: 2px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12); + box-sizing: border-box; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + width: auto; + overflow: hidden; + z-index: 9; + border-color: #999999; + border-style: solid; + border-width: 0; + max-height: 0; + -webkit-transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s ease 0.3s,padding-top 0s ease 0.3s, padding-bottom 0s ease 0.3s; + transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s ease 0.3s,padding-top 0s ease 0.3s, padding-bottom 0s ease 0.3s; +} + +.c8:focus { + box-shadow: 0 0 5px 0 #026cdf; +} + +.c8.dropdown--clicked { + padding-top: 4px; + padding-bottom: 8px; + border-width: 1px; + max-height: 606px; + -webkit-transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s,padding-top 0s,padding-bottom 0s; + transition: max-height 0.3s cubic-bezier(0.455,0.03,0.515,0.955), border-width 0s,padding-top 0s,padding-bottom 0s; +} + +.c8.dropdown--overflow { + overflow-y: auto; +} + +.dropdown--open-upward .c8 { + bottom: 46px; + border-radius: 2px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12); +} + +.dropdown--open-upward .c8.dropdown__items--small { + bottom: 35px; +} + +.c4 { + display: none; +} + +.c2 { + position: relative; + display: inline-block; + color: #262626; + outline: none; + border-radius: 2px; +} + +.c2:focus { + box-shadow: 0 0 5px 0 #026cdf; +} + +.c2.full-width { + width: 100%; + display: block; +} + +.c2.hybrid { + display: none; +} + +.c2.hybrid.full-width { + display: none; +} + +.c7 { + color: #999999; + -webkit-transition: opacity 0.1s cubic-bezier(0.455,0.03,0.515,0.955); + transition: opacity 0.1s cubic-bezier(0.455,0.03,0.515,0.955); + margin-right: 14px; + min-width: 16px; +} + +.dropdown--small .c7 { + margin-right: 14px; +} + +.dropdown--border:hover .c7:not(.dropdown__chevron--disabled) { + margin-right: 14px; +} + +.dropdown--small.dropdown--border:hover .c7:not(.dropdown__chevron--disabled) { + margin-right: 12px; +} + +.c7.dropdown__icon--hide { + opacity: 0; +} + +.c6 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 14px; + white-space: nowrap; + width: 85%; + overflow: hidden; + text-overflow: ellipsis; + margin: 0 14px; +} + +.dropdown--small .c6 { + font-size: 14px; + margin: 0 12px; +} + +.dropdown--large .c6 { + font-size: 16px; +} + +.dropdown--no-border .c6 { + margin-right: 14px; +} + +.dropdown--no-border .c6.dropdown--small .dropdown--no-border .c5 { + margin-left: 12px; +} + +.dropdown--large.dropdown--border .c6 { + margin-left: 14px; +} + +.dropdown--small.dropdown--border .c6 { + margin-left: 12px; +} + +.dropdown--active.dropdown--no-border .c6 { + margin-right: 14px; +} + +.dropdown--active.dropdown--no-border .c6.dropdown--small .dropdown--active.dropdown--no-border .c5 { + margin-left: 12px; +} + +.dropdown--active.dropdown--no-border:hover .c6:not(.dropdown__text--disabled) { + margin-right: 14px; +} + +.dropdown--small.dropdown--border:hover .c6:not(.dropdown__text--disabled) { + margin-left: 12px; +} + +.dropdown--large.dropdown--border:hover .c6:not(.dropdown__text--disabled) { + margin-left: 14px; +} + +.c6 svg { + margin-right: 12px; +} + +.c9 { + min-height: -webkit-min-content; + min-height: -moz-min-content; + min-height: min-content; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + opacity: 0; + -webkit-transition: opacity 0.3s cubic-bezier(0.455,0.03,0.515,0.955); + transition: opacity 0.3s cubic-bezier(0.455,0.03,0.515,0.955); +} + +.dropdown--clicked .c9 { + -webkit-transition-delay: 0.1s; + transition-delay: 0.1s; + opacity: 1; +} + +.c1 { + position: relative; + display: inline-block; + box-sizing: border-box; + cursor: pointer; + outline: none; + color: #262626; + background-color: rgba(255,255,255,1); + border-radius: 2px; + height: 44px; + padding: 0 44px 0 14px; + font-size: 16px; + -webkit-transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + transition: border-color 0.3s cubic-bezier(0.455,0.03,0.515,0.955), z-index 0s ease 0.3s; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position-y: 50%; + background-position-x: calc(100% - 15px); +} + +.c1.select--small { + height: 36px; + padding: 0 42px 0 13px; + font-size: 14px; +} + +.c1.select--disabled { + cursor: not-allowed; + opacity: 1; + color: rgba(38,38,38,0.4); +} + +.c1.select--disabled:not(.select--chevron--disabled) { + background-image: url('data:image/svg+xml;utf8,'); +} + +.c1:focus { + box-shadow: 0 0 5px 0 #026cdf; +} + +.c1.select--border { + border: solid 1px #999999; + padding: 1px 45px 1px 15px; +} + +.c1.select--border.select--small { + padding: 1px 42px 1px 13px; +} + +.c1.select--border.select--disabled { + border-color: rgba(38,38,38,0.4); +} + +.c1.select--no-border { + border: solid 2px rgba(255,255,255,1); + background-position-x: calc(100% - 14px); +} + +.c1.select--chevron--disabled { + background-image: none; + padding: 0 15px 0 15px; +} + +.c1.select--chevron--disabled.select--small { + padding: 0 12px 0 13px; +} + +.c1.select--chevron--disabled.select--no-border { + padding: 0 14px 0 14px; +} + +.c1.select--chevron--disabled.select--no-border.select--small { + padding: 0 13px 0 12px; +} + +.c1.select--full--width { + width: 100%; +} + +.c1.hybrid { + display: inline-block; + -webkit-transition: none; + transition: none; +} + +.c1:hover:not(.select--disabled) { + border: solid 2px #026cdf; + background-position-x: calc(100% - 14px); + padding: 0 44px 0 14px; +} + +.c1:hover:not(.select--disabled).select--small { + background-position-x: calc(100% - 12px); + padding: 0 39px 0 12px; +} + +.c1:hover:not(.select--disabled).select--no-border.select--small { + background-position-x: calc(100% - 14px); + padding: 0 42px 0 13px; +} + +.c1:hover:not(.select--disabled).select--chevron--disabled { + padding: 0 14px 0 14px; +} + +.c1:hover:not(.select--disabled).select--chevron--disabled.select--small { + padding: 0 11px 0 12px; +} + +.c1:hover:not(.select--disabled).select--chevron--disabled.select--no-border.select--small { + padding: 0 13px 0 12px; +} + +.c1:hover:not(.select--disabled).select--full--width { + background-position-x: calc(100% - 14px); +} + +.c10 { + cursor: pointer; + box-sizing: border-box; +} + +.dropdown__items .c10 { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 36px; + margin: 4px 8px 0 8px; + padding: 7px 10px; + font-size: 14px; + text-align: left; + border: none; + background-color: rgba(255,255,255,1); + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + overflow-x: hidden; + text-overflow: ellipsis; + color: #262626; + line-height: 1.25; +} + +.dropdown__items .c10:focus { + background-color: #026cdf; + color: rgba(255,255,255,1); + outline: none; + border-radius: 2px; +} + +.dropdown__items .c10.dropdown__selected { + color: #262626; + background-color: #ebebeb; + border-radius: 2px; +} + +.dropdown__items.dropdown__items--small .c10 { + height: 32px; + font-size: 14px; + line-height: 1.3; +} + +.dropdown__items.dropdown__items--large .c10 { + font-size: 16px; +} + +
+
+ +
+ + +
+
+
, + "debug": [Function], + "getAllByAltText": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getAllByValue": [Function], + "getByAltText": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "getByValue": [Function], + "queryAllByAltText": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryAllByValue": [Function], + "queryByAltText": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "queryByValue": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/src/components/Input/index.js b/src/components/Input/index.js index 04c2f7449..b5bf46fb2 100644 --- a/src/components/Input/index.js +++ b/src/components/Input/index.js @@ -9,6 +9,8 @@ export { default as DropDownOption } from "./DropDown/DropDownOption"; export { default as DropDownGroup } from "./DropDown/DropDownGroup"; export { default as DropDownLabel } from "./DropDown/DropDownLabel"; export { default as Select } from "./Select/Select"; +export { default as HybridSelect } from "./HybridDropDown/HybridSelect"; +export { default as HybridOption } from "./HybridDropDown/HybridOption"; export { default as Toggle } from "./Toggle/Toggle"; export { default as ButtonGroup } from "./ButtonGroup/ButtonGroup"; export { default as QtySelector } from "./QtySelector/QtySelector"; diff --git a/src/index.tsx b/src/index.tsx index 61f6844df..b34ad2832 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -196,6 +196,8 @@ export { DropDownOption, DropDownLabel, Select, + HybridSelect, + HybridOption, RadioButton, RadioGroup, CheckBoxButton as CheckBox,