diff --git a/ui/src/shared/components/ColorDropdown.js b/ui/src/shared/components/ColorDropdown.js
deleted file mode 100644
index 48d648410..000000000
--- a/ui/src/shared/components/ColorDropdown.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-
-import classnames from 'classnames'
-import OnClickOutside from 'shared/components/OnClickOutside'
-import FancyScrollbar from 'shared/components/FancyScrollbar'
-import {ErrorHandling} from 'src/shared/decorators/errors'
-
-@ErrorHandling
-class ColorDropdown extends Component {
- constructor(props) {
- super(props)
-
- this.state = {
- visible: false,
- }
- }
-
- handleToggleMenu = () => {
- const {disabled} = this.props
-
- if (disabled) {
- return
- }
- this.setState({visible: !this.state.visible})
- }
-
- handleClickOutside = () => {
- this.setState({visible: false})
- }
-
- handleColorClick = color => () => {
- this.props.onChoose(color)
- this.setState({visible: false})
- }
-
- render() {
- const {visible} = this.state
- const {colors, selected, disabled, stretchToFit} = this.props
-
- const dropdownClassNames = classnames('color-dropdown', {
- open: visible,
- 'color-dropdown--stretch': stretchToFit,
- })
- const toggleClassNames = classnames(
- 'btn btn-sm btn-default color-dropdown--toggle',
- {active: visible, 'color-dropdown__disabled': disabled}
- )
-
- return (
-
-
- {visible ? (
-
-
- {colors.map((color, i) => (
-
-
- {color.name}
-
- ))}
-
-
- ) : null}
-
- )
- }
-}
-
-const {arrayOf, bool, func, shape, string} = PropTypes
-
-ColorDropdown.propTypes = {
- selected: shape({
- hex: string.isRequired,
- name: string.isRequired,
- }).isRequired,
- onChoose: func.isRequired,
- colors: arrayOf(
- shape({
- hex: string.isRequired,
- name: string.isRequired,
- }).isRequired
- ).isRequired,
- stretchToFit: bool,
- disabled: bool,
-}
-
-export default OnClickOutside(ColorDropdown)
diff --git a/ui/src/shared/components/ColorDropdown.tsx b/ui/src/shared/components/ColorDropdown.tsx
new file mode 100644
index 000000000..7fd97e901
--- /dev/null
+++ b/ui/src/shared/components/ColorDropdown.tsx
@@ -0,0 +1,125 @@
+import React, {Component} from 'react'
+
+import classnames from 'classnames'
+import {ClickOutside} from 'src/shared/components/ClickOutside'
+import FancyScrollbar from 'src/shared/components/FancyScrollbar'
+import {ErrorHandling} from 'src/shared/decorators/errors'
+import {ColorNumber} from 'src/types/colors'
+import {DROPDOWN_MENU_MAX_HEIGHT} from 'src/shared/constants/index'
+
+interface Props {
+ selected: ColorNumber
+ disabled: boolean
+ stretchToFit: boolean
+ colors: ColorNumber[]
+ onChoose: (colors: ColorNumber[]) => void
+}
+
+interface State {
+ visible: boolean
+}
+
+@ErrorHandling
+export default class ColorDropdown extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ visible: false,
+ }
+ }
+
+ public render() {
+ const {visible} = this.state
+ const {selected} = this.props
+
+ return (
+
+
+
+ {visible && this.renderMenu}
+
+
+ )
+ }
+
+ private get dropdownClassNames(): string {
+ const {stretchToFit} = this.props
+ const {visible} = this.state
+
+ return classnames('color-dropdown', {
+ open: visible,
+ 'color-dropdown--stretch': stretchToFit,
+ })
+ }
+
+ private get buttonClassNames(): string {
+ const {disabled} = this.props
+ const {visible} = this.state
+
+ return classnames('btn btn-sm btn-default color-dropdown--toggle', {
+ active: visible,
+ 'color-dropdown__disabled': disabled,
+ })
+ }
+
+ private get renderMenu(): JSX.Element {
+ const {colors, selected} = this.props
+
+ return (
+
+
+ {colors.map((color, i) => (
+
+
+ {color.name}
+
+ ))}
+
+
+ )
+ }
+
+ private handleToggleMenu = (): void => {
+ const {disabled} = this.props
+
+ if (disabled) {
+ return
+ }
+ this.setState({visible: !this.state.visible})
+ }
+
+ private handleClickOutside = (): void => {
+ this.setState({visible: false})
+ }
+
+ private handleColorClick = color => (): void => {
+ this.props.onChoose(color)
+ this.setState({visible: false})
+ }
+}