import {useCallback, useRef, useState} from 'react'; import isPropValid from '@emotion/is-prop-valid'; import styled from '@emotion/styled'; import Button from 'sentry/components/button'; import Input, {InputProps} from 'sentry/components/input'; import {IconSearch} from 'sentry/icons'; import {IconClose} from 'sentry/icons/iconClose'; import {t} from 'sentry/locale'; interface SearchBarProps extends Omit { defaultQuery?: string; onChange?: (query: string) => void; onSearch?: (query: string) => void; query?: string; width?: string; } function SearchBar({ query: queryProp, defaultQuery = '', onChange, onSearch, width, size, className, ...inputProps }: SearchBarProps) { const inputRef = useRef(null); const [query, setQuery] = useState(queryProp ?? defaultQuery); const onQueryChange = useCallback( (e: React.ChangeEvent) => { const {value} = e.target; setQuery(value); onChange?.(value); }, [onChange] ); const onSubmit = useCallback( (e: React.FormEvent) => { e.preventDefault(); inputRef.current?.blur(); onSearch?.(query); }, [onSearch, query] ); const clearSearch = useCallback(() => { setQuery(''); onChange?.(''); onSearch?.(''); }, [onChange, onSearch]); return ( {!!query && ( } aria-label={t('Clear')} inputSize={size} /> )} ); } const FormWrap = styled('form')` display: block; position: relative; `; const StyledInput = styled(Input)<{showClearButton: boolean}>` width: ${p => (p.width ? p.width : undefined)}; padding-left: ${p => `calc( ${p.theme.formPadding[p.size ?? 'md'].paddingLeft}px * 1.5 + ${p.theme.iconSizes.sm} )`}; ${p => p.showClearButton && ` padding-right: calc( ${p.theme.formPadding[p.size ?? 'md'].paddingRight}px * 1.5 + ${p.theme.iconSizes.xs} ); `} `; const StyledIconSearch = styled(IconSearch, { shouldForwardProp: prop => typeof prop === 'string' && isPropValid(prop), })<{inputSize: InputProps['size']}>` position: absolute; top: 50%; left: ${p => p.theme.formPadding[p.inputSize ?? 'md'].paddingLeft}px; transform: translateY(-50%); pointer-events: none; `; const SearchClearButton = styled(Button)<{inputSize: InputProps['size']}>` position: absolute; top: 50%; transform: translateY(-50%); right: ${p => p.theme.formPadding[p.inputSize ?? 'md'].paddingRight}px; font-size: ${p => p.theme.fontSizeLarge}; color: ${p => p.theme.subText}; &:hover { color: ${p => p.theme.textColor}; } `; export default SearchBar;