diff --git a/client/src/components/BoardActions/Filters.jsx b/client/src/components/BoardActions/Filters.jsx
index e9083bc..305bf1e 100644
--- a/client/src/components/BoardActions/Filters.jsx
+++ b/client/src/components/BoardActions/Filters.jsx
@@ -1,6 +1,8 @@
-import React, { useCallback, useEffect, useRef } from 'react';
+import React, { useCallback, useRef, useState } from 'react';
import PropTypes from 'prop-types';
+import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
+import { Icon } from 'semantic-ui-react';
import { usePopup } from '../../lib/popup';
import { Input } from '../../lib/custom-ui';
@@ -30,7 +32,14 @@ const Filters = React.memo(
onTextFilterUpdate,
}) => {
const [t] = useTranslation();
- const searchField = useRef(null);
+ const [isSearchFocused, setIsSearchFocused] = useState(false);
+
+ const searchFieldRef = useRef(null);
+
+ const cancelSearch = useCallback(() => {
+ onTextFilterUpdate('');
+ searchFieldRef.current.blur();
+ }, [onTextFilterUpdate]);
const handleRemoveUserClick = useCallback(
(id) => {
@@ -46,17 +55,39 @@ const Filters = React.memo(
[onLabelRemove],
);
- const handleKeyUp = useCallback(() => {
- onTextFilterUpdate(searchField.current.inputRef.current.value);
- }, [onTextFilterUpdate]);
+ const handleSearchChange = useCallback(
+ (_, { value }) => {
+ onTextFilterUpdate(value);
+ },
+ [onTextFilterUpdate],
+ );
- useEffect(() => {
- searchField.current.inputRef.current.value = filterText;
- }, [filterText]);
+ const handleSearchFocus = useCallback(() => {
+ setIsSearchFocused(true);
+ }, []);
+
+ const handleSearchKeyDown = useCallback(
+ (event) => {
+ if (event.key === 'Escape') {
+ cancelSearch();
+ }
+ },
+ [cancelSearch],
+ );
+
+ const handleSearchBlur = useCallback(() => {
+ setIsSearchFocused(false);
+ }, []);
+
+ const handleCancelSearchClick = useCallback(() => {
+ cancelSearch();
+ }, [cancelSearch]);
const BoardMembershipsPopup = usePopup(BoardMembershipsStep);
const LabelsPopup = usePopup(LabelsStep);
+ const isSearchActive = filterText || isSearchFocused;
+
return (
<>
@@ -114,10 +145,21 @@ const Filters = React.memo(
handleKeyUp()}
+ icon={
+ isSearchActive ? (
+
+ ) : (
+ 'search'
+ )
+ }
+ className={classNames(styles.search, !isSearchActive && styles.searchInactive)}
+ onFocus={handleSearchFocus}
+ onKeyDown={handleSearchKeyDown}
+ onChange={handleSearchChange}
+ onBlur={handleSearchBlur}
/>
>
diff --git a/client/src/components/BoardActions/Filters.module.scss b/client/src/components/BoardActions/Filters.module.scss
index 1af6dd2..12c7fc4 100644
--- a/client/src/components/BoardActions/Filters.module.scss
+++ b/client/src/components/BoardActions/Filters.module.scss
@@ -43,4 +43,32 @@
line-height: 20px;
padding: 2px 12px;
}
+
+ .search {
+ height: 30px;
+ margin: 0 12px;
+ transition: width 0.2s ease;
+ width: 280px;
+
+ input {
+ font-size: 13px;
+ }
+ }
+
+ .searchInactive {
+ color: #fff;
+ height: 24px;
+ width: 220px;
+
+ input {
+ background: rgba(0, 0, 0, 0.24);
+ border: none;
+ color: #fff !important;
+ font-size: 12px;
+
+ &::placeholder {
+ color: #fff;
+ }
+ }
+ }
}
diff --git a/client/src/lib/custom-ui/components/Input/Input.jsx b/client/src/lib/custom-ui/components/Input/Input.jsx
index f9bf001..4e820fb 100755
--- a/client/src/lib/custom-ui/components/Input/Input.jsx
+++ b/client/src/lib/custom-ui/components/Input/Input.jsx
@@ -9,4 +9,6 @@ export default class Input extends SemanticUIInput {
static Mask = InputMask;
focus = (options) => this.inputRef.current.focus(options);
+
+ blur = () => this.inputRef.current.blur();
}