diff --git a/web/packages/shared/components/ClusterDropdown/ClusterDropdown.tsx b/web/packages/shared/components/ClusterDropdown/ClusterDropdown.tsx index 7387c17778894..fdccb6ae9045b 100644 --- a/web/packages/shared/components/ClusterDropdown/ClusterDropdown.tsx +++ b/web/packages/shared/components/ClusterDropdown/ClusterDropdown.tsx @@ -17,8 +17,9 @@ */ import React, { useState, useEffect } from 'react'; +import styled from 'styled-components'; import { useHistory } from 'react-router'; -import { ButtonSecondary, Flex, Menu, MenuItem, Text } from 'design'; +import { Box, ButtonSecondary, Flex, Menu, MenuItem, Text } from 'design'; import { ChevronDown } from 'design/Icon'; import cfg from 'teleport/config'; import { Cluster } from 'teleport/services/clusters'; @@ -66,6 +67,8 @@ export function ClusterDropdown({ const [options, setOptions] = React.useState( createOptions(initialClusters) ); + const showInput = options.length > 5 ? true : false; + const [clusterFilter, setClusterFilter] = useState(''); const history = useHistory(); const [anchorEl, setAnchorEl] = useState(null); @@ -133,6 +136,17 @@ export function ClusterDropdown({ return null; } + const onClusterFilterChange = (e: React.ChangeEvent) => { + setClusterFilter(e.target.value); + }; + + let filteredOptions = options; + if (clusterFilter) { + filteredOptions = options.filter(cluster => + cluster.label.toLowerCase().includes(clusterFilter.toLowerCase()) + ); + } + return ( @@ -150,7 +164,11 @@ export function ClusterDropdown({ `margin-top: 36px;`} + popoverCss={() => ` + margin-top: ${showInput ? '40px' : '4px'}; + max-height: 265px; + overflow: hidden; + `} transformOrigin={{ vertical: 'top', horizontal: 'left', @@ -163,20 +181,74 @@ export function ClusterDropdown({ open={Boolean(anchorEl)} onClose={handleClose} > - {options.map(cluster => ( - onChangeOption(cluster.value)} + {showInput ? ( + p.theme.space[2]}px; + `} > - - {cluster.label} - - - ))} + + + ) : ( + // without this empty box, the entire positioning is way out of whack + // TODO (avatus): find out why during menu/popover rework + + )} + + {filteredOptions.map(cluster => ( + onChangeOption(cluster.value)} + > + + {cluster.label} + + + ))} + ); } type Option = { value: string; label: string }; + +const ClusterFilter = styled.input( + ({ theme }) => ` + background-color: ${theme.colors.spotBackground[0]}; + padding-left: ${theme.space[3]}px; + width: 100%; + border-radius: 29px; + box-sizing: border-box; + color: ${theme.colors.text.main}; + height: 32px; + font-size: ${theme.fontSizes[1]}px; + outline: none; + border: none; + &:focus { + border: none; + } + + ::placeholder { + color: ${theme.colors.text.muted}; + opacity: 1; + } +` +);