Repository: boarlabsxyz/razom
Pull request #130: Added filtering to the regions list
Author: login: Anton-88
Created: 2025-03-19T08:45:05Z | Merged: 2025-03-31T11:38:52Z

  - Introduced an enhanced region filtering experience with a sticky search input and robust keyboard navigation—including support for Tab and Arrow keys—to quickly locate desired regions.
  - Improved localization with region names now presented in the local language.

- **Style**
  - Refined the visual appearance of interactive elements with updated typography, touch responsiveness, and clear selection indicators for a more intuitive user interface.

- **Documentation**
  - Updated CHANGELOG to include the new keyboard filtering feature and changes to class naming conventions.


Diff:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b64ad36b..3959079d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [1.6.0] - Unreleased
 
+### Added
+
+- possibility to filter regionsList with a keyboard([130](https://github.com/boarlabsxyz/razom/pull/130))
+
+### Changed
+
+- all className attr to cebab case format ([126](https://github.com/boarlabsxyz/razom/pull/126))
+
 ### Fixed
 
 - ability to generate a preview deployment URL for Razom ([136](https://github.com/boarlabsxyz/razom/pull/136))
diff --git a/veterans/components/homePage/mapSection/MapSection.test.tsx b/veterans/components/homePage/mapSection/MapSection.test.tsx
index a2b35e3a..5ad6aedc 100644
--- a/veterans/components/homePage/mapSection/MapSection.test.tsx
+++ b/veterans/components/homePage/mapSection/MapSection.test.tsx
@@ -29,13 +29,15 @@ jest.mock('./map', () => ({
 jest.mock('./regionsFilter', () => ({
   __esModule: true,
   default: ({
+    selectedRegion,
     setSelectedRegion,
   }: {
-    selectedRegion: string | undefined;
+    selectedRegion?: string;
     setSelectedRegion: (region: string) => void;
   }) => (
     <div data-testid="regions-list">
-      <button onClick={() => setSelectedRegion('Kyiv')}>Select Kyiv</button>
+      <button onClick={() => setSelectedRegion('Київ')}>Select Kyiv</button>
+      <span>{selectedRegion}</span>
     </div>
   ),
 }));
@@ -52,7 +54,7 @@ describe('MapSection Component', () => {
     render(<MapSection />);
     const selectRegionButton = screen.getByText('Select Kyiv');
     fireEvent.click(selectRegionButton);
-    expect(screen.getByTestId('ukraine-map')).toHaveTextContent('Kyiv');
+    expect(screen.getByTestId('ukraine-map')).toHaveTextContent('Київ');
   });
 
   it('shows reset button when filters are applied', () => {
diff --git a/veterans/components/homePage/mapSection/regionsFilter/index.ts b/veterans/components/homePage/mapSection/regionsFilter/index.tsx
similarity index 100%
rename from veterans/components/homePage/mapSection/regionsFilter/index.ts
rename to veterans/components/homePage/mapSection/regionsFilter/index.tsx
diff --git a/veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css b/veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
index 6e3f283d..85f4f71d 100644
--- a/veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
+++ b/veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
@@ -1,128 +1,173 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-  font-weight: 400;
-  font-size: 0.875rem;
-  line-height: 1.625rem;
-  color: var(--haiti);
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+/* <<<<<<< HEAD */
+.wrapper {
+  width: 100%;
+  max-width: 240px;
+  padding: 16px;
+}
+
+.regions-wrapper {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  margin-bottom: 12px;
+}
+
+.region-list-title {
+  height: 20px;
+  font-weight: 500;
+  font-size: 16px;
+  line-height: 24px;
+}
+
+.region-selector {
+  position: relative;
+  width: 240px;
+  width: 100%;
+}
+
+.region-selector-btn {
+  position: relative;
+  height: 50px;
+  margin: 12px 0 0 0;
+  padding: 12px;
+  width: 100%;
+  cursor: pointer;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  background-color: var(--white);
+  border: 1px solid var(--pattens-blue);
+  transition: all 0.3s ease-in-out;
+  -webkit-tap-highlight-color: transparent;
+  touch-action: manipulation;
+}
+
+.region-name {
+  flex-grow: 1;
+  text-align: left;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 26px;
+  color: var(--haiti);
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-rendering: optimizeLegibility;
+}
+
+.num-of-initiatives {
+  flex-shrink: 0;
+  text-align: right;
+  padding-right: 10px;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-rendering: optimizeLegibility;
+}
+
+.region-selector-btn:after {
+  content: '';
+  height: 7px;
+  width: 12px;
+  background-image: url('/icons/arrow-down-black.svg');
+  background-size: contain;
+  background-repeat: no-repeat;
+  display: inline-block;
+  transition: transform 0.3s ease-in-out;
+}
+
+.region-selector-btn.open:after {
+  transform: rotate(180deg);
+}
+
+.dropdown-arrow {
+  font-size: 0.8em;
+  color: var(--ebony);
+  margin-left: 5px;
+  transition: transform 0.2s ease-in-out;
+  display: inline-block;
+}
+
+.region-selector-list {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  position: absolute;
+  top: 100%;
+  left: 0;
+  width: 100%;
+  background-color: var(--white);
+  border: 1px solid var(--very-light-grey);
+  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
+  max-height: 300px;
+  overflow-y: auto;
+  z-index: 1;
+  display: none;}
+
+.region-selector-list.show {
+    display: block;
+  }
+
+.region-search-input {
+  position: sticky;
+  top: 0;
+  height: 28px;
+  width: calc(100% - 24px);
+  padding: 12px;
+  border: none;
+  font-size: 14px;
+  outline: none;
+  z-index: 1;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-rendering: optimizeLegibility;
+}
+
+.region-search-input::placeholder {
+  color: var(--forest-jade);
+  opacity: 0.7;
+}
+
+.region-search-input:focus {
+  border-bottom-color: var(--primary-color);
+}
+
+.region-selector-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  cursor: pointer;
+  padding: 12px;
+  max-height: 50px;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 26px;
+  border: 1px solid var(--pattens-blue);
+  transition: background-color 0.2s ease-in-out;
+  background-color: var(--white);
+  -webkit-tap-highlight-color: transparent;
+  touch-action: manipulation;
+}
+
+.region-selector-item:hover,
+.region-selector-item:focus {
+  background-color: var(--gum-leaf);
+}
+
+.region-selector-item.selected {
+  background-color: var(--gum-leaf);
+  font-weight: 500;
+}
+
+.region-selector-btn.open {
+  border-radius: 4px 4px 0 0;
+}
+
+@media (max-width: 480px) {
+  .wrapper {
+    width: calc(100% - 32px);
+    max-width: 100%;
+  }
+
+  .region-selector {
+    width: 100%;
+  }
+}
diff --git a/veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx b/veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
index f1d5f773..a7679f58 100644
--- a/veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
+++ b/veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
@@ -216,4 +216,19 @@ describe('RegionsList Component', () => {
     );
     expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
   });
+
+  test('search input updates inputValue and resets focusedIndex', async () => {
+    renderWithApollo(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
+    await waitForDataLoad();
+
+    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    const searchInput = screen.getByTestId('region-search-input');
+
+    fireEvent.change(searchInput, { target: { value: 'Region 1' } });
+
+    expect(searchInput).toHaveValue('Region 1');
+    expect(
+      screen.getByRole('menuitemradio', { name: 'Select Region 1' }),
+    ).toBeInTheDocument();
+  });
 });
diff --git a/veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx b/veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
index 7678b12e..9a41b7a4 100644
--- a/veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
+++ b/veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
@@ -3,27 +3,50 @@
 import React, { useState, useEffect, useRef, useCallback } from 'react';
 import { useQuery } from '@apollo/client';
 import { GET_REGIONS, type Region } from '@helpers/queries';
-
+import { RegionsListProps } from './types';
 import Spinner from '@comComps/spinner';
 
 import st from './regionsList.module.css';
 
-interface RegionsListProps {
-  readonly selectedRegion?: string;
-  readonly setSelectedRegion: (region: string) => void;
-}
-
-function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
-  const [isOpen, setIsOpen] = useState(false);
-  const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
-  const { data, loading, error } = useQuery(GET_REGIONS);
+const DEFAULT_REGION_NAME = 'Всі';
+const SEARCH_PLACEHOLDER = 'Укажіть область...';
+const UKRAINIAN_TEXT_REGEX = /^[а-яґєіїё]+$/iu;
 
+function RegionsList({
+  selectedRegion,
+  setSelectedRegion,
+}: Readonly<RegionsListProps>) {
   const dropdownRef = useRef<HTMLDivElement>(null);
   const buttonRef = useRef<HTMLButtonElement>(null);
   const listRef = useRef<HTMLDivElement>(null);
   const itemsRef = useRef<(HTMLDivElement | null)[]>([]);
+  const inputRef = useRef<HTMLInputElement>(null);
+
+  const [isOpen, setIsOpen] = useState(false);
+  const { data, loading, error } = useQuery(GET_REGIONS);
+  const [inputValue, setInputValue] = useState('');
+
+  const isUkrainianText = useCallback(
+    (text: string) => UKRAINIAN_TEXT_REGEX.test(text),
+    [],
+  );
 
   const regions = data?.regions || [];
+  const filteredRegions = regions.filter((region: Region) =>
+    isUkrainianText(inputValue)
+      ? region.name.toLowerCase().includes(inputValue.toLowerCase())
+      : true,
+  );
+
+  const defaultRegion = regions.find(
+    (region: Region) => region.name === DEFAULT_REGION_NAME,
+  ) || {
+    name: '',
+    numOfInitiatives: 0,
+  };
+  const [focusedIndex, setFocusedIndex] = useState<number | null>(
+    regions.findIndex((region: Region) => region.name === defaultRegion.name),
+  );
 
   const toggleDropdown = () => {
     setIsOpen((prev) => {
@@ -58,59 +81,111 @@ function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
     [setSelectedRegion, setIsOpen, setFocusedIndex, regions, buttonRef],
   );
 
-  const handleClickOutside = (event: MouseEvent) => {
+  const handleClickOutside = useCallback((e: MouseEvent) => {
     if (
       dropdownRef.current &&
-      !dropdownRef.current.contains(event.target as Node)
+      !dropdownRef.current.contains(e.target as Node)
     ) {
       setIsOpen(false);
+      setInputValue('');
       setFocusedIndex(null);
     }
+  }, []);
+
+  const calculatePreviousTabOrArrowUpIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex <= 0
+      ? length - 1
+      : focusedIndex - 1;
   };
 
-  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
-    if (event.key === 'Escape') {
-      setIsOpen(false);
+  const calculateNextTabOrArrowDownIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex >= length - 1
+      ? 0
+      : focusedIndex + 1;
+  };
+
+  const handleInputChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      setInputValue(e.target.value);
       setFocusedIndex(null);
-      buttonRef.current?.focus();
-    } else if (isOpen) {
-      if (event.key === 'ArrowDown' || event.key === 'Tab') {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === regions.length - 1 ? 0 : prev + 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (
-        event.key === 'ArrowUp' ||
-        (event.shiftKey && event.key === 'Tab')
-      ) {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === 0 ? regions.length - 1 : prev - 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (event.key === 'Enter' || event.key === ' ') {
-        event.preventDefault();
-        if (focusedIndex !== null) {
-          handleRegionSelect(regions[focusedIndex]);
-        }
+    },
+    [],
+  );
+
+  const handleKeyDown = useCallback(
+    (e: React.KeyboardEvent<HTMLDivElement>) => {
+      if (!isOpen) {
+        return;
       }
-    }
-  };
+
+      let newIndex: number;
+
+      switch (e.key) {
+        case 'Tab':
+          e.preventDefault();
+          newIndex = e.shiftKey
+            ? calculatePreviousTabOrArrowUpIndex(
+                focusedIndex,
+                filteredRegions.length,
+              )
+            : calculateNextTabOrArrowDownIndex(
+                focusedIndex,
+                filteredRegions.length,
+              );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowDown':
+          e.preventDefault();
+          newIndex = calculateNextTabOrArrowDownIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowUp':
+          e.preventDefault();
+          newIndex = calculatePreviousTabOrArrowUpIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'Enter':
+        case ' ':
+          e.preventDefault();
+          if (focusedIndex !== null) {
+            handleRegionSelect(filteredRegions[focusedIndex]);
+          }
+          break;
+        case 'Escape':
+          e.preventDefault();
+          setIsOpen(false);
+          setInputValue('');
+          setFocusedIndex(null);
+          break;
+      }
+    },
+    [isOpen, focusedIndex, filteredRegions, handleRegionSelect],
+  );
 
   useEffect(() => {
     if (isOpen) {
       document.addEventListener('mousedown', handleClickOutside);
-      listRef.current?.focus();
+      inputRef.current?.focus();
     }
     return () => {
       document.removeEventListener('mousedown', handleClickOutside);
     };
-  }, [isOpen]);
+  }, [isOpen, handleClickOutside]);
 
   if (loading) {
     return <Spinner />;
@@ -149,7 +224,26 @@ function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
             }
             onKeyDown={handleKeyDown}
           >
-            {regions.map((region: Region, index: number) => (
+            <input
+              ref={inputRef}
+              type="text"
+              value={inputValue}
+              onChange={handleInputChange}
+              placeholder={SEARCH_PLACEHOLDER}
+              className={st['region-search-input']}
+              data-testid="region-search-input"
+              aria-label="Пошук регіону"
+              aria-controls="region-list"
+              aria-expanded={isOpen}
+              aria-haspopup="listbox"
+              aria-autocomplete="list"
+              role="combobox"
+              aria-owns="region-list"
+              aria-activedescendant={
+                focusedIndex !== null ? `region-${focusedIndex}` : undefined
+              }
+            />
+            {filteredRegions.map((region: Region, index: number) => (
               <div
                 key={region.id}
                 id={`region-${index}`}
@@ -158,15 +252,15 @@ function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
                   itemsRef.current[index] = el;
                 }}
                 onClick={() => handleRegionSelect(region)}
-                onKeyDown={(event) => {
-                  if (event.key === 'Enter' || event.key === ' ') {
+                onKeyDown={(e) => {
+                  if (e.key === 'Enter' || e.key === ' ') {
                     handleRegionSelect(region);
                   }
                 }}
-                tabIndex={-1}
+                tabIndex={focusedIndex === index ? 0 : -1}
                 className={`${st['region-selector-item']} ${
                   focusedIndex === index ? st.focused : ''
-                }`}
+                } ${selectedRegion === region.name ? st.selected : ''}`}
                 aria-checked={selectedRegion === region.name}
                 aria-label={`Select ${region.name}`}
               >
diff --git a/veterans/components/homePage/mapSection/regionsFilter/types.ts b/veterans/components/homePage/mapSection/regionsFilter/types.ts
new file mode 100644
index 00000000..42cfca8b
--- /dev/null
+++ b/veterans/components/homePage/mapSection/regionsFilter/types.ts
@@ -0,0 +1,4 @@
+export interface RegionsListProps {
+  readonly selectedRegion?: string;
+  readonly setSelectedRegion: (region: string) => void;
+}


Reviews:
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-19T08:47:53Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (3)</summary><blockquote>

`87-87`: **Remove commented code**

This commented line should be removed as it's been replaced by the `selectRegion` helper function call below.


```diff
-    // fireEvent.click(getAllRegions()[1]);
```

---

`106-107`: **Remove commented code for cleaner tests**

Several instances of commented-out fireEvent calls should be removed as they've been replaced with the pressKey helper function.


```diff
-    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
     pressKey(regions[0], 'ArrowDown');

-    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
     pressKey(regions[0], 'ArrowDown');

-    // fireEvent.keyDown(regions[1], { key: 'ArrowUp' });
     pressKey(regions[0], 'ArrowUp');

-    // fireEvent.keyDown(regions[0], { key: 'Enter' });
     pressKey(regions[0], 'Enter');

-      // fireEvent.keyDown(list, { key: 'Escape' });
       pressKey(list, 'Escape');
```


Also applies to: 110-111, 114-115, 118-119, 156-157

---

`129-132`: **Simplify key press handling**

There's duplicate code with both `fireEvent.keyDown` and `pressKey` being called with the same parameters. Since you've created the `pressKey` helper, you should use only that function.


```diff
    if (list) {
-      fireEvent.keyDown(list, { key: 'в' });
      pressKey(list, 'в');
    }

    if (list) {
-      fireEvent.keyDown(list, { key: 'Backspace' });
      pressKey(list, 'Backspace');
    }
```


Also applies to: 139-142

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between a8e0de0ff414002496369912b0605ee774d48cf9 and 8bc9e1266ce6f8de10fde02e1210964b77c75252.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (7 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: unit-tests
* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (5)</summary>

`6-35`: **Good job defining explicit test data!**

Using a static array with meaningful Ukrainian region names and specific initiative counts makes the tests more deterministic and easier to understand. This change aligns well with the filtering functionality being added.

---

`37-54`: **Great refactoring of test helpers!**

Extracting these helper functions improves test readability and maintainability. The `pressKey` and `selectRegion` utilities in particular will make the tests more concise.

---

`83-98`: **Well implemented focus handling test**

The new test for checking focus behavior when reopening the dropdown is a great addition. It ensures that the component properly remembers the previously selected item, which improves usability.

---

`124-148`: **Excellent test for search term clearing**

This new test verifies the search filtering functionality, which is a core feature in this PR. It correctly tests both filtering (by typing "в") and clearing the filter (with Backspace). The waitFor handlers properly account for the asynchronous nature of these interactions.

---

`1-171`: **Overall test implementation looks solid**

The test suite comprehensively covers the component's functionality, including rendering, interactions, keyboard navigation, and the new filtering capability. The refactored helper functions and explicit test data make the tests more readable and maintainable.

A few minor cleanup items (commented code and duplicate calls) would make the code even cleaner, but the functionality testing appears thorough and well-implemented.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-19T10:30:37Z
user: login: Anton-88
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T10:34:58Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T10:35:21Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (1)</summary><blockquote>

`105-106`: _⚠️ Potential issue_

**Fix ArrowDown test logic.**

There appears to be an issue with the ArrowDown test. When pressing ArrowDown on regions[0], the focus should move to the next item (regions[1]), not remain on regions[0].

```diff
-    pressKey(regions[0], 'ArrowDown');
-    expect(regions[0]).toHaveFocus();
+    // First press should initialize focus on regions[0]
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
+    
+    // Second press should move focus to regions[1]
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[1]).toHaveFocus();
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (1)</summary><blockquote>

`119-143`: **Good addition of search term testing.**

This test effectively validates the keyboard filtering functionality which is the main objective of the PR. It correctly tests that:
1. Typing 'в' filters the list to fewer items
2. Pressing Backspace clears the filter and restores all items

However, there's an inconsistency in how keyboard events are simulated.


```diff
-      fireEvent.keyDown(list, { key: 'в' });
-      pressKey(list, 'в');
+      // Use only one method to simulate key presses consistently
+      pressKey(list, 'в');

// And similarly for Backspace:
-      fireEvent.keyDown(list, { key: 'Backspace' });
-      pressKey(list, 'Backspace');
+      pressKey(list, 'Backspace');
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8bc9e1266ce6f8de10fde02e1210964b77c75252 and 27270f796401abdbad8f7c3de3b8a3e63cf682c9.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: sonarqube
* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (6)</summary>

`2-2`: **Good addition of waitFor import.**

Adding `waitFor` to the imports is appropriate for the new async tests that verify focus behavior and filtering functionality.

---

`6-35`: **Improved mock data with realistic Ukrainian region names.**

The static region data with actual Ukrainian names and initiative counts provides a more realistic test environment and better supports testing the filtering functionality. This change aligns well with the PR's objective of adding keyboard filtering to the regions list.

---

`37-54`: **Well-structured test utility functions.**

These helper functions improve test readability and maintainability by abstracting common operations. The separation of concerns between setup, querying, and interaction functions follows testing best practices.

---

`76-81`: **Simplified regions count test.**

The test now uses the helper functions and correctly validates that the dropdown shows all 26 regions, which matches the static mock data you've defined.

---

`83-97`: **Good addition of focus retention test.**

This new test appropriately verifies that the component maintains focus on the selected region when reopening the dropdown, which is an important accessibility feature. Using `waitFor` correctly handles the asynchronous behavior.

---

`114-116`: **Correct verification of selected region text.**

The test now correctly verifies that the button shows "Вінницька" after selection, which corresponds to the first region in your mock data. This is a good improvement from the previous test.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T10:36:04Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-19T10:36:07Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-19T11:40:26Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (3)</summary><blockquote>

`90-95`: **Consider enhancing focus test with more specific assertions.**

While the focus test works correctly, you could enhance it by verifying that the selected region's text matches what you expect. Additionally, the 1000ms timeout might be longer than necessary for most test environments.

```diff
test('sets correct focus when reopening dropdown with selected region', async () => {
  setupDropdownWithSelection(1);
  await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
-    timeout: 1000,
+    timeout: 500,
  });
+  expect(getAllRegions()[1]).toHaveTextContent('Волинська');
});
```

---

`111-114`: **Consider expanding search term filtering tests.**

The current test verifies count changes when filtering, but it could be enhanced to verify specific filtered results and test more complex Ukrainian character input patterns.

```diff
test('clears search term with backspace', async () => {
  setupDropdown();
  await typeAndClearSearchTerm('в');
+  
+  // Test specific filtering results
+  setupDropdown();
+  const list = getRegionsList();
+  pressKey(list!, 'В');
+  
+  await waitFor(() => {
+    const filteredRegions = getAllRegions();
+    expect(filteredRegions.length).toBe(4); // Вінницька, Волинська, Івано-Франківська, Львівська
+    expect(filteredRegions[0]).toHaveTextContent('Вінницька');
+    expect(filteredRegions[1]).toHaveTextContent('Волинська');
+  });
});
```

---

`97-109`: **Consider testing edge cases for keyboard navigation.**

While the keyboard navigation tests cover basic functionality, they could be expanded to test wrapping behavior (pressing Up on the first item or Down on the last item).

```diff
test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
  setupDropdown();
  const regions = getAllRegions();
  pressKey(regions[0], 'ArrowDown');
  expect(regions[0]).toHaveFocus();
  pressKey(regions[0], 'ArrowDown');
  expect(regions[1]).toHaveFocus();
  pressKey(regions[1], 'ArrowUp');
  expect(regions[0]).toHaveFocus();
+  
+  // Test wrapping behavior
+  const lastIndex = regions.length - 1;
+  // Focus last item
+  regions[lastIndex].focus();
+  expect(regions[lastIndex]).toHaveFocus();
+  // Test wrapping from bottom to top
+  pressKey(regions[lastIndex], 'ArrowDown');
+  expect(regions[0]).toHaveFocus();
+  // Test wrapping from top to bottom
+  pressKey(regions[0], 'ArrowUp');
+  expect(regions[lastIndex]).toHaveFocus();
  
  pressKey(regions[0], 'Enter');
  expect(getDropdownButton()).toHaveTextContent(/Вінницька/i);
  expect(getRegionsList()).not.toBeInTheDocument();
});
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7960f4bb0f1f1d33d62e9145c2fefed32898e865 and 2218ddb118b0b2d42ff9c06e4b9f83dc2a8b5eb0.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: unit-tests
* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (3)</summary>

`6-35`: **Good replacement of dynamic mock with realistic Ukrainian region data.**

Using static region data with actual Ukrainian names and initiative counts makes the tests more specific and maintainable. This change aligns well with the PR objective to support Ukrainian input in region filtering.

---

`37-58`: **Well-structured test utilities for better readability.**

The addition of utility functions improves test readability and maintainability. The `typeAndClearSearchTerm` function effectively tests the new filtering capability.

---

`60-69`: **Well-organized setup helper functions.**

These setup functions help reduce code duplication and make tests more maintainable. They provide a clean way to prepare test scenarios for different use cases.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T13:15:44Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-19T13:15:47Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (2)</summary><blockquote>

`76-81`: **Good focus management test with room for optimization**

The test for focus management when reopening the dropdown is important for accessibility. However, the 1000ms timeout might be unnecessarily long for most test environments.


```diff
- await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
-   timeout: 1000,
- });
+ await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
+   timeout: 500,
+ });
```

---

`97-111`: **Good test for the new search term clearing feature**

This test effectively validates the Ukrainian text filtering functionality and backspace key behavior, which were key objectives of this PR. It confirms both the filtering and clearing work as expected.


Consider adding comments explaining that 'в' is a Ukrainian character being used to test the filtering functionality.

```diff
    setupDropdown();
    const list = getRegionsList();
+   // Test filtering with Ukrainian character 'в'
    pressKey(list!, 'в');
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2218ddb118b0b2d42ff9c06e4b9f83dc2a8b5eb0 and aa4d6fcdc5acebaa14a85d632a95680770102a39.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (3)</summary>

`6-35`: **Strong improvement with realistic Ukrainian region data**

Replacing arbitrary test data with real Ukrainian region names is a great enhancement. It makes the tests more realistic and provides proper coverage for Ukrainian text filtering functionality.

---

`37-55`: **Well-structured test utility functions**

These utility functions significantly improve code organization and readability. Abstracting common test operations reduces duplication and makes the test cases much more maintainable.

---

`90-91`: **Correctly addressed ArrowUp navigation**

The ArrowUp test now properly checks navigation from one item to the previous item, fixing the issue mentioned in the previous review.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-19T16:31:52Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-19T17:06:48Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (3)</summary><blockquote>

`48-59`: **Consider simplifying the scrollToElement function**

The try-catch block might be unnecessary here since the fallback is to call `element.focus()`. If `scrollIntoView` fails, `focus()` might also fail for the same reason.

```diff
const scrollToElement = useCallback((element: HTMLElement) => {
-  try {
-    if (typeof element.scrollIntoView === 'function') {
-      element.scrollIntoView({
-        block: 'center',
-        behavior: 'smooth',
-      });
-    }
-  } catch {
-    element.focus();
-  }
+  if (typeof element.scrollIntoView === 'function') {
+    element.scrollIntoView({
+      block: 'center',
+      behavior: 'smooth',
+    });
+  } else {
+    element.focus();
+  }
}, []);
```

---

`88-144`: **Consider breaking down the handleKeyDown function**

This function is quite large and handles multiple keyboard interactions. For better maintainability, consider extracting the logic for each key into separate functions.


You could refactor it like this:

```typescript
const handleArrowDown = useCallback((e: React.KeyboardEvent) => {
  e.preventDefault();
  const newIndex = focusedIndex === null || focusedIndex >= filteredRegions.length - 1
    ? 0
    : focusedIndex + 1;
  setFocusedIndex(newIndex);
  itemsRef.current[newIndex]?.focus();
}, [focusedIndex, filteredRegions]);

const handleArrowUp = useCallback((e: React.KeyboardEvent) => {
  e.preventDefault();
  const newIndex = focusedIndex === null || focusedIndex <= 0
    ? filteredRegions.length - 1
    : focusedIndex - 1;
  setFocusedIndex(newIndex);
  itemsRef.current[newIndex]?.focus();
}, [focusedIndex, filteredRegions]);

// ...similar functions for Tab, Enter/Space, Escape...

const handleKeyDown = useCallback(
  (e: React.KeyboardEvent<HTMLDivElement>) => {
    if (!isOpen) {
      return;
    }

    switch (e.key) {
      case 'Tab':
        handleTab(e);
        break;
      case 'ArrowDown':
        handleArrowDown(e);
        break;
      case 'ArrowUp':
        handleArrowUp(e);
        break;
      // ...other cases
    }
  },
  [isOpen, handleTab, handleArrowDown, handleArrowUp, /* other handlers */]
);
```

---

`154-172`: **Consider adding a comment about the setTimeout usage**

The `setTimeout` with 0ms delay is used to defer focus until after the component renders, but this pattern might be confusing to other developers. Consider adding a comment explaining this approach.

```diff
const toggleDropdown = useCallback(() => {
  setIsOpen((prev) => {
    if (!prev) {
      setInputValue('');
+      // Defer focus until after render to ensure elements are available
      setTimeout(() => {
        if (selectedRegion !== DEFAULT_REGION_NAME) {
          const selectedElement = itemsRef.current[focusedIndex || 0];
          if (selectedElement) {
            selectedElement.focus();
            scrollToElement(selectedElement);
          }
        } else {
          inputRef.current?.focus();
        }
      }, 0);
    }
    return !prev;
  });
}, [selectedRegion, focusedIndex, scrollToElement]);
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 562c507539a97098e26d6d0325662eecd937a8fc and 3ea754875726d9a8f99e47b32c8373df8fa5aed5.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (3 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/types.ts` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/types.ts (2) (2)</summary>

* `RegionsListProps` (6-8)
* `Region` (1-4)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css</summary>

[error] 40-40: Unexpected shorthand property margin after margin-top



(lint/suspicious/noShorthandPropertyOverrides)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Analyze (javascript-typescript)

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/types.ts (1)</summary>

`1-8`: **Clean and well-structured type definitions**

The interfaces are properly defined with clear property types. Making `setCurrentRegion` optional in `RegionsListProps` is a good design decision as it allows the component to be used in different contexts.

</details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (3)</summary>

`10-12`: **Well-defined constants**

Good practice to extract these values as constants at the top of the file. The Ukrainian text regex will be useful for filtering.

---

`42-46`: **Filter implementation looks good**

The filtering logic correctly uses the Ukrainian text regex to determine if filtering should be applied, and performs case-insensitive matching.

---

`214-222`: **Good implementation of search input with accessibility attributes**

The search input is well-implemented with proper refs, event handlers, and test IDs. The placeholder text provides clear guidance to users.

</details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (4)</summary>

`6-35`: **Good use of static test data**

Using fixed region names for tests makes the tests more predictable and easier to maintain than dynamically generating test data.

---

`37-63`: **Well-structured test utility functions**

These helper functions improve test readability and reduce duplication. They also make the tests more maintainable by centralizing common testing patterns.

---

`122-129`: **Comprehensive edge case testing**

Good job adding tests for edge cases such as non-matching input and non-Ukrainian text. These tests ensure the component behaves correctly under various conditions.



Also applies to: 167-175

---

`197-217`: **Thorough keyboard navigation testing**

The tests for Tab and Shift+Tab navigation are well-implemented and verify that focus moves correctly through the list items.

</details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css (2)</summary>

`104-120`: **Well-implemented search input styles**

The `.region-search-input` class is well-designed with appropriate positioning, sizing, and focus states. The sticky positioning ensures the search input remains visible while scrolling through a long list.

---

`140-143`: **Good visual feedback for selected item**

The `.selected` class provides clear visual differentiation for the selected item. The background color and font weight changes make the selection obvious to users.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-20T21:35:34Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (1)</summary><blockquote>

`230-285`: _⚠️ Potential issue_

**Legacy tests use different props than new tests**

These unchanged tests use `selectedRegion` and `setSelectedRegion` props, while new tests like line 187-195 use `setCurrentRegion`. This suggests an API change, but both sets of tests are present, which could lead to confusion.

If the component API has changed, update or remove these legacy tests to match the current component implementation. Otherwise, document why both prop patterns are supported.

```diff
- <RegionsList
-   selectedRegion="Region 5"
-   setSelectedRegion={mockSetSelectedRegion}
- />
+ <RegionsList setCurrentRegion={mockSetCurrentRegion} />
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (1)</summary><blockquote>

`105-120`: **Test name doesn't match implementation**

The test name suggests it's testing backspace functionality, but the implementation is using `typeText('')` which sets an empty value rather than simulating backspace key presses.

Either rename the test to "clears search term when input is emptied" or modify the implementation to actually test backspace key:

```diff
- typeText('');
+ const input = screen.getByTestId('region-search-input');
+ pressKey(input, 'Backspace');
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3ea754875726d9a8f99e47b32c8373df8fa5aed5 and 8497405f9be1e5adea6b47938cb0a9100df26c77.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `CHANGELOG.md` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* CHANGELOG.md

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (7)</summary>

`6-35`: **Well-structured mock data for realistic testing!**

Using real Ukrainian region names instead of generic "Region X" names makes the tests more realistic and allows proper testing of filtering functionality with actual Ukrainian characters.

---

`37-63`: **Great utility functions for test readability!**

These helper functions improve test readability and maintainability by encapsulating common test operations. This is an excellent practice that reduces code duplication across tests.

---

`208-217`: **Shift+Tab behavior test may not reflect standard keyboard navigation**

Similar to the Tab test, the Shift+Tab behavior being tested (jumping from first item to last item) doesn't match standard web navigation patterns. This could confuse users who expect standard keyboard navigation.

Please verify that this custom Shift+Tab behavior is documented for users and matches accessibility best practices.

---

`84-89`: **Good use of waitFor for asynchronous UI behavior**

Using `waitFor` with a reasonable timeout for focus checks is a good practice for testing asynchronous UI behaviors. This makes the test more reliable.

---

`131-152`: **Excellent coverage of filtering edge cases**

The tests for case-insensitive filtering and multiple character filtering ensure the feature works correctly with various inputs. These edge cases are critical for a good user experience.

---

`167-175`: **Good test for non-Ukrainian text input**

Testing how the component handles input that doesn't match any Ukrainian characters is important for internationalization and user error handling.

---

`197-206`: <details>
<summary>✅ Verification successful</summary>

**Tab behavior test may not reflect standard keyboard navigation**

Tab key typically moves focus to the next focusable element in the DOM, not sequentially through all items in a list. The current test simulates pressing Tab on the list itself, not on an individual region.

Please verify that this custom Tab behavior is intentional and matches the component's actual keyboard navigation implementation.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check how Tab navigation is implemented in the component
rg -A 5 "Tab|onKeyDown" ./veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
```

Length of output: 729

---



</details>

**Custom Tab Key Navigation Confirmed**

After reviewing the implementation in `regionsList.tsx`, it’s clear that the component intentionally intercepts the native Tab behavior using a custom onKeyDown handler. The Tab case explicitly prevents default behavior and recalculates focus using a custom index. This confirms that the test—which simulates pressing Tab on the list—is intentionally verifying the component’s custom keyboard navigation behavior.

- The component’s onKeyDown logic for `'Tab'` uses `e.preventDefault()` and computes a new focus index (with proper handling of Shift+Tab).
- Each region is assigned a `tabIndex` based on the custom focus logic, ensuring that focus is manually managed.

No changes are required to the test; however, it might be helpful to add an inline comment in the test or component code to clarify that this custom behavior is by design.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-20T21:40:54Z
user: login: Anton-88
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T21:40:54Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-20T21:41:45Z
user: login: Anton-88
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T22:06:38Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-20T22:07:01Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (1)</summary><blockquote>

`84-89`: **Consider reducing the timeout value.**

The 1000ms timeout for the focus check seems excessive for a UI component test. In most cases, focus should be applied immediately or within a few milliseconds after the component renders.


```diff
  await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
-   timeout: 1000,
+   timeout: 200,
  });
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 08b62b8b835ffb5c0d1787e685c5f395a614aa1b and 39e02a32a22bfac0765fda222595b140680b46af.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (12)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx (12)</summary>

`6-35`: **Well-structured mock data with comprehensive Ukrainian region coverage.**

The use of a static array of specific Ukrainian region names provides realistic test data and makes the tests more deterministic. This is a good approach that aligns with the feature's purpose of filtering Ukrainian region names.

---

`37-63`: **Excellent test utility functions implementation.**

The utility functions significantly improve the test code's readability and maintainability by abstracting common operations. Functions like `setupRegionsList`, `openDropdown`, and `typeText` eliminate code duplication and make test intentions clearer.

---

`91-103`: **Good keyboard navigation test coverage.**

The implementation properly tests ArrowDown, ArrowUp, and Enter key interactions, ensuring focus moves correctly between options and selection works as expected.

---

`105-120`: **Good test for search term clearing functionality.**

This test properly verifies that backspace/clearing a search input resets the filtering and shows all regions again.

---

`122-129`: **Inconsistency between test name and expectations**

The test name suggests regions should be hidden when no matches are found, but the test expects all 26 regions to still be displayed.

Either:
1. Rename the test to reflect that all regions remain visible when no match is found, or
2. Update the expectation if regions should actually be hidden:

```diff
- test('hides all options when no region matches input', async () => {
+ test('shows all regions even when no region matches input', async () => {
```

---

`131-140`: **Comprehensive filtering test coverage.**

The tests thoroughly cover various filtering scenarios:
- Case-insensitive filtering
- Multi-character filtering
- Non-Ukrainian text handling
- Empty input handling

This comprehensive coverage ensures the filtering functionality is robust across different input scenarios.



Also applies to: 142-152, 167-175, 177-184

---

`154-165`: **Good test coverage for dropdown closing behavior.**

The tests properly verify that the dropdown closes on Escape key press and when clicking outside the component, which are important UX considerations.

---

`187-195`: **Good callback testing approach.**

The test correctly verifies that the `setCurrentRegion` callback is called with the expected region name when a selection is made, ensuring proper communication with parent components.

---

`197-217`: **Thorough keyboard navigation testing with Tab and Shift+Tab.**

The tests properly verify that Tab and Shift+Tab navigation works correctly, which is crucial for accessibility. Testing both forward and backward navigation ensures users can efficiently navigate the component using the keyboard.

---

`219-228`: **Good Space key selection test.**

The test verifies that pressing the Space key on a focused region correctly selects it and closes the dropdown, ensuring multiple selection methods work as expected.

---

`230-239`: **Important focus management test for usability.**

The test ensures focus moves to the search input when the dropdown opens, which is an important UX consideration that facilitates immediate filtering by users.

---

`241-267`: **Comprehensive tests for region selection workflows.**

These tests verify both mouse click and keyboard selection workflows, ensuring users can select regions through multiple interaction methods.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-20T22:08:50Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-20T22:08:53Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-20T22:16:51Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css (1)</summary><blockquote>

`103-115`: **New Search Input Styling Enhances Filtering**  
The new `.region-search-input` class uses `position: sticky` to keep the search field visible during scrolling. The calculated width (`calc(100% - 24px)`) and padding provide a balanced look.  
  
*Suggestion:* Consider adding `box-sizing: border-box;` to ensure that padding is included in the element’s total width, which can help maintain consistent dimensions across browsers.  
  
```diff
 .region-search-input {
+  box-sizing: border-box;
   position: sticky;
   top: 0;
   width: calc(100% - 24px);
   padding: 12px;
```

</blockquote></details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (4)</summary><blockquote>

`42-46`: **Consider revising the filtering logic.**

The current implementation only filters when the input contains Ukrainian text. If the input doesn't match the Ukrainian regex, it returns all regions. This might be confusing for users who type non-Ukrainian characters expecting the list to filter.

```diff
const filteredRegions = regionsArray.filter((region) =>
-  isUkrainianText(inputValue)
-    ? region.name.toLowerCase().includes(inputValue.toLowerCase())
-    : true,
+  inputValue === '' || region.name.toLowerCase().includes(inputValue.toLowerCase()),
);
```

---

`143-175`: **Reduce code duplication in keyboard navigation helpers.**

The `calculateTabIndex` function duplicates logic from `calculateArrowDownIndex` and `calculateArrowUpIndex`. Consider refactoring to reuse these functions.

```diff
const calculateTabIndex = (
  shiftKey: boolean,
  focusedIndex: number | null,
  length: number,
): number => {
-  if (shiftKey) {
-    return focusedIndex === null || focusedIndex <= 0
-      ? length - 1
-      : focusedIndex - 1;
-  } else {
-    return focusedIndex === null || focusedIndex >= length - 1
-      ? 0
-      : focusedIndex + 1;
-  }
+  return shiftKey 
+    ? calculateArrowUpIndex(focusedIndex, length)
+    : calculateArrowDownIndex(focusedIndex, length);
};
```

---

`88-141`: **Repetitive focus logic in keyboard handler.**

The keyboard handler has repetitive code for setting focus. Consider extracting this pattern into a helper function.

```diff
+ const setFocusToIndex = useCallback((newIndex: number) => {
+   setFocusedIndex(newIndex);
+   itemsRef.current[newIndex]?.focus();
+ }, []);

const handleKeyDown = useCallback(
  (e: React.KeyboardEvent<HTMLDivElement>) => {
    if (!isOpen) {
      return;
    }

    let newIndex: number;

    switch (e.key) {
      case 'Tab':
        e.preventDefault();
        newIndex = calculateTabIndex(
          e.shiftKey,
          focusedIndex,
          filteredRegions.length,
        );
-       setFocusedIndex(newIndex);
-       itemsRef.current[newIndex]?.focus();
+       setFocusToIndex(newIndex);
        break;
      case 'ArrowDown':
        e.preventDefault();
        newIndex = calculateArrowDownIndex(
          focusedIndex,
          filteredRegions.length,
        );
-       setFocusedIndex(newIndex);
-       itemsRef.current[newIndex]?.focus();
+       setFocusToIndex(newIndex);
        break;
      // Similar changes for ArrowUp
```

---

`61-75`: **Missing dependency in useCallback.**

The `handleRegionSelect` callback uses `DEFAULT_REGION_NAME` but doesn't include it in the dependencies array. While constants don't typically change, it's still a best practice to include all values from outside the function scope.

```diff
  },
- [setCurrentRegion],
+ [setCurrentRegion, DEFAULT_REGION_NAME],
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 960cfdfaf847c8e178bd176ed137f1df94173c25 and 3277160842b499da217b44406e067d1f5ee71cf8.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/types.ts (2)</summary>

* `RegionsListProps` (6-8)
* `Region` (1-4)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: e2e-tests
* GitHub Check: unit-tests
* GitHub Check: Analyze (javascript-typescript)

</details>

<details>
<summary>🔇 Additional comments (23)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css (18)</summary>

`1-5`: **Wrapper Container Setup is Clear**  
The `.wrapper` class is well defined with a fixed max-width and padding, helping constrain the content nicely in its container.

---

`7-11`: **Effective Use of Flex Gap for Spacing**  
The `.regions-wrapper` now uses `gap: 8px` to manage spacing between child elements. This modern approach improves readability and maintainability.

---

`13-18`: **Refined Title Styling**  
The `.region-list-title` class now explicitly sets the font size, weight, color (`var(--text-color)`), and resets the margin. These changes yield a cleaner, more consistent appearance for the title.

---

`20-23`: **Solid Container for Selector**  
The `.region-selector` class remains concise, setting a relative positioning and full width, which is appropriate for a dropdown container.

---

`25-40`: **Improved Interactive Button Styling**  
The `.region-selector-btn` class now establishes a clear interactive style with:  
- Defined height and padding for a consistent touch target.  
- A corrected margin (`12px 0 0 0`), which resolves previous conflicts.  
- Touch-friendly properties like `-webkit-tap-highlight-color` and `touch-action`.  
The transition set on the entire element ensures smooth visual feedback.

---

`42-52`: **Consistent Text Styling for Region Names**  
The `.region-name` class sets appropriate font-weight, size, and line-height while incorporating font smoothing. This ensures text clarity and consistency.

---

`54-61`: **Clean Presentation for Initiative Numbers**  
The `.num-of-initiatives` class properly aligns and applies font smoothing to numerical data, ensuring its legibility and visual balance within the UI.

---

`63-72`: **Well-Implemented Pseudo-element for Arrow Icon**  
The pseudo-element in `.region-selector-btn:after` effectively uses an SVG background image with a smooth transition. This approach cleanly separates visual elements from content.

---

`74-76`: **Clear Visual Cue for Open State**  
The rotation applied in `.region-selector-btn.open:after` correctly signals the open state of the selector. This enhances UX by providing an intuitive visual cue.

---

`78-84`: **Concise Dropdown Arrow Styling**  
The `.dropdown-arrow` class provides subtle styling for any supplementary icon, using a slight margin and transition that fits well alongside the primary functionalities.

---

`86-101`: **Robust Dropdown List Styling**  
The `.region-selector-list` class is carefully styled for dropdown presentation:  
- Absolute positioning and zero side margins ensure it aligns with its parent.  
- Removal of the top border (`border-top: none`) and application of a border-radius on the bottom corners create a polished look.  
- A fixed max-height with overflow handling enhances usability for long lists.  
The `z-index: 1000` ensures the dropdown overlays other content as needed.

---

`117-120`: **Subtle and Readable Placeholder Styling**  
The `.region-search-input::placeholder` styling makes use of reduced opacity and a complementary color (`var(--forest-jade)`), ensuring that placeholder text remains unobtrusive yet visible.

---

`122-124`: **Clear Focus Indicator for Search Input**  
The focus state for `.region-search-input` changes the `border-bottom-color` to `var(--primary-color)`, providing a straightforward and accessible visual indicator.

---

`126-137`: **Interactive Selector Item Styling**  
The `.region-selector-item` class is designed with flexible layout properties and a smooth background transition, creating a user-friendly clickable area. The inclusion of touch-related properties further supports mobile interactions.

---

`139-142`: **Responsive Hover and Focus Effects**  
The style rules for `.region-selector-item:hover, .region-selector-item:focus` apply a distinct background color (`var(--gum-leaf)`), enhancing accessibility and providing clear feedback during user interaction.

---

`144-147`: **Distinct Styling for Selected Items**  
The `.region-selector-item.selected` class reinforces visual hierarchy by altering both the background color and font weight, making it easier for users to identify their selection.

---

`149-151`: **Crisp Open State Button Appearance**  
The `.region-selector-btn.open` class adjusts the border-radius to emphasize the open state of the dropdown. This subtle change contributes to an overall consistent and modern design.

---

`153-162`: **Well-Constructed Mobile Responsiveness**  
The media query ensures that on devices with a maximum width of 480px:  
- The `.wrapper` adjusts its width (using `calc(100% - 32px)`) and sets `max-width: 100%;` to better accommodate smaller screens.  
- The `.region-selector` maintains a full-width layout.  
This responsive design supports an optimal mobile user experience.

</details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (5)</summary>

`4-12`: **Well-structured component setup with clear constants and typing.**

The imports are organized well, and the extraction of string constants (`DEFAULT_REGION_NAME`, `SEARCH_PLACEHOLDER`) improves maintainability. The Ukrainian text regex constant is also a good practice to avoid repeating complex regex patterns.

---

`14-36`: **Component props and state management are well-organized.**

The component now accepts an optional `setCurrentRegion` function prop, properly uses the Readonly type modifier, and maintains internal state for handling the dropdown's functionality. The refs are appropriately typed and named.

---

`177-183`: **Good implementation of the input change handler.**

The handler correctly updates the input value and resets the focused index when the user types in the search field.

---

`185-203`: **Well-managed focus handling in the dropdown toggle.**

The toggle function manages focus transitions effectively, ensuring the selected region gets focused when opening the dropdown. The timeout ensures the DOM has updated before attempting to focus elements.

---

`245-263`: <details>
<summary>❓ Verification inconclusive</summary>

**Potential ARIA attribute conflict.**

The search input has `aria-activedescendant` which is also present on the parent div with `id="region-list"`. This might confuse screen readers. Consider keeping it only on the most appropriate element.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if aria-activedescendant is recommended on both parent and child elements

echo "Checking ARIA best practices for aria-activedescendant..."
echo "Looking for similar patterns in the codebase..."

# Search for cases where aria-activedescendant is defined on both parent and child
rg -A 2 -B 2 "aria-activedescendant.*\n.*aria-activedescendant" --glob "*.tsx" --glob "*.jsx"
```

Length of output: 517

---

Below is an updated verification step along with the revised review comment. Since the initial search produced an error due to missing multiline support, please run the corrected command below to check whether any component applies the `aria-activedescendant` attribute on both a parent element and its child elements:



**Rewritten Review Comment:**

**Action Required: Verify ARIA Attribute Placement**

- The search input in `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (lines 245-263) sets the `aria-activedescendant` attribute.
- There is a potential issue if the parent element (with `id="region-list"`) also sets the same attribute, as this could confuse screen readers.
- Please confirm (by running the above command or manually inspecting related components) that the attribute is applied only on the element that manages the active descendant relationship.
- If the parent element is also setting this attribute, consider removing it there and ensuring that only the most appropriate element (likely the input) retains it.



---

🏁 Script executed:

```shell

#!/bin/bash
echo "Searching for instances where 'aria-activedescendant' is used concurrently in nearby elements (multiline search):"
rg -U "aria-activedescendant.*\n.*aria-activedescendant" --glob "*.tsx" --glob "*.jsx"
```

Length of output: 453

---



</details>

**Action Required: Verify ARIA Attribute Usage**

- The search input in `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (lines 245–263) sets `aria-activedescendant`.  
- The original concern noted a potential conflict if the parent element (with `id="region-list"`) also uses `aria-activedescendant`.  
- A multiline grep check was attempted but did not yield conclusive results. Please manually verify that the parent element is not redundantly setting `aria-activedescendant`. If it is, remove the attribute from the parent so that only the input element manages the active descendant relationship.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-23T12:55:02Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-23T12:55:04Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (3)</summary><blockquote>

`37-46`: **Consider performance optimization for filtering logic**

The filtering logic is clear and properly uses a memoized callback for the Ukrainian text validation. However, `filteredRegions` will be recalculated on every render since it's not wrapped in `useMemo`.


Consider memoizing the filtered regions to avoid unnecessary calculations:

```diff
- const filteredRegions = regionsArray.filter((region) =>
-   isUkrainianText(inputValue)
-     ? region.name.toLowerCase().includes(inputValue.toLowerCase())
-     : true,
- );

+ const filteredRegions = useMemo(() => 
+   regionsArray.filter((region) =>
+     isUkrainianText(inputValue)
+       ? region.name.toLowerCase().includes(inputValue.toLowerCase())
+       : true,
+   ),
+   [inputValue, isUkrainianText]
+ );
```

---

`48-59`: **Ensure robust scrolling behavior**

The `scrollToElement` function has good error handling with a fallback to `element.focus()`. However, the empty catch block might hide issues.


Consider adding error logging in the catch block:

```diff
  try {
    if (typeof element.scrollIntoView === 'function') {
      element.scrollIntoView({
        block: 'center',
        behavior: 'smooth',
      });
    }
-  } catch {
+  } catch (error) {
+    console.error('Error scrolling to element:', error);
    element.focus();
  }
```

---

`215-295`: **Consider adding empty state for filtered results**

The component does not handle the case when `filteredRegions` is empty (no matches for the search term). Users might benefit from a message indicating no results were found.


Add a message when no regions match the search criteria:

```diff
            />
+           {filteredRegions.length === 0 && (
+             <div className={st['no-results-message']}>
+               Немає результатів
+             </div>
+           )}
            {filteredRegions.map((region, index) => (
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3277160842b499da217b44406e067d1f5ee71cf8 and 775c07da17a160ba81454b3f0a96e795b86af4cf.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/types.ts (2)</summary>

* `RegionsListProps` (6-8)
* `Region` (1-4)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: unit-tests
* GitHub Check: e2e-tests
* GitHub Check: Analyze (javascript-typescript)

</details>

<details>
<summary>🔇 Additional comments (11)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (11)</summary>

`3-12`: **Improved import structure and constants handling**

The addition of constants like `DEFAULT_REGION_NAME`, `SEARCH_PLACEHOLDER`, and `UKRAINIAN_TEXT_REGEX` is a good practice for maintainability. The regex for Ukrainian text validation is a nice touch for filtering logic.

---

`14-36`: **Component and state setup looks good**

The component now manages its internal state for the selected region, making it more self-contained. The introduction of `inputValue` state and `inputRef` is appropriate for the new search functionality. Using `defaultRegion` to initialize the state is a reasonable approach.

---

`61-75`: **Region selection handling is well implemented**

The `handleRegionSelect` function properly manages state updates and conditionally calls the optional `setCurrentRegion` callback. Resetting the input value when a region is selected is a good UX choice.

---

`77-86`: **Good outside click handler with input reset**

The outside click handler appropriately closes the dropdown and resets the search input.

---

`88-139`: **Excellent keyboard navigation implementation**

The keyboard navigation implementation is thorough and handles multiple keyboard interactions including Tab, arrow keys, Enter, Space, and Escape. The switch case structure is clear and each case is well-handled.

---

`141-175`: **Well-structured navigation helper functions**

The extracted helper functions for calculating navigation indices improve code readability and maintainability. Each function has a clear purpose and handles edge cases appropriately.

---

`177-183`: **Input change handler is concise and effective**

The input change handler is simple and effective, updating the input value and resetting the focused index when the search term changes.

---

`185-203`: **Toggle dropdown handling with focus management**

The `toggleDropdown` function handles opening and closing the dropdown, and also manages focus appropriately. The use of `setTimeout` to ensure the DOM is ready before attempting to focus is a good practice.

---

`205-213`: **Effect hook with proper cleanup**

The effect hook correctly adds and removes event listeners, and sets focus to the input field when the dropdown opens.

---

`245-263`: **Accessibility-rich search input implementation**

The search input has comprehensive ARIA attributes for accessibility. This is excellent for screen reader support.

---

`264-290`: **Using filtered regions for rendering the list**

The component now correctly renders the filtered regions list instead of the full regions array. The keyboard event handling on list items is well-implemented.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-23T14:00:32Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-23T14:00:35Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (4)</summary><blockquote>

`37-46`: **Consider optimizing filteredRegions with useMemo**

The `filteredRegions` computation happens on every render, which could be optimized with `useMemo` to prevent unnecessary recalculations when other state changes don't affect the filtering.


```diff
- const filteredRegions = regionsArray.filter((region) =>
-   isUkrainianText(inputValue)
-     ? region.name.toLowerCase().includes(inputValue.toLowerCase())
-     : true,
- );

+ const filteredRegions = React.useMemo(() => {
+   return regionsArray.filter((region) =>
+     isUkrainianText(inputValue)
+       ? region.name.toLowerCase().includes(inputValue.toLowerCase())
+       : true,
+   );
+ }, [regionsArray, inputValue, isUkrainianText]);
```

---

`173-191`: **Consider refactoring setTimeout in toggleDropdown**

Using `setTimeout` with a zero delay is a common pattern, but it might lead to unexpected behavior in some cases. Consider refactoring to use `useEffect` for focus management after state updates.


```diff
- toggleDropdown = useCallback(() => {
-   setIsOpen((prev) => {
-     if (!prev) {
-       setInputValue('');
-       setTimeout(() => {
-         if (selectedRegion !== DEFAULT_REGION_NAME) {
-           const selectedElement = itemsRef.current[focusedIndex || 0];
-           if (selectedElement) {
-             selectedElement.focus();
-             scrollToElement(selectedElement);
-           }
-         } else {
-           inputRef.current?.focus();
-         }
-       }, 0);
-     }
-     return !prev;
-   });
- }, [selectedRegion, focusedIndex, scrollToElement]);

+ toggleDropdown = useCallback(() => {
+   setIsOpen((prev) => {
+     if (!prev) {
+       setInputValue('');
+     }
+     return !prev;
+   });
+ }, []);
+ 
+ // Handle focus management after state updates
+ useEffect(() => {
+   if (isOpen && selectedRegion !== DEFAULT_REGION_NAME) {
+     const selectedElement = itemsRef.current[focusedIndex || 0];
+     if (selectedElement) {
+       selectedElement.focus();
+       scrollToElement(selectedElement);
+     }
+   } else if (isOpen) {
+     inputRef.current?.focus();
+   }
+ }, [isOpen, selectedRegion, focusedIndex, scrollToElement]);
```

---

`252-278`: **Good use of filteredRegions for dynamic filtering**

Using `filteredRegions` for rendering ensures that the list properly updates based on the user's input. The keyboard navigation is properly integrated with this filtered list.


However, the aria-label is in English (`Select ${region.name}`) while the rest of the UI is in Ukrainian. Consider translating this for consistency.


```diff
- aria-label={`Select ${region.name}`}
+ aria-label={`Обрати ${region.name}`}
```

---

`261-265`: **Consider simplifying the onKeyDown handler for region selection items**

Since the inline onKeyDown handler only handles Enter and Space keys, you could use the more concise arrow function syntax.


```diff
- onKeyDown={(e) => {
-   if (e.key === 'Enter' || e.key === ' ') {
-     handleRegionSelect(region);
-   }
- }}
+ onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && handleRegionSelect(region)}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 775c07da17a160ba81454b3f0a96e795b86af4cf and 311d3bf658f997bfc4c2801ec4b7d0badbf687b5.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (3 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (1)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/types.ts (2)</summary>

* `RegionsListProps` (6-8)
* `Region` (1-4)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (8)</summary>

`10-12`: **Good practice using constants for configuration values**

Defining constants for default values and patterns at the top of the file improves maintainability and makes the code more self-documenting.

---

`14-28`: **Good implementation of state management**

The component now properly manages its internal state with a default region and focused index. Using `useState` with meaningful initial values helps ensure the component behaves correctly when first rendered.

---

`29-29`: **Effective addition of input state for filtering**

The new `inputValue` state is a good approach for managing the search functionality.

---

`48-59`: **Well-implemented scrolling function with error handling**

The `scrollToElement` function includes a good fallback to `element.focus()` in case `scrollIntoView` fails, enhancing robustness.

---

`61-75`: **Good update to region selection handling**

The `handleRegionSelect` function now properly resets the input value and conditionally calls the `setCurrentRegion` callback, maintaining backward compatibility with the optional prop pattern.

---

`147-163`: **Clean helper functions for index calculation**

The helper functions for calculating previous and next indices are well-implemented and improve code readability. They handle edge cases appropriately by wrapping around to the beginning or end of the list.

---

`233-251`: **Well-implemented search input with proper accessibility attributes**

The search input implementation includes comprehensive ARIA attributes, which is excellent for accessibility. The component is properly wired to the state and handlers.

---

`88-145`: <details>
<summary>❓ Verification inconclusive</summary>

**Excellent keyboard navigation implementation**

The enhanced keyboard navigation with dedicated handlers for different keys greatly improves accessibility. The code is well-structured with clear separation of concerns for each key event.


However, consider addressing a potential edge case: what happens if `filteredRegions` is empty? The current navigation logic might lead to issues if there are no items to navigate through.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if the code handles empty filteredRegions in keyboard navigation

# Look for any handling of empty filteredRegions in the component
rg -A 3 -B 3 "filteredRegions.length === 0" --glob "*.tsx" 
rg -A 3 -B 3 "!filteredRegions.length" --glob "*.tsx"
rg -A 3 -B 3 "filteredRegions.length < 1" --glob "*.tsx"
```

Length of output: 175

---



</details>

**Action Required: Verify behavior for empty `filteredRegions` in keyboard navigation.**

Excellent implementation of keyboard navigation with clear separation of concerns for handling key events. However, there is no explicit check for an empty `filteredRegions` array. Without guarding against an empty list, functions like `calculateNextTabOrArrowDownIndex` and `calculatePreviousTabOrArrowUpIndex` may compute invalid focus indices, possibly leading to errors when users interact with the control.

- **Location to verify:**  
  `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (Lines 88–145)

Please verify manually whether an empty `filteredRegions` scenario is handled elsewhere or consider adding a guard to prevent navigation when there are no items.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-27T14:57:17Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-27T14:57:20Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (6)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css (2)</summary><blockquote>

`45-55`: **Good improvement to typography rendering**

Adding font smoothing properties (`-webkit-font-smoothing`, `-moz-osx-font-smoothing`, and `text-rendering`) enhances text legibility across different browsers and devices.

Consider using relative units (rem) instead of pixels for font-size for better accessibility. This allows text to scale properly when users change their browser's font size settings.


```diff
  font-weight: 400;
- font-size: 14px;
+ font-size: 0.875rem;
  line-height: 26px;
```

---

`109-131`: **Well-structured styling for the new search input**

The search input styling is cleanly implemented with appropriate styles for the base state, placeholder text, and focus state.

Note that the height (28px) plus padding (24px) equals 52px, which is slightly larger than the region-selector-item height (50px). Consider matching these heights for visual consistency.


```diff
  position: sticky;
  top: 0;
- height: 28px;
+ height: 26px;
  width: calc(100% - 24px);
```

</blockquote></details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (4)</summary><blockquote>

`6-6`: **Ensure naming consistency between component and its props interface**

The component has been renamed from `RegionsList` to `RegList`, but it still uses `RegionsListProps` interface. For better maintainability and code clarity, align the naming convention:

1. Either rename the component back to `RegionsList` to match the props interface, or
2. Update the props interface name to `RegListProps` in the types.ts file



Also applies to: 15-15, 277-277

---

`92-108`: **Consider simplifying the index calculation helper functions**

These two functions are very similar and could be consolidated into a single function with a direction parameter to reduce code duplication.

```diff
- const calculatePreviousTabOrArrowUpIndex = (
-   focusedIndex: number | null,
-   length: number,
- ): number => {
-   return focusedIndex === null || focusedIndex <= 0
-     ? length - 1
-     : focusedIndex - 1;
- };
-
- const calculateNextTabOrArrowDownIndex = (
-   focusedIndex: number | null,
-   length: number,
- ): number => {
-   return focusedIndex === null || focusedIndex >= length - 1
-     ? 0
-     : focusedIndex + 1;
- };

+ const calculateNewIndex = (
+   focusedIndex: number | null,
+   length: number,
+   direction: 'next' | 'previous'
+ ): number => {
+   if (direction === 'previous') {
+     return focusedIndex === null || focusedIndex <= 0
+       ? length - 1
+       : focusedIndex - 1;
+   } else {
+     return focusedIndex === null || focusedIndex >= length - 1
+       ? 0
+       : focusedIndex + 1;
+   }
+ };
```

---

`118-175`: **Optimize keyboard navigation event handler**

The keyboard navigation is comprehensive but has some potential issues:

1. Overriding the browser's default Tab behavior (lines 127-140) might confuse users who expect standard web navigation patterns.
2. The dependency array includes `filteredRegions`, which might cause unnecessary re-renders if the filtered list changes frequently.

Consider:
1. Removing the Tab key handling and letting the browser handle tab navigation
2. Using functional updates for `setFocusedIndex` to reduce dependencies


```diff
const handleKeyDown = useCallback(
  (e: React.KeyboardEvent<HTMLDivElement>) => {
    if (!isOpen) {
      return;
    }

    let newIndex: number;

    switch (e.key) {
-     case 'Tab':
-       e.preventDefault();
-       newIndex = e.shiftKey
-         ? calculatePreviousTabOrArrowUpIndex(
-             focusedIndex,
-             filteredRegions.length,
-           )
-         : calculateNextTabOrArrowDownIndex(
-             focusedIndex,
-             filteredRegions.length,
-           );
-       setFocusedIndex(newIndex);
-       itemsRef.current[newIndex]?.focus();
-       break;
      case 'ArrowDown':
        e.preventDefault();
-       newIndex = calculateNextTabOrArrowDownIndex(
-         focusedIndex,
-         filteredRegions.length,
-       );
-       setFocusedIndex(newIndex);
+       setFocusedIndex(prevIndex => {
+         const newIndex = calculateNextTabOrArrowDownIndex(
+           prevIndex,
+           filteredRegions.length,
+         );
+         itemsRef.current[newIndex]?.focus();
+         return newIndex;
+       });
-       itemsRef.current[newIndex]?.focus();
        break;
      // ... similar changes for ArrowUp
    }
  },
- [isOpen, focusedIndex, filteredRegions, handleRegionSelect],
+ [isOpen, filteredRegions.length, handleRegionSelect, itemsRef],
);
```

---

`224-242`: **Well-implemented search input with appropriate accessibility attributes**

The search input includes important ARIA attributes for accessibility. However, there are potentially conflicting or redundant attributes:

- `aria-owns="region-list"` and `aria-controls="region-list"` serve similar purposes
- `role="combobox"` might not be necessary with the other ARIA attributes present

Consider simplifying the ARIA attributes while maintaining accessibility.


```diff
<input
  ref={inputRef}
  type="text"
  value={inputValue}
  onChange={handleInputChange}
  placeholder={SEARCH_PLACEHOLDER}
  className={st['region-search-input']}
  data-testid="region-search-input"
  aria-label="Пошук регіону"
  aria-controls="region-list"
  aria-expanded={isOpen}
  aria-haspopup="listbox"
  aria-autocomplete="list"
  role="combobox"
- aria-owns="region-list"
  aria-activedescendant={
    focusedIndex !== null ? `region-${focusedIndex}` : undefined
  }
/>
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 311d3bf658f997bfc4c2801ec4b7d0badbf687b5 and 93bd1c461970f29bc21d55720634478647c60968.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `CHANGELOG.md` (1 hunks)
* `veterans/components/homePage/mapSection/MapSection.test.tsx` (2 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css` (1 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (5 hunks)
* `veterans/components/homePage/mapSection/regionsFilter/types.ts` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* veterans/components/homePage/mapSection/regionsFilter/types.ts
* CHANGELOG.md
* veterans/components/homePage/mapSection/MapSection.test.tsx

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: sonarqube
* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css (2)</summary>

`41-42`: **Great addition of touch-friendly properties!**

The addition of `-webkit-tap-highlight-color: transparent` and `touch-action: manipulation` improves the mobile user experience by removing the default tap highlights and ensuring proper touch events handling.

---

`155-158`: **Good addition of selected state styling**

Adding distinct visual styling for the selected state improves user experience by clearly indicating the current selection.

</details>
<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (4)</summary>

`11-13`: **Good use of constants for improved maintainability**

Extracting string literals into named constants improves code readability and makes future updates easier. The Ukrainian text regex is a good candidate for reuse.

---

`24-36`: **Well-implemented search filtering with Ukrainian text support**

The combination of a search input state with a specialized regex for Ukrainian text provides a good user experience for filtering regions.

---

`243-243`: **Good use of filtered regions and selected state**

Using the filtered regions array for rendering and adding a visual indicator for the selected item improves the user experience significantly.



Also applies to: 260-260

---

`81-90`: _🛠️ Refactor suggestion_

**Missing dependency in useCallback**

The `handleClickOutside` function uses `setInputValue` but doesn't include it in the dependency array. This could lead to stale closures if `setInputValue` ever changes.

```diff
  const handleClickOutside = useCallback((e: MouseEvent) => {
    if (
      dropdownRef.current &&
      !dropdownRef.current.contains(e.target as Node)
    ) {
      setIsOpen(false);
      setInputValue('');
      setFocusedIndex(null);
    }
- }, []);
+ }, [setInputValue]);
```



> Likely an incorrect or invalid review comment.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-27T20:24:19Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-27T20:24:22Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (2)</summary><blockquote>

`11-13`: **Consider externalizing or localizing constants.**  
Hardcoding strings (region names, placeholders) and the regex may reduce flexibility. If these values are subject to frequent changes or need translations, consider moving them to a config or localization module.

---

`227-246`: **Match search input height with region items.**  
Address the user comment about ensuring the `.region-search-input` height matches the `.region-selector-item`. This alignment can make the UI more consistent and visually engaging.  

```diff
.region-search-input {
+  /* Example: match the line height or padding to that of .region-selector-item */
+  line-height: var(--region-selector-item-line-height);
+  height: var(--region-selector-item-height);
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 93bd1c461970f29bc21d55720634478647c60968 and 8ab13a39fee966a62a9c2afcec5dd7a759df708d.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx` (4 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: sonarqube
* GitHub Check: e2e-tests

</details>

<details>
<summary>🔇 Additional comments (13)</summary><blockquote>

<details>
<summary>veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx (13)</summary>

`6-6`: **No issues with importing the `RegionsListProps` interface.**
The import statement correctly references the new interface file.

---

`15-18`: **Review apparent interface discrepancy.**  
This code references `selectedRegion` and `setSelectedRegion`, but the summary suggests these props were removed from the interface. Confirm that the interface and usage are aligned, or remove the props if they're no longer needed.  




> Likely an incorrect or invalid review comment.

---

`23-23`: **Ref usage is appropriate.**  
Using a ref for the input is a fitting way to manage focus behavior.

---

`25-27`: **LGTM regarding new state variables.**  
The states `isOpen` and `inputValue` appear necessary for controlling dropdown visibility and storing user input.

---

`29-32`: **Regex-based filtering helper looks good.**  
The `isUkrainianText` callback is straightforward. Verify it covers all desired Ukrainian characters and consider whether partial matches from non-Ukrainian characters are intentionally excluded.

---

`35-39`: **Verify filter logic for non-Ukrainian text.**  
Right now, if the user types non-Ukrainian characters, the filtering is disabled and all regions are displayed. Confirm that this is the actual desired behavior.

---

`41-49`: **Ensure fallback logic for default region is correct.**  
If no region named `'Всі'` exists, the code defaults to an empty object, which may cause confusion for users. Verify this matches functional or product requirements.

---

`84-93`: **Dropdown click-outside behavior is consistent.**  
Hiding the dropdown and clearing the input upon outside clicks is a common pattern. Ensure the UX is acceptable when users accidentally click out and lose typed input.

---

`95-111`: **Helper functions for keyboard navigation are clean and reusable.**  
The modular approach to calculating next/previous indices is well-structured, preventing off-by-one errors.

---

`113-118`: **Input change handling is straightforward.**  
Resetting `focusedIndex` on every user input ensures fresh navigation. This is a sensible approach to prevent index mismatches.

---

`183-189`: **Focusing the input on open.**  
Good user experience strategy. Confirm that focusing the input unconditionally is desired in all scenarios (e.g., for screen readers).

---

`255-260`: **Consistent handling of Enter and Space keys.**  
Allowing users to select a region with both keys improves accessibility. Implementation looks good.

---

`263-263`: **Proper use of classes for highlighting selected/focused items.**  
Combining `focused` and `selected` states using conditional classes helps communicate item state effectively.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-27T20:46:55Z
user: login: Anton-88
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T20:54:57Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-27T20:55:17Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8ab13a39fee966a62a9c2afcec5dd7a759df708d and 18663fba9ac840336428dc7f50e36917578444a9.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: unit-tests
* GitHub Check: e2e-tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-27T20:57:30Z
user: login: Anton-88
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T20:59:08Z
user: login: coderabbitai[bot]
state: APPROVED
author_association: NONE
submitted_at: 2025-03-27T20:59:17Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-27T20:59:30Z
user: login: VitalyyP
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T08:26:18Z
user: login: yuramax
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T10:37:06Z
user: login: yuramax
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T11:36:20Z
user: login: yuramax
body: LGTM! 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T11:36:54Z
user: login: Anton-88
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T11:38:45Z

Review comments:
diff_hunk: @@ -1,98 +1,171 @@
 import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінницька', numOfInitiatives: 4 },
+    { name: 'Волинська', numOfInitiatives: 24 },
+    { name: 'Дніпропетровська', numOfInitiatives: 12 },
+    { name: 'Донецька', numOfInitiatives: 14 },
+    { name: 'Житомирська', numOfInitiatives: 19 },
+    { name: 'Закарпатська', numOfInitiatives: 28 },
+    { name: 'Запорізька', numOfInitiatives: 8 },
+    { name: 'Івано-Франківська', numOfInitiatives: 17 },
+    { name: 'Київська', numOfInitiatives: 5 },
+    { name: 'Кіровоградська', numOfInitiatives: 21 },
+    { name: 'Луганська', numOfInitiatives: 3 },
+    { name: 'Львівська', numOfInitiatives: 11 },
+    { name: 'Миколаївська', numOfInitiatives: 25 },
+    { name: 'Одеська', numOfInitiatives: 9 },
+    { name: 'Полтавська', numOfInitiatives: 16 },
+    { name: 'Рівненська', numOfInitiatives: 7 },
+    { name: 'Сумська', numOfInitiatives: 22 },
+    { name: 'Тернопільська', numOfInitiatives: 6 },
+    { name: 'Харківська', numOfInitiatives: 15 },
+    { name: 'Херсонська', numOfInitiatives: 2 },
+    { name: 'Хмельницька', numOfInitiatives: 20 },
+    { name: 'Черкаська', numOfInitiatives: 10 },
+    { name: 'Чернівецька', numOfInitiatives: 23 },
+    { name: 'Чернігівська', numOfInitiatives: 18 },
+    { name: 'АР Крим', numOfInitiatives: 1 },
+    { name: 'Всі', numOfInitiatives: 185 },
+  ];
+});
 
-describe('RegionsList Component', () => {
-  let mockSetCurrentRegion: jest.Mock;
+const setupRegionsList = () => {
+  render(<RegionsList />);
+};
 
-  beforeEach(() => {
-    mockSetCurrentRegion = jest.fn();
-  });
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+
+const openDropdown = () => fireEvent.click(getDropdownButton());
+
+const pressKey = (element: HTMLElement, key: string) =>
+  fireEvent.keyDown(element, { key });
+
+const selectRegion = (index: number) => {
+  fireEvent.click(getAllRegions()[index]);
+};
 
+describe('RegionsList Component', () => {
   test('correctly renders and shows default region', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('dropdown opens and closes when button is clicked', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    const button = screen.getByTestId('btn-for-region-selection');
+    const button = getDropdownButton();
 
     fireEvent.click(button);
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
+    expect(getRegionsList()).toBeInTheDocument();
 
     fireEvent.click(button);
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('contains exactly 26 regions', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    setupRegionsList();
+
+    openDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
+
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupRegionsList();
+
+    openDropdown();
+    // fireEvent.click(getAllRegions()[1]);
+    selectRegion(1);
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+    openDropdown();
+
+    await waitFor(
+      () => {
+        expect(getAllRegions()[1]).toHaveFocus();
+      },
+      { timeout: 1000 },
+    );
   });
 
   test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    const list = screen.getByTestId('list-of-regions');
-    const regions = screen.getAllByRole('menuitemradio');
+    openDropdown();
+    const regions = getAllRegions();
 
-    list.focus();
+    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
 
-    fireEvent.keyDown(list, { key: 'ArrowDown' });
+    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
+    pressKey(regions[0], 'ArrowDown');
     expect(regions[1]).toHaveFocus();
 
-    fireEvent.keyDown(list, { key: 'ArrowUp' });
+    // fireEvent.keyDown(regions[1], { key: 'ArrowUp' });
+    pressKey(regions[0], 'ArrowUp');
     expect(regions[0]).toHaveFocus();
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix ArrowUp test logic**

There appears to be an issue with the Arrow Up test. You're pressing the ArrowUp key on regions[0], but testing if regions[0] has focus. This is likely incorrect, as pressing ArrowUp should move to the previous item or wrap to the last item.


```diff
-    pressKey(regions[0], 'ArrowUp');
-    expect(regions[0]).toHaveFocus();
+    // From regions[1] (set in lines 111-112)
+    pressKey(regions[1], 'ArrowUp');
+    expect(regions[0]).toHaveFocus();
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    // From regions[1] (set in lines 111-112)
    pressKey(regions[1], 'ArrowUp');
    expect(regions[0]).toHaveFocus();
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->

✅ Addressed in commit 27270f7
created_at: 2025-03-19T10:30:37Z
author_association: NONE
diff_hunk: @@ -1,98 +1,171 @@
 import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінницька', numOfInitiatives: 4 },
+    { name: 'Волинська', numOfInitiatives: 24 },
+    { name: 'Дніпропетровська', numOfInitiatives: 12 },
+    { name: 'Донецька', numOfInitiatives: 14 },
+    { name: 'Житомирська', numOfInitiatives: 19 },
+    { name: 'Закарпатська', numOfInitiatives: 28 },
+    { name: 'Запорізька', numOfInitiatives: 8 },
+    { name: 'Івано-Франківська', numOfInitiatives: 17 },
+    { name: 'Київська', numOfInitiatives: 5 },
+    { name: 'Кіровоградська', numOfInitiatives: 21 },
+    { name: 'Луганська', numOfInitiatives: 3 },
+    { name: 'Львівська', numOfInitiatives: 11 },
+    { name: 'Миколаївська', numOfInitiatives: 25 },
+    { name: 'Одеська', numOfInitiatives: 9 },
+    { name: 'Полтавська', numOfInitiatives: 16 },
+    { name: 'Рівненська', numOfInitiatives: 7 },
+    { name: 'Сумська', numOfInitiatives: 22 },
+    { name: 'Тернопільська', numOfInitiatives: 6 },
+    { name: 'Харківська', numOfInitiatives: 15 },
+    { name: 'Херсонська', numOfInitiatives: 2 },
+    { name: 'Хмельницька', numOfInitiatives: 20 },
+    { name: 'Черкаська', numOfInitiatives: 10 },
+    { name: 'Чернівецька', numOfInitiatives: 23 },
+    { name: 'Чернігівська', numOfInitiatives: 18 },
+    { name: 'АР Крим', numOfInitiatives: 1 },
+    { name: 'Всі', numOfInitiatives: 185 },
+  ];
+});
 
-describe('RegionsList Component', () => {
-  let mockSetCurrentRegion: jest.Mock;
+const setupRegionsList = () => {
+  render(<RegionsList />);
+};
 
-  beforeEach(() => {
-    mockSetCurrentRegion = jest.fn();
-  });
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+
+const openDropdown = () => fireEvent.click(getDropdownButton());
+
+const pressKey = (element: HTMLElement, key: string) =>
+  fireEvent.keyDown(element, { key });
+
+const selectRegion = (index: number) => {
+  fireEvent.click(getAllRegions()[index]);
+};
 
+describe('RegionsList Component', () => {
   test('correctly renders and shows default region', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('dropdown opens and closes when button is clicked', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    const button = screen.getByTestId('btn-for-region-selection');
+    const button = getDropdownButton();
 
     fireEvent.click(button);
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
+    expect(getRegionsList()).toBeInTheDocument();
 
     fireEvent.click(button);
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('contains exactly 26 regions', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    setupRegionsList();
+
+    openDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
+
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupRegionsList();
+
+    openDropdown();
+    // fireEvent.click(getAllRegions()[1]);
+    selectRegion(1);
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+    openDropdown();
+
+    await waitFor(
+      () => {
+        expect(getAllRegions()[1]).toHaveFocus();
+      },
+      { timeout: 1000 },
+    );
   });
 
   test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    const list = screen.getByTestId('list-of-regions');
-    const regions = screen.getAllByRole('menuitemradio');
+    openDropdown();
+    const regions = getAllRegions();
 
-    list.focus();
+    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
 
-    fireEvent.keyDown(list, { key: 'ArrowDown' });
+    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
+    pressKey(regions[0], 'ArrowDown');
     expect(regions[1]).toHaveFocus();
 
-    fireEvent.keyDown(list, { key: 'ArrowUp' });
+    // fireEvent.keyDown(regions[1], { key: 'ArrowUp' });
+    pressKey(regions[0], 'ArrowUp');
     expect(regions[0]).toHaveFocus();
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: Anton-88
body: thanks, it is fixed in the commit [27270f7](https://github.com/boarlabsxyz/razom/pull/130/commits/27270f796401abdbad8f7c3de3b8a3e63cf682c9)
created_at: 2025-03-19T10:34:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,98 +1,171 @@
 import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінницька', numOfInitiatives: 4 },
+    { name: 'Волинська', numOfInitiatives: 24 },
+    { name: 'Дніпропетровська', numOfInitiatives: 12 },
+    { name: 'Донецька', numOfInitiatives: 14 },
+    { name: 'Житомирська', numOfInitiatives: 19 },
+    { name: 'Закарпатська', numOfInitiatives: 28 },
+    { name: 'Запорізька', numOfInitiatives: 8 },
+    { name: 'Івано-Франківська', numOfInitiatives: 17 },
+    { name: 'Київська', numOfInitiatives: 5 },
+    { name: 'Кіровоградська', numOfInitiatives: 21 },
+    { name: 'Луганська', numOfInitiatives: 3 },
+    { name: 'Львівська', numOfInitiatives: 11 },
+    { name: 'Миколаївська', numOfInitiatives: 25 },
+    { name: 'Одеська', numOfInitiatives: 9 },
+    { name: 'Полтавська', numOfInitiatives: 16 },
+    { name: 'Рівненська', numOfInitiatives: 7 },
+    { name: 'Сумська', numOfInitiatives: 22 },
+    { name: 'Тернопільська', numOfInitiatives: 6 },
+    { name: 'Харківська', numOfInitiatives: 15 },
+    { name: 'Херсонська', numOfInitiatives: 2 },
+    { name: 'Хмельницька', numOfInitiatives: 20 },
+    { name: 'Черкаська', numOfInitiatives: 10 },
+    { name: 'Чернівецька', numOfInitiatives: 23 },
+    { name: 'Чернігівська', numOfInitiatives: 18 },
+    { name: 'АР Крим', numOfInitiatives: 1 },
+    { name: 'Всі', numOfInitiatives: 185 },
+  ];
+});
 
-describe('RegionsList Component', () => {
-  let mockSetCurrentRegion: jest.Mock;
+const setupRegionsList = () => {
+  render(<RegionsList />);
+};
 
-  beforeEach(() => {
-    mockSetCurrentRegion = jest.fn();
-  });
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+
+const openDropdown = () => fireEvent.click(getDropdownButton());
+
+const pressKey = (element: HTMLElement, key: string) =>
+  fireEvent.keyDown(element, { key });
+
+const selectRegion = (index: number) => {
+  fireEvent.click(getAllRegions()[index]);
+};
 
+describe('RegionsList Component', () => {
   test('correctly renders and shows default region', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('dropdown opens and closes when button is clicked', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    const button = screen.getByTestId('btn-for-region-selection');
+    const button = getDropdownButton();
 
     fireEvent.click(button);
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
+    expect(getRegionsList()).toBeInTheDocument();
 
     fireEvent.click(button);
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('contains exactly 26 regions', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    setupRegionsList();
+
+    openDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
+
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupRegionsList();
+
+    openDropdown();
+    // fireEvent.click(getAllRegions()[1]);
+    selectRegion(1);
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+    openDropdown();
+
+    await waitFor(
+      () => {
+        expect(getAllRegions()[1]).toHaveFocus();
+      },
+      { timeout: 1000 },
+    );
   });
 
   test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
+    setupRegionsList();
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    const list = screen.getByTestId('list-of-regions');
-    const regions = screen.getAllByRole('menuitemradio');
+    openDropdown();
+    const regions = getAllRegions();
 
-    list.focus();
+    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
 
-    fireEvent.keyDown(list, { key: 'ArrowDown' });
+    // fireEvent.keyDown(regions[0], { key: 'ArrowDown' });
+    pressKey(regions[0], 'ArrowDown');
     expect(regions[1]).toHaveFocus();
 
-    fireEvent.keyDown(list, { key: 'ArrowUp' });
+    // fireEvent.keyDown(regions[1], { key: 'ArrowUp' });
+    pressKey(regions[0], 'ArrowUp');
     expect(regions[0]).toHaveFocus();
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: @Anton-88 You're welcome! I'm glad to see the test logic issue has been addressed in your commit. The fix ensures the Arrow Up test properly checks navigation from one item to the previous item.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-19T10:35:21Z
author_association: NONE
diff_hunk: @@ -1,98 +1,125 @@
 import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
-
-describe('RegionsList Component', () => {
-  let mockSetCurrentRegion: jest.Mock;
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінниця' },
+    { name: 'Луцьк' },
+    { name: 'Дніпро' },
+    { name: 'Донецьк' },
+    { name: 'Житомир' },
+    { name: 'Ужгород' },
+    { name: 'Запоріжжя' },
+    { name: 'Івано-Франківськ' },
+    { name: 'Київ' },
+    { name: 'Кропивницький' },
+    { name: 'Луганськ' },
+    { name: 'Львів' },
+    { name: 'Миколаїв' },
+    { name: 'Одеса' },
+    { name: 'Полтава' },
+    { name: 'Рівне' },
+    { name: 'Суми' },
+    { name: 'Тернопіль' },
+    { name: 'Харків' },
+    { name: 'Херсон' },
+    { name: 'Хмельницький' },
+    { name: 'Черкаси' },
+    { name: 'Чернівці' },
+    { name: 'Чернігів' },
+    { name: 'Сімферополь' },
+    { name: 'Всі' },
+  ];
+});
 
-  beforeEach(() => {
-    mockSetCurrentRegion = jest.fn();
-  });
+const setupRegionsList = () => render(<RegionsList />);
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+const openDropdown = () => fireEvent.click(getDropdownButton());
+const pressKey = (element: HTMLElement, key: string) =>
+  fireEvent.keyDown(element, { key });
+const selectRegion = (index: number) => fireEvent.click(getAllRegions()[index]);
+
+const setupDropdown = () => {
+  setupRegionsList();
+  openDropdown();
+};
+
+const setupDropdownWithSelection = (index: number) => {
+  setupDropdown();
+  selectRegion(index);
+  openDropdown();
+};
 
+describe('RegionsList Component', () => {
   test('correctly renders and shows default region', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    setupRegionsList();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('dropdown opens and closes when button is clicked', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-
-    const button = screen.getByTestId('btn-for-region-selection');
-
-    fireEvent.click(button);
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
-
-    fireEvent.click(button);
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    setupDropdown();
+    expect(getRegionsList()).toBeInTheDocument();
+    fireEvent.click(getDropdownButton());
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
   test('contains exactly 26 regions', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    setupDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupDropdownWithSelection(1);
+    await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
+      timeout: 1000,
+    });
   });
 
   test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
-    render(<RegionsList setCurrentRegion={mockSetCurrentRegion} />);
-
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    const list = screen.getByTestId('list-of-regions');
-    const regions = screen.getAllByRole('menuitemradio');
-
-    list.focus();
-
-    fireEvent.keyDown(list, { key: 'ArrowDown' });
+    setupDropdown();
+    const regions = getAllRegions();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'ArrowDown');
     expect(regions[1]).toHaveFocus();
-
-    fireEvent.keyDown(list, { key: 'ArrowUp' });
+    pressKey(regions[1], 'ArrowUp');
     expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'Enter');
+    expect(getDropdownButton()).toHaveTextContent(/Вінниця/i);
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-    fireEvent.keyDown(list, { key: 'Enter' });
-    expect(screen.getByTestId('btn-for-region-selection')).toHaveTextContent(
-      /Region 1/i,
-    );
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+  test('clears search term with backspace', async () => {
+    setupDropdown();
+    const list = getRegionsList();
+    pressKey(list!, 'в');
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    await waitFor(() => {
+      expect(getAllRegions().length).toBeLessThan(26);
+    });
 
-    if (document.activeElement) {
-      fireEvent.keyDown(document.activeElement, { key: ' ' });
-    }
-    expect(screen.getByTestId('btn-for-region-selection')).toHaveTextContent(
-      /Region 1/i,
-    );
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+    pressKey(list!, 'Backspace');
+
+    await waitFor(() => {
+      expect(getAllRegions().length).toBe(26);
+    });
   });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Consider adding edge case tests for filtering**

While the basic filtering functionality is well tested, consider adding tests for additional scenarios:

1. What happens when a user types text that doesn't match any region?
2. Is filtering case-insensitive? 
3. Does it handle multiple characters correctly?

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there are any tests for edge cases in filtering
rg -A 5 "test.*no match|test.*case insensitive|test.*multiple characters" ./veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
```

Length of output: 152

---



</details>

**Attention: Edge Case Filtering Tests Needed**

The current test verifies that the search term is cleared with a backspace, but it does not cover critical edge cases. In particular, there are no tests addressing the following scenarios:

- Behavior when a user types text that doesn't match any region.
- Ensuring that filtering is case-insensitive.
- Handling of multi-character inputs effectively.

Please add tests for these scenarios to ensure the filtering functionality is robust.

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commits 7dfc853 to 562c507
created_at: 2025-03-19T16:31:51Z
author_association: NONE
diff_hunk: @@ -1,124 +1,158 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+.wrapper {
+  width: 100%;
+  max-width: 240px;
+  padding: 16px;
+}
+
+.regions-wrapper {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.region-list-title {
+  font-size: 16px;
+  font-weight: 500;
+  color: var(--text-color);
+  margin: 0;
+}
+
+.region-selector {
+  position: relative;
+  width: 100%;
+}
+
+.region-selector-btn {
+  position: relative;
+  height: 50px;
+  margin-top: 12px;
+  padding: 12px;
+  width: 100%;
+  cursor: pointer;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  background-color: var(--white);
+  border: 1px solid var(--pattens-blue);
+  transition: all 0.3s ease-in-out;
+  -webkit-tap-highlight-color: transparent;
+  touch-action: manipulation;
+  margin: 0;
+}
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix margin property override**

There's a conflict between `margin-top: 12px` and `margin: 0`. The `margin: 0` will override the `margin-top` setting, potentially causing unintended behavior.

```diff
.region-selector-btn {
  position: relative;
  height: 50px;
  margin-top: 12px;
  padding: 12px;
  width: 100%;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: var(--white);
  border: 1px solid var(--pattens-blue);
  transition: all 0.3s ease-in-out;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
-  margin: 0;
+  margin: 12px 0 0 0;
}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
.region-selector-btn {
  position: relative;
  height: 50px;
  margin-top: 12px;
  padding: 12px;
  width: 100%;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: var(--white);
  border: 1px solid var(--pattens-blue);
  transition: all 0.3s ease-in-out;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  margin: 12px 0 0 0;
}
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 40-40: Unexpected shorthand property margin after margin-top



(lint/suspicious/noShorthandPropertyOverrides)

</details>

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-20T21:35:33Z
author_association: NONE
diff_hunk: @@ -3,116 +3,228 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінниця' },
+    { name: 'Луцьк' },
+    { name: 'Дніпро' },
+    { name: 'Донецьк' },
+    { name: 'Житомир' },
+    { name: 'Ужгород' },
+    { name: 'Запоріжжя' },
+    { name: 'Івано-Франківськ' },
+    { name: 'Київ' },
+    { name: 'Кропивницький' },
+    { name: 'Луганськ' },
+    { name: 'Львів' },
+    { name: 'Миколаїв' },
+    { name: 'Одеса' },
+    { name: 'Полтава' },
+    { name: 'Рівне' },
+    { name: 'Суми' },
+    { name: 'Тернопіль' },
+    { name: 'Харків' },
+    { name: 'Херсон' },
+    { name: 'Хмельницький' },
+    { name: 'Черкаси' },
+    { name: 'Чернівці' },
+    { name: 'Чернігів' },
+    { name: 'Сімферополь' },
+    { name: 'Всі' },
+  ];
+});
+
+const setupRegionsList = () => render(<RegionsList />);
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+const openDropdown = () => fireEvent.click(getDropdownButton());
+const pressKey = (
+  element: HTMLElement,
+  key: string,
+  shiftKey: boolean = false,
+) => fireEvent.keyDown(element, { key, shiftKey });
+const selectRegion = (index: number) => fireEvent.click(getAllRegions()[index]);
+
+const setupDropdown = () => {
+  setupRegionsList();
+  openDropdown();
+};
+
+const setupDropdownWithSelection = (index: number) => {
+  setupDropdown();
+  selectRegion(index);
+  openDropdown();
+};
+
+const typeText = (text: string) => {
+  const input = screen.getByTestId('region-search-input');
+  fireEvent.change(input, { target: { value: text } });
+};
 
 describe('RegionsList Component', () => {
-  let mockSetSelectedRegion: jest.Mock;
+  test('correctly renders and shows default region', () => {
+    setupRegionsList();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-  beforeEach(() => {
-    mockSetSelectedRegion = jest.fn();
+  test('dropdown opens and closes when button is clicked', () => {
+    setupDropdown();
+    expect(getRegionsList()).toBeInTheDocument();
+    fireEvent.click(getDropdownButton());
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
-  test('correctly renders and shows default region', () => {
-    render(
-      <RegionsList
-        selectedRegion="Region 5"
-        setSelectedRegion={mockSetSelectedRegion}
-      />,
-    );
+  test('contains exactly 26 regions', () => {
+    setupDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
 
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.getByTestId('btn-for-region-selection')).toHaveTextContent(
-      /Region 5/i,
-    );
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupDropdownWithSelection(1);
+    await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
+      timeout: 1000,
+    });
   });
 
-  test('dropdown opens and highlights the selected region', () => {
-    render(
-      <RegionsList
-        selectedRegion="Region 10"
-        setSelectedRegion={mockSetSelectedRegion}
-      />,
-    );
+  test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
+    setupDropdown();
+    const regions = getAllRegions();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[1]).toHaveFocus();
+    pressKey(regions[1], 'ArrowUp');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'Enter');
+    expect(getDropdownButton()).toHaveTextContent(/Вінниця/i);
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
+  test('clears search term with backspace', async () => {
+    setupDropdown();
+    typeText('в');
+
+    await waitFor(() => {
+      const filteredItems = getAllRegions();
+      expect(filteredItems.length).toBeLessThan(26);
+    });
+
+    typeText('');
 
-    const selectedRegionElement = screen.getByRole('menuitemradio', {
-      name: /Region 10/i,
+    await waitFor(() => {
+      const filteredItems = getAllRegions();
+      expect(filteredItems.length).toBe(26);
     });
-    expect(selectedRegionElement).toHaveClass('focused');
   });
 
-  test('contains exactly 26 regions', () => {
-    render(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+  test('hides all options when no region matches input', async () => {
+    setupDropdown();
+    typeText('zzz');
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+    await waitFor(() => {
+      expect(getAllRegions().length).toBe(26);
+    });
   });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Inconsistency between test name and expectations**

The test name suggests regions should be hidden when no matches are found, but the test expects all 26 regions to still be displayed.

Either:
1. Rename the test to reflect that all regions remain visible when no match is found, or
2. Update the expectation if regions should actually be hidden:

```diff
- expect(getAllRegions().length).toBe(26);
+ expect(getAllRegions().length).toBe(0);
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  test('hides all options when no region matches input', async () => {
    setupDropdown();
    typeText('zzz');

    await waitFor(() => {
      expect(getAllRegions().length).toBe(0);
    });
  });
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-20T21:40:54Z
author_association: NONE
diff_hunk: @@ -1,124 +1,158 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+.wrapper {
+  width: 100%;
+  max-width: 240px;
+  padding: 16px;
+}
+
+.regions-wrapper {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.region-list-title {
+  font-size: 16px;
+  font-weight: 500;
+  color: var(--text-color);
+  margin: 0;
+}
+
+.region-selector {
+  position: relative;
+  width: 100%;
+}
+
+.region-selector-btn {
+  position: relative;
+  height: 50px;
+  margin-top: 12px;
+  padding: 12px;
+  width: 100%;
+  cursor: pointer;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  background-color: var(--white);
+  border: 1px solid var(--pattens-blue);
+  transition: all 0.3s ease-in-out;
+  -webkit-tap-highlight-color: transparent;
+  touch-action: manipulation;
+  margin: 0;
+}
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
user: login: Anton-88
body: good point, I fixed it in the next commit https://github.com/boarlabsxyz/razom/pull/130/commits/8497405f9be1e5adea6b47938cb0a9100df26c77
created_at: 2025-03-20T21:40:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,124 +1,158 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+.wrapper {
+  width: 100%;
+  max-width: 240px;
+  padding: 16px;
+}
+
+.regions-wrapper {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.region-list-title {
+  font-size: 16px;
+  font-weight: 500;
+  color: var(--text-color);
+  margin: 0;
+}
+
+.region-selector {
+  position: relative;
+  width: 100%;
+}
+
+.region-selector-btn {
+  position: relative;
+  height: 50px;
+  margin-top: 12px;
+  padding: 12px;
+  width: 100%;
+  cursor: pointer;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  background-color: var(--white);
+  border: 1px solid var(--pattens-blue);
+  transition: all 0.3s ease-in-out;
+  -webkit-tap-highlight-color: transparent;
+  touch-action: manipulation;
+  margin: 0;
+}
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
user: login: coderabbitai[bot]
body: <details>
<summary>🧩 Analysis chain</summary>

@Anton-88 Great! Thank you for the quick fix. I've verified the commit and it looks good. The CSS margin properties are now properly defined without conflicts.

---

🏁 Script executed:
```
#!/bin/bash
# Let's examine the commit that fixed the margin issue
git show 8497405f9be1e5adea6b47938cb0a9100df26c77 -- 'veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css'
```

Length of output: 131

---

🏁 Script executed:
```
#!/bin/bash
# Let's try a different approach to examine the commit
git log -1 --patch 8497405f9be1e5adea6b47938cb0a9100df26c77 -- veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css

# If that doesn't work, let's get the current content of the file
echo "Current file content:"
cat veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css | grep -A 20 "region-selector-btn"
```

Length of output: 1518

---



</details>

@Anton-88 Perfect! I can confirm that the CSS has been fixed appropriately. The `.region-selector-btn` class now has the correct `margin: 12px 0 0 0` property, resolving the conflict. Thanks for implementing this fix so quickly.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-20T21:41:45Z
author_association: NONE
diff_hunk: @@ -3,116 +3,228 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінниця' },
+    { name: 'Луцьк' },
+    { name: 'Дніпро' },
+    { name: 'Донецьк' },
+    { name: 'Житомир' },
+    { name: 'Ужгород' },
+    { name: 'Запоріжжя' },
+    { name: 'Івано-Франківськ' },
+    { name: 'Київ' },
+    { name: 'Кропивницький' },
+    { name: 'Луганськ' },
+    { name: 'Львів' },
+    { name: 'Миколаїв' },
+    { name: 'Одеса' },
+    { name: 'Полтава' },
+    { name: 'Рівне' },
+    { name: 'Суми' },
+    { name: 'Тернопіль' },
+    { name: 'Харків' },
+    { name: 'Херсон' },
+    { name: 'Хмельницький' },
+    { name: 'Черкаси' },
+    { name: 'Чернівці' },
+    { name: 'Чернігів' },
+    { name: 'Сімферополь' },
+    { name: 'Всі' },
+  ];
+});
+
+const setupRegionsList = () => render(<RegionsList />);
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+const openDropdown = () => fireEvent.click(getDropdownButton());
+const pressKey = (
+  element: HTMLElement,
+  key: string,
+  shiftKey: boolean = false,
+) => fireEvent.keyDown(element, { key, shiftKey });
+const selectRegion = (index: number) => fireEvent.click(getAllRegions()[index]);
+
+const setupDropdown = () => {
+  setupRegionsList();
+  openDropdown();
+};
+
+const setupDropdownWithSelection = (index: number) => {
+  setupDropdown();
+  selectRegion(index);
+  openDropdown();
+};
+
+const typeText = (text: string) => {
+  const input = screen.getByTestId('region-search-input');
+  fireEvent.change(input, { target: { value: text } });
+};
 
 describe('RegionsList Component', () => {
-  let mockSetSelectedRegion: jest.Mock;
+  test('correctly renders and shows default region', () => {
+    setupRegionsList();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-  beforeEach(() => {
-    mockSetSelectedRegion = jest.fn();
+  test('dropdown opens and closes when button is clicked', () => {
+    setupDropdown();
+    expect(getRegionsList()).toBeInTheDocument();
+    fireEvent.click(getDropdownButton());
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
-  test('correctly renders and shows default region', () => {
-    render(
-      <RegionsList
-        selectedRegion="Region 5"
-        setSelectedRegion={mockSetSelectedRegion}
-      />,
-    );
+  test('contains exactly 26 regions', () => {
+    setupDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
 
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.getByTestId('btn-for-region-selection')).toHaveTextContent(
-      /Region 5/i,
-    );
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupDropdownWithSelection(1);
+    await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
+      timeout: 1000,
+    });
   });
 
-  test('dropdown opens and highlights the selected region', () => {
-    render(
-      <RegionsList
-        selectedRegion="Region 10"
-        setSelectedRegion={mockSetSelectedRegion}
-      />,
-    );
+  test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
+    setupDropdown();
+    const regions = getAllRegions();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[1]).toHaveFocus();
+    pressKey(regions[1], 'ArrowUp');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'Enter');
+    expect(getDropdownButton()).toHaveTextContent(/Вінниця/i);
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
+  test('clears search term with backspace', async () => {
+    setupDropdown();
+    typeText('в');
+
+    await waitFor(() => {
+      const filteredItems = getAllRegions();
+      expect(filteredItems.length).toBeLessThan(26);
+    });
+
+    typeText('');
 
-    const selectedRegionElement = screen.getByRole('menuitemradio', {
-      name: /Region 10/i,
+    await waitFor(() => {
+      const filteredItems = getAllRegions();
+      expect(filteredItems.length).toBe(26);
     });
-    expect(selectedRegionElement).toHaveClass('focused');
   });
 
-  test('contains exactly 26 regions', () => {
-    render(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+  test('hides all options when no region matches input', async () => {
+    setupDropdown();
+    typeText('zzz');
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+    await waitFor(() => {
+      expect(getAllRegions().length).toBe(26);
+    });
   });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: Anton-88
body: this test will be changed, thanks
created_at: 2025-03-20T22:06:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,116 +3,228 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
 import '@testing-library/jest-dom';
 import RegionsList from './regionsList';
 
-jest.mock('data/RegionsArray', () =>
-  Array.from({ length: 26 }, (_, i) => ({
-    name: `Region ${i + 1}`,
-    numOfInitiatives: i * 2,
-  })),
-);
+jest.mock('data/RegionsArray', () => {
+  return [
+    { name: 'Вінниця' },
+    { name: 'Луцьк' },
+    { name: 'Дніпро' },
+    { name: 'Донецьк' },
+    { name: 'Житомир' },
+    { name: 'Ужгород' },
+    { name: 'Запоріжжя' },
+    { name: 'Івано-Франківськ' },
+    { name: 'Київ' },
+    { name: 'Кропивницький' },
+    { name: 'Луганськ' },
+    { name: 'Львів' },
+    { name: 'Миколаїв' },
+    { name: 'Одеса' },
+    { name: 'Полтава' },
+    { name: 'Рівне' },
+    { name: 'Суми' },
+    { name: 'Тернопіль' },
+    { name: 'Харків' },
+    { name: 'Херсон' },
+    { name: 'Хмельницький' },
+    { name: 'Черкаси' },
+    { name: 'Чернівці' },
+    { name: 'Чернігів' },
+    { name: 'Сімферополь' },
+    { name: 'Всі' },
+  ];
+});
+
+const setupRegionsList = () => render(<RegionsList />);
+const getRegionsList = () => screen.queryByTestId('list-of-regions');
+const getAllRegions = () => screen.queryAllByRole('menuitemradio');
+const getDropdownButton = () => screen.getByTestId('btn-for-region-selection');
+const openDropdown = () => fireEvent.click(getDropdownButton());
+const pressKey = (
+  element: HTMLElement,
+  key: string,
+  shiftKey: boolean = false,
+) => fireEvent.keyDown(element, { key, shiftKey });
+const selectRegion = (index: number) => fireEvent.click(getAllRegions()[index]);
+
+const setupDropdown = () => {
+  setupRegionsList();
+  openDropdown();
+};
+
+const setupDropdownWithSelection = (index: number) => {
+  setupDropdown();
+  selectRegion(index);
+  openDropdown();
+};
+
+const typeText = (text: string) => {
+  const input = screen.getByTestId('region-search-input');
+  fireEvent.change(input, { target: { value: text } });
+};
 
 describe('RegionsList Component', () => {
-  let mockSetSelectedRegion: jest.Mock;
+  test('correctly renders and shows default region', () => {
+    setupRegionsList();
+    expect(getDropdownButton()).toBeInTheDocument();
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-  beforeEach(() => {
-    mockSetSelectedRegion = jest.fn();
+  test('dropdown opens and closes when button is clicked', () => {
+    setupDropdown();
+    expect(getRegionsList()).toBeInTheDocument();
+    fireEvent.click(getDropdownButton());
+    expect(getRegionsList()).not.toBeInTheDocument();
   });
 
-  test('correctly renders and shows default region', () => {
-    render(
-      <RegionsList
-        selectedRegion="Region 5"
-        setSelectedRegion={mockSetSelectedRegion}
-      />,
-    );
+  test('contains exactly 26 regions', () => {
+    setupDropdown();
+    expect(getAllRegions().length).toBe(26);
+  });
 
-    expect(screen.getByTestId('btn-for-region-selection')).toBeInTheDocument();
-    expect(screen.getByTestId('btn-for-region-selection')).toHaveTextContent(
-      /Region 5/i,
-    );
-    expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
+  test('sets correct focus when reopening dropdown with selected region', async () => {
+    setupDropdownWithSelection(1);
+    await waitFor(() => expect(getAllRegions()[1]).toHaveFocus(), {
+      timeout: 1000,
+    });
   });
 
-  test('dropdown opens and highlights the selected region', () => {
-    render(
-      <RegionsList
-        selectedRegion="Region 10"
-        setSelectedRegion={mockSetSelectedRegion}
-      />,
-    );
+  test('keyboard navigation works (ArrowDown, ArrowUp, Enter, Space)', () => {
+    setupDropdown();
+    const regions = getAllRegions();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'ArrowDown');
+    expect(regions[1]).toHaveFocus();
+    pressKey(regions[1], 'ArrowUp');
+    expect(regions[0]).toHaveFocus();
+    pressKey(regions[0], 'Enter');
+    expect(getDropdownButton()).toHaveTextContent(/Вінниця/i);
+    expect(getRegionsList()).not.toBeInTheDocument();
+  });
 
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
-    expect(screen.getByTestId('list-of-regions')).toBeInTheDocument();
+  test('clears search term with backspace', async () => {
+    setupDropdown();
+    typeText('в');
+
+    await waitFor(() => {
+      const filteredItems = getAllRegions();
+      expect(filteredItems.length).toBeLessThan(26);
+    });
+
+    typeText('');
 
-    const selectedRegionElement = screen.getByRole('menuitemradio', {
-      name: /Region 10/i,
+    await waitFor(() => {
+      const filteredItems = getAllRegions();
+      expect(filteredItems.length).toBe(26);
     });
-    expect(selectedRegionElement).toHaveClass('focused');
   });
 
-  test('contains exactly 26 regions', () => {
-    render(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
-    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+  test('hides all options when no region matches input', async () => {
+    setupDropdown();
+    typeText('zzz');
 
-    const items = screen.getAllByRole('menuitemradio');
-    expect(items.length).toBe(26);
+    await waitFor(() => {
+      expect(getAllRegions().length).toBe(26);
+    });
   });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: @Anton-88 I understand that you'll be addressing this test discrepancy. Let me know if you need any assistance with the implementation.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-20T22:07:01Z
author_association: NONE
diff_hunk: @@ -58,59 +81,111 @@ function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
     [setSelectedRegion, setIsOpen, setFocusedIndex, regions, buttonRef],
   );
 
-  const handleClickOutside = (event: MouseEvent) => {
+  const handleClickOutside = useCallback((e: MouseEvent) => {
     if (
       dropdownRef.current &&
-      !dropdownRef.current.contains(event.target as Node)
+      !dropdownRef.current.contains(e.target as Node)
     ) {
       setIsOpen(false);
+      setInputValue('');
       setFocusedIndex(null);
     }
+  }, []);
+
+  const calculatePreviousTabOrArrowUpIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex <= 0
+      ? length - 1
+      : focusedIndex - 1;
   };
 
-  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
-    if (event.key === 'Escape') {
-      setIsOpen(false);
+  const calculateNextTabOrArrowDownIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex >= length - 1
+      ? 0
+      : focusedIndex + 1;
+  };
+
+  const handleInputChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      setInputValue(e.target.value);
       setFocusedIndex(null);
-      buttonRef.current?.focus();
-    } else if (isOpen) {
-      if (event.key === 'ArrowDown' || event.key === 'Tab') {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === regions.length - 1 ? 0 : prev + 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (
-        event.key === 'ArrowUp' ||
-        (event.shiftKey && event.key === 'Tab')
-      ) {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === 0 ? regions.length - 1 : prev - 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (event.key === 'Enter' || event.key === ' ') {
-        event.preventDefault();
-        if (focusedIndex !== null) {
-          handleRegionSelect(regions[focusedIndex]);
-        }
+    },
+    [],
+  );
+
+  const handleKeyDown = useCallback(
+    (e: React.KeyboardEvent<HTMLDivElement>) => {
+      if (!isOpen) {
+        return;
       }
-    }
-  };
+
+      let newIndex: number;
+
+      switch (e.key) {
+        case 'Tab':
+          e.preventDefault();
+          newIndex = e.shiftKey
+            ? calculatePreviousTabOrArrowUpIndex(
+                focusedIndex,
+                filteredRegions.length,
+              )
+            : calculateNextTabOrArrowDownIndex(
+                focusedIndex,
+                filteredRegions.length,
+              );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowDown':
+          e.preventDefault();
+          newIndex = calculateNextTabOrArrowDownIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowUp':
+          e.preventDefault();
+          newIndex = calculatePreviousTabOrArrowUpIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'Enter':
+        case ' ':
+          e.preventDefault();
+          if (focusedIndex !== null) {
+            handleRegionSelect(filteredRegions[focusedIndex]);
+          }
+          break;
+        case 'Escape':
+          e.preventDefault();
+          setIsOpen(false);
+          setInputValue('');
+          setFocusedIndex(null);
+          break;
+      }
+    },
+    [isOpen, focusedIndex, filteredRegions, handleRegionSelect],
+  );
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Potential accessibility concern with overriding Tab key default.**  
While custom focus management is valuable, blocking the default Tab might impede standard navigation for keyboard users wishing to leave the dropdown. Consider a more nuanced approach to allow typical Tab usage once the user reaches the dropdown boundaries.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-27T20:46:54Z
author_association: NONE
diff_hunk: @@ -58,59 +81,111 @@ function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
     [setSelectedRegion, setIsOpen, setFocusedIndex, regions, buttonRef],
   );
 
-  const handleClickOutside = (event: MouseEvent) => {
+  const handleClickOutside = useCallback((e: MouseEvent) => {
     if (
       dropdownRef.current &&
-      !dropdownRef.current.contains(event.target as Node)
+      !dropdownRef.current.contains(e.target as Node)
     ) {
       setIsOpen(false);
+      setInputValue('');
       setFocusedIndex(null);
     }
+  }, []);
+
+  const calculatePreviousTabOrArrowUpIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex <= 0
+      ? length - 1
+      : focusedIndex - 1;
   };
 
-  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
-    if (event.key === 'Escape') {
-      setIsOpen(false);
+  const calculateNextTabOrArrowDownIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex >= length - 1
+      ? 0
+      : focusedIndex + 1;
+  };
+
+  const handleInputChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      setInputValue(e.target.value);
       setFocusedIndex(null);
-      buttonRef.current?.focus();
-    } else if (isOpen) {
-      if (event.key === 'ArrowDown' || event.key === 'Tab') {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === regions.length - 1 ? 0 : prev + 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (
-        event.key === 'ArrowUp' ||
-        (event.shiftKey && event.key === 'Tab')
-      ) {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === 0 ? regions.length - 1 : prev - 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (event.key === 'Enter' || event.key === ' ') {
-        event.preventDefault();
-        if (focusedIndex !== null) {
-          handleRegionSelect(regions[focusedIndex]);
-        }
+    },
+    [],
+  );
+
+  const handleKeyDown = useCallback(
+    (e: React.KeyboardEvent<HTMLDivElement>) => {
+      if (!isOpen) {
+        return;
       }
-    }
-  };
+
+      let newIndex: number;
+
+      switch (e.key) {
+        case 'Tab':
+          e.preventDefault();
+          newIndex = e.shiftKey
+            ? calculatePreviousTabOrArrowUpIndex(
+                focusedIndex,
+                filteredRegions.length,
+              )
+            : calculateNextTabOrArrowDownIndex(
+                focusedIndex,
+                filteredRegions.length,
+              );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowDown':
+          e.preventDefault();
+          newIndex = calculateNextTabOrArrowDownIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowUp':
+          e.preventDefault();
+          newIndex = calculatePreviousTabOrArrowUpIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'Enter':
+        case ' ':
+          e.preventDefault();
+          if (focusedIndex !== null) {
+            handleRegionSelect(filteredRegions[focusedIndex]);
+          }
+          break;
+        case 'Escape':
+          e.preventDefault();
+          setIsOpen(false);
+          setInputValue('');
+          setFocusedIndex(null);
+          break;
+      }
+    },
+    [isOpen, focusedIndex, filteredRegions, handleRegionSelect],
+  );
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
user: login: Anton-88
body: leave it pls as it is for now, thx
created_at: 2025-03-27T20:54:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -58,59 +81,111 @@ function RegionsList({ selectedRegion, setSelectedRegion }: RegionsListProps) {
     [setSelectedRegion, setIsOpen, setFocusedIndex, regions, buttonRef],
   );
 
-  const handleClickOutside = (event: MouseEvent) => {
+  const handleClickOutside = useCallback((e: MouseEvent) => {
     if (
       dropdownRef.current &&
-      !dropdownRef.current.contains(event.target as Node)
+      !dropdownRef.current.contains(e.target as Node)
     ) {
       setIsOpen(false);
+      setInputValue('');
       setFocusedIndex(null);
     }
+  }, []);
+
+  const calculatePreviousTabOrArrowUpIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex <= 0
+      ? length - 1
+      : focusedIndex - 1;
   };
 
-  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
-    if (event.key === 'Escape') {
-      setIsOpen(false);
+  const calculateNextTabOrArrowDownIndex = (
+    focusedIndex: number | null,
+    length: number,
+  ): number => {
+    return focusedIndex === null || focusedIndex >= length - 1
+      ? 0
+      : focusedIndex + 1;
+  };
+
+  const handleInputChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      setInputValue(e.target.value);
       setFocusedIndex(null);
-      buttonRef.current?.focus();
-    } else if (isOpen) {
-      if (event.key === 'ArrowDown' || event.key === 'Tab') {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === regions.length - 1 ? 0 : prev + 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (
-        event.key === 'ArrowUp' ||
-        (event.shiftKey && event.key === 'Tab')
-      ) {
-        event.preventDefault();
-        setFocusedIndex((prev) => {
-          const nextIndex =
-            prev === null || prev === 0 ? regions.length - 1 : prev - 1;
-          itemsRef.current[nextIndex]?.focus();
-          return nextIndex;
-        });
-      } else if (event.key === 'Enter' || event.key === ' ') {
-        event.preventDefault();
-        if (focusedIndex !== null) {
-          handleRegionSelect(regions[focusedIndex]);
-        }
+    },
+    [],
+  );
+
+  const handleKeyDown = useCallback(
+    (e: React.KeyboardEvent<HTMLDivElement>) => {
+      if (!isOpen) {
+        return;
       }
-    }
-  };
+
+      let newIndex: number;
+
+      switch (e.key) {
+        case 'Tab':
+          e.preventDefault();
+          newIndex = e.shiftKey
+            ? calculatePreviousTabOrArrowUpIndex(
+                focusedIndex,
+                filteredRegions.length,
+              )
+            : calculateNextTabOrArrowDownIndex(
+                focusedIndex,
+                filteredRegions.length,
+              );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowDown':
+          e.preventDefault();
+          newIndex = calculateNextTabOrArrowDownIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'ArrowUp':
+          e.preventDefault();
+          newIndex = calculatePreviousTabOrArrowUpIndex(
+            focusedIndex,
+            filteredRegions.length,
+          );
+          setFocusedIndex(newIndex);
+          itemsRef.current[newIndex]?.focus();
+          break;
+        case 'Enter':
+        case ' ':
+          e.preventDefault();
+          if (focusedIndex !== null) {
+            handleRegionSelect(filteredRegions[focusedIndex]);
+          }
+          break;
+        case 'Escape':
+          e.preventDefault();
+          setIsOpen(false);
+          setInputValue('');
+          setFocusedIndex(null);
+          break;
+      }
+    },
+    [isOpen, focusedIndex, filteredRegions, handleRegionSelect],
+  );
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.tsx
user: login: coderabbitai[bot]
body: @Anton-88 Understood, I'll leave it as is for now. Thanks for letting me know!

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-27T20:55:17Z
author_association: NONE
diff_hunk: @@ -216,4 +216,19 @@ describe('RegionsList Component', () => {
     );
     expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
   });
+
+  test('search input updates inputValue and resets focusedIndex', async () => {
+    renderWithApollo(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
+    await waitForDataLoad();
+
+    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    const searchInput = screen.getByTestId('region-search-input');
+
+    fireEvent.change(searchInput, { target: { value: 'Region 1' } });
+
+    expect(searchInput).toHaveValue('Region 1');
+    expect(
+      screen.getByRole('menuitemradio', { name: 'Select Region 1' }),
+    ).toBeInTheDocument();
+  });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Enhance test coverage for search input filtering**

While this test verifies basic search functionality, it's missing several important aspects:

1. The test name mentions "resets focusedIndex" but there's no assertion checking this behavior
2. It only verifies that a matching region appears, but doesn't confirm that non-matching regions are filtered out
3. It doesn't address the edge cases mentioned in previous reviews


Enhance this test or add additional tests to cover:

```diff
  test('search input updates inputValue and resets focusedIndex', async () => {
    renderWithApollo(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
    await waitForDataLoad();

    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
    const searchInput = screen.getByTestId('region-search-input');

    fireEvent.change(searchInput, { target: { value: 'Region 1' } });

    expect(searchInput).toHaveValue('Region 1');
    expect(
      screen.getByRole('menuitemradio', { name: 'Select Region 1' }),
    ).toBeInTheDocument();
+   // Verify non-matching regions are filtered out
+   const visibleRegions = screen.getAllByRole('menuitemradio');
+   expect(visibleRegions.length).toBe(1);
+   
+   // Verify focusedIndex reset (focused element should be the first visible result)
+   expect(visibleRegions[0]).toHaveClass('focused');
  });
```

Consider adding these additional tests:
1. Test for no matching results (e.g., searching for "XYZ")
2. Test for case-insensitive filtering (e.g., searching for "region" vs "REGION")
3. Test for partial matches (e.g., searching for "Reg")
4. Test keyboard navigation in filtered results

This will ensure robust coverage of the filtering functionality.


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  test('search input updates inputValue and resets focusedIndex', async () => {
    renderWithApollo(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
    await waitForDataLoad();

    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
    const searchInput = screen.getByTestId('region-search-input');

    fireEvent.change(searchInput, { target: { value: 'Region 1' } });

    expect(searchInput).toHaveValue('Region 1');
    expect(
      screen.getByRole('menuitemradio', { name: 'Select Region 1' }),
    ).toBeInTheDocument();
    
    // Verify non-matching regions are filtered out
    const visibleRegions = screen.getAllByRole('menuitemradio');
    expect(visibleRegions.length).toBe(1);
    
    // Verify focusedIndex reset (focused element should be the first visible result)
    expect(visibleRegions[0]).toHaveClass('focused');
  });
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-27T20:57:30Z
author_association: NONE
diff_hunk: @@ -216,4 +216,19 @@ describe('RegionsList Component', () => {
     );
     expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
   });
+
+  test('search input updates inputValue and resets focusedIndex', async () => {
+    renderWithApollo(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
+    await waitForDataLoad();
+
+    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    const searchInput = screen.getByTestId('region-search-input');
+
+    fireEvent.change(searchInput, { target: { value: 'Region 1' } });
+
+    expect(searchInput).toHaveValue('Region 1');
+    expect(
+      screen.getByRole('menuitemradio', { name: 'Select Region 1' }),
+    ).toBeInTheDocument();
+  });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: Anton-88
body: thanks for your suggestion, for now those tests enough, later they will be added!
created_at: 2025-03-27T20:59:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -216,4 +216,19 @@ describe('RegionsList Component', () => {
     );
     expect(screen.queryByTestId('list-of-regions')).not.toBeInTheDocument();
   });
+
+  test('search input updates inputValue and resets focusedIndex', async () => {
+    renderWithApollo(<RegionsList setSelectedRegion={mockSetSelectedRegion} />);
+    await waitForDataLoad();
+
+    fireEvent.click(screen.getByTestId('btn-for-region-selection'));
+    const searchInput = screen.getByTestId('region-search-input');
+
+    fireEvent.change(searchInput, { target: { value: 'Region 1' } });
+
+    expect(searchInput).toHaveValue('Region 1');
+    expect(
+      screen.getByRole('menuitemradio', { name: 'Select Region 1' }),
+    ).toBeInTheDocument();
+  });
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.test.tsx
user: login: coderabbitai[bot]
body: @Anton-88 Understood! Your current test implementation covers the basic functionality, and you can enhance the test coverage later as needed. Thanks for considering the suggestions.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-27T20:59:30Z
author_association: NONE
diff_hunk: @@ -1,128 +1,173 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-  font-weight: 400;
-  font-size: 0.875rem;
-  line-height: 1.625rem;
-  color: var(--haiti);
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+/* <<<<<<< HEAD */
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
user: login: yuramax
body: @Anton-88, please remove this line, it was left after the merge.
created_at: 2025-03-31T10:36:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,128 +1,173 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-  font-weight: 400;
-  font-size: 0.875rem;
-  line-height: 1.625rem;
-  color: var(--haiti);
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+/* <<<<<<< HEAD */
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
user: login: yuramax
body: We agreed to make the correction in the next PR related to [task 124](https://github.com/boarlabsxyz/razom/issues/124)
created_at: 2025-03-31T11:36:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,128 +1,173 @@
-.wrapper {
-  width: 100%;
-  max-width: 240px;
-  padding: 16px;
-}
-
-.regions-wrapper {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-bottom: 12px;
-}
-
-.region-list-title {
-  height: 20px;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 24px;
-}
-
-.region-selector {
-  position: relative;
-  width: 240px;
-  width: 100%;
-}
-
-.region-name {
-  flex-grow: 1;
-  text-align: left;
-  font-weight: 400;
-  font-size: 0.875rem;
-  line-height: 1.625rem;
-  color: var(--haiti);
-}
-
-.num-of-initiatives {
-  flex-shrink: 0;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.region-selector-btn {
-  position: relative;
-  height: 50px;
-  margin-top: 12px;
-  padding: 12px;
-  width: 100%;
-  cursor: pointer;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  background-color: var(--white);
-  border: 1px solid var(--pattens-blue);
-  transition: all 0.3s ease-in-out;
-}
-
-.region-selector-btn:after {
-  content: '';
-  height: 7px;
-  width: 12px;
-  background-image: url('/icons/arrow-down-black.svg');
-  background-size: contain;
-  background-repeat: no-repeat;
-  display: inline-block;
-  transition: transform 0.3s ease-in-out;
-}
-
-.region-selector-btn.open:after {
-  transform: rotate(180deg);
-}
-
-.dropdown-arrow {
-  font-size: 0.8em;
-  color: var(--ebony);
-  margin-left: 5px;
-  transition: transform 0.2s ease-in-out;
-  display: inline-block;
-}
-
-.region-selector-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  position: absolute;
-  top: 100%;
-  left: 0;
-  width: 100%;
-  background-color: var(--white);
-  border: 1px solid var(--very-light-grey);
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-  max-height: 300px;
-  overflow-y: auto;
-  z-index: 1;
-  display: none;
-}
-
-.region-selector-list.show {
-  display: block;
-}
-
-.region-selector-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  max-height: 50px;
-  padding: 12px 12px;
-  cursor: pointer;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 26px;
-  border: 1px solid var(--pattens-blue);
-}
-
-.region-selector-item:hover,
-.region-selector-item:focus {
-  background-color: var(--gum-leaf);
-}
-
-@media (max-width: 480px) {
-  .wrapper {
-    width: calc(100% - 32px);
-    max-width: 100%;
-  }
-
-  .region-selector {
-    width: 100%;
-  }
-}
+/* <<<<<<< HEAD */
path: veterans/components/homePage/mapSection/regionsFilter/regionsList.module.css
user: login: Anton-88
body: thanks for the note, I will fix it in the next task
created_at: 2025-03-31T11:38:45Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-03-19T08:45:14Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

<details>
<summary>📝 Walkthrough</summary>

## Walkthrough
This pull request updates the region filtering functionality in the homepage map section. It refines the styling with enhancements for touch interactions and font rendering, and revises the component logic by removing certain props and improving filtering and keyboard navigation. Additionally, related TypeScript types and tests have been updated, with a changelog entry added to document these modifications.

## Changes
| File(s) | Change Summary |
|---------|----------------|
| `veterans/components/homePage/mapSection/regionsFilter/{regionsList.module.css, regionsList.tsx, types.ts}` | **CSS:** Enhanced touch interaction (added `-webkit-tap-highlight-color` and `touch-action`), refined font styling, added `.region-search-input`, and updated selected state and dropdown styles.<br>**TSX:** Removed `selectedRegion` and `setSelectedRegion` props, introduced `inputValue` for filtering, improved filtering logic with Ukrainian text regex validation, and expanded keyboard navigation.<br>**Types:** Introduced new `RegionsListProps` interface. |
| `veterans/components/homePage/mapSection/MapSection.test.tsx` | Made `selectedRegion` optional, modified the button click handler to use `'Київ'`, and updated expectations to reflect localization changes. |
| `CHANGELOG.md` | Added a version 1.6.0 entry documenting the new keyboard filtering feature and updated class naming conventions. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant User as User
    participant RegionsList as RegionsList Component
    participant Parent as Parent Component

    User->>RegionsList: Type in search input
    RegionsList->>RegionsList: Filter regions based on input (with Ukrainian regex)
    User->>RegionsList: Navigate with Arrow keys / Tab
    RegionsList->>RegionsList: Update highlighted region
    User->>RegionsList: Select region (click or key press)
    alt Callback provided
        RegionsList->>Parent: Call setCurrentRegion(selectedRegion)
    else No callback
        RegionsList->>RegionsList: Update internal state only
    end
```

## Possibly related PRs
- **boarlabsxyz/razom#117:** The changes in the main PR focus on styling updates in the `regionsList.module.css`, which are directly related to the modifications made in the `regionsList.tsx` file.
- **boarlabsxyz/razom#131:** The changes in the main PR are related to the styling of the `.region-name` class in the `regionsList.module.css`, which is also modified in the retrieved PR.

## Suggested reviewers
- IhorMasechko  
- VitalyyP  
- yuramax  

</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpADK2VmgqyjcEj2wAbb5AokAI7Y0riQ4rjedJAARACCtEr0AGbw3jQU8BhE4fjhsJ4BRPD4GMjeSLgxkADuaMiI2ALM6jT0cvme2IiUkHEYBBhgABzD6Bj0qPBKA/Cp0fWQGE4CvQCMAMwADBowBTyZzC7yyfgM3fzJ+ai2KMgEkGSwmAyeuPvJ2BhiJRhoFbh5Pgru9CiRiqUGiQoj9SpBaBR8NxaPgalgOllcIjaNgGFkcj0pFQ/OQapBkiRqNgAohdh4eihvt5sEpxoyMmgflJID0XAxYIzuHhyfg+EVfjzoaJxHCauoBbRZH8WgxyWkMvjxpNmLx8FJ6ABrEiyAT4Fz0P4SeBEai/DRGACSWDQiXUEoeoKWJDJFKpNIANJ1rHYsgxmUpkE8XiQ2AN7nlPVbGv8DtJ2La4cD/ODfimpbHcIhAzUEPzGRJ8N5udhkdRoohuJz8YHAdx8EQqNxYLJA5h6ARcbAwEjxC0AF7RTHKWFlOn7FHnAsZrDPZD/RB5VZkSA12h1/t5ALJGFhT3eOuIMJExC/QCYBMh4DrEVIC2uJtnUuQLWgWtkFBgpFmSF7QMAAxalQQoZhRRIFt9luPVKGeHx7n2GhL0YeppBFPhPQAAxsHNIQAGUqPCFB1Up2EDR9dStP9OXOKgGHkPt2WnGUsH5UQDVpSAHTCdc8hdWhkFJGBZG4Eh7AYTJuDCKcKGSTlsIeJRPzBCEsF1KSKHEbC2KYSjyAGA4kVpdx4LsBhMEgVZ0AYV5EB6ftYERbAiAFT1Tl8VFNQAVRsYiuAAbVgXBcG4RAOAAehi4p3iaDQjJi00XHPAREAAD1kMcYqoMcWBioVfBizYtgAXQACnCyLorihLYCSlK0ooDLsty/K0EK5hip8bwyu2ABKECLEgABhFhXwcJwjlcR0sE9Izpp6GdLiDEq/ACYJQl7HkPNIS8JTqZAjlZDpPW6XoADV1H+WRZCsbMbQoWhNU9S9ZAqP8sw+ykKDLLIhTCOV3iyINxUhSAKkvXZ7CkvFUhs3we0gW7cHux6zLbFz8moIMCmtcL1vwyGylIy8AH0ybAXkAaHIG8HIxBYHwHx2k8HpTzyI5cDLT1Cc8sJfv2PCycQCncGpoihh6E9RTAdQYzwudUGW9hGTemz0PQEVzmQOEyEaTI/yTbAUyYMpKjIFitXQCoiAwAs7JIXAahIbc/r5AVGcE99PSV5gH0W/YycleWKGLUsBSYdnHgwZ5vjefZEOJPwrr4Egst0+Abc8Do6OmTU0EgaCAgUAob25bx8HwA07YpaEQIAOWE11OItqb2ANvg3sQfWbyh93y4wfA2kZDbn2maJ1bjSUZxoiZ4G197nlPD4PdoAROXrk7ocfJWD2uBp8SifaiEOziQP0YxwCgMh6CzNA8EIUhyCocfZ84A5+GEaVJGwh0JgSgqCqHUFoHQN8TBQDgFMN8OACDEDIMoT+XcBhcCoGSRozhXB2XkMA5QYDNDaF0GAQwt9TAGCkByMoMUjJthMoWGKrM2BWDQKQGKRxuD2H/qUfKMtECgXVJQfhWkJaVA0NBHEURkrOQ4AYGIiiDBjTiA6JB799z7RwUCK4/JMCHUsp4PR2RsLg09ONew9g1Rn0xNiXEnMSBEhTFIuYy9lzxiDJ9b6OQsz0KonGOcngVY0zltKBWAhcAYHImGeoYlUSMjDCybCeEwDuwEAadQYAMbcDAAgTyDtwpgCYDXCg5E2J4QHPyMAnJOLkR0pQfSRZ46JzxH+SpPsBgcTtHsIJGgabKhIGU98KtljMGHMkRWGA3S2ikIgaJ55nLYWeNyLcWBdyaIeLRZ8nhTimQCBMSgmpQYChSWkjJuAwC7IuYgaCY8EDZDwoGFJ0ExzDmypc0o1zblgweb2YZNAsoXP2SA/EdTES6UaYEkUpkbwThwpAYJMswADPIquF225jGkBSIiZgCKdjDAAOwAFYAjMHIg8PCawAAs3AsqPLtmeLInhBbEzRas9AtAhDdHHskHFCK1gaAAGwACYSXK1yAi4VgraUqyMHEL0ZIYnOSeX0pFdMqm+3pWyj2zpEh0EDIXN6DEeTiAYAaeQvs1TQnoMcnkCNXGqi8dhU4fBTj6xNReO23BzyvFZt4EB4Qs6aB6Qi1VWlaZSjEArQO8zYlLHiaGcMBkEWhLEHQZmGMaCBkxZqdQMgd4djZu+YpooG6fNqCQImIMChYFTW0KFiLw11vCZEjQSIyCxucpAbV24XHzCPompJutTSvUoGAKgb0Lj1L0qjNAyQKQ/D/Hm9A3ApIuGjLUGt/ApIYAbWG34EaI5gBhrgTtyAe1rNrOPB4RtqSeHUPCJA3q0CyGQEwCgAQxDeHkCWbcLNUS7qMAAeScb4OCaZGCJ0Os0jdiYkDmz8LwNMAxlx20UjUiUIsjEsAYd3Wo8o2aCXSIctphNXVfD3EuPwl4KC4lwHe/g5HvgdwBLIUalg4jEY/r8DxnolAxO41DLMWc2x6WiKWoUAgKiqnYG6aQRgoDjQWWuPVtAuCNoPeqhmGBgbkXBnhahyhaF+MYYgZhLASBsI4VwnhM5RE8aEVx+zJEJFSJ8CQWRcyDCKeUzuK9dB1P7tKIesJFAwARKiRPAzrsjNmZM93czrD2EkE4WgbhvCMDObKI5jIWXxGwzczIhgzk8LeYmr59ZbRAv9J/IMqLhmqDGZw/4phLDLPJdS+luz4scsiPFpLSRih3OedKz5uNlWAuhtGeMyZ0zxCzL01gaLNC4vNdM4l9r1m0u2c4nl3rFA8sDcKx54rXmxtdom2p0NITI0EDCzG+rMXGureMgltrVmUs2Yy3t4RB3+uuaG0VkrZWlPjf81djTwXm1hZPYthFDXMAvdw3GDbH3Os7d+D9pz/2CuA5O8D87yBLvVbVbdltu722Rf0wjprr2UfvY6197rAj9uHYB9I/HXnFExAU5QmnSOWtmYZ1trru2eu/bZ7DQsWV5Hc+URxtRb8UH1lmscdamL5MGA8AinHmhpfkVSGfC9PJrRTKRpgSI8hLsSqjEnIMBEBGS2iWt9gDbCJiMllYcFcz2JKRUt2xY7K+253aPIUlepV5BLrXQd3vwhn0DwlzHhJ4Y8yzBe2vSucmlsQfaPMkjESDyTXAiwiLpSjfuALHlzl4vfmT0OSySHmQ3xdMsb/ZtXsUsBL47siEqHce978cwj4x8FQdUnkZdAyQLyvEpeOskAJAuHgCoKITzfbXX+CELVgedXsjsa8I+Rw/ikB3D0PglqXXWI1H+cWULDfX5yDXYoqpjdbMQkfWSlIaC6zwvfygqexEykP0X0o5l4OlEkIxnoeM8YwheZ+ZRZ19N86s5gUAwhLYMYshkB/IDQqAshl9Fog1AxF8Kg9xx4OgS4igfAXBHhs4aRB5d0Q0Kl2wiAogAARcFFENEA3L4NaY3a3B4GkV2e3RA5kOrX9EOTwBEJETgrAVASnOgECbXI0E0M0V6JYNAK0G0TiaGdsZeAPGQXfETPsaIB4RoVdUUWAmCCib1LOX3DDSEReCAzUROWgbxBFaAFQelPCOID9VEVggDelcpHwxEGofybgciZQ5AS/S0a0W0UjdyTye3P/AIWgKvMoFWRglwqIAAaWNH8K4PJB4O0LbxIGUijRSIlTwDSHgDhQKG8F0kKOY2gMv2RnOHPHEFI08HEiyCUCyjsiwkfgkMgGUNTEWVoF2ASDehY2/T+UFGFHmH9XhS001HFn0PRV1SSD+VcjBAORNh8SuFWLzx3HEAqAnFQiCWSIAJ4yAKoAtTKBoBdBJhTkyGKD+D8DFgEWCJfQyO11Tn+GoyxDowYzYi8WcI0Pzl3xdC5UvBMOEkcimkUHn1BAZA1yaVvT2JgKDD7mfVkGiFWPfRpAYSPiWmpH2TCC00DSgnYz6C43cQlT41EHPEEzKHWhEwsPEz4Ek2k3jgiCzwU2sHBQaXkBvEdj9C6HB3UwCDLwwG/XDmlCuNKAAH4uAaN8QABuOHRSMooJNI/LXAWvKKciQAJMJsxoJ9RyQ+UtT/d+8eNPdvdRsBSM9AQTdRT6Ny5icddKQUQZThTXZk95TUiZYuAqoyYVSsR8QhpIAABePQBffAaYDUieK014bvAfGve0yAE08Pc03lLvZMnUnvdM8yB08CJouEEUv4N08U0gybX/IoiUXUyWKqAAbzlLTUDK0kDCT1uwVKwAAF8uBGzKgDTEAho4cPi0y9dspjSEVPgyysAhzLwWy2y2g0iuy/SeyOyJQBzIBS9vSK9Fz9Tvc9AxyotdcNB9cFElFvNKFxoAAJOIZuAAcQAFFiIgMnzJE1MryecVFFdkEP4VdtF1cx9EBDFIN9FTEBh99PAS5Z8Mt4VrwJQBVBUNAtgJ58J7zHzXz3zPzmBaADc0gm9/Jdigx4hVNqhtZwRRRZ1yQv8GNUAFwnB2ATC157Ya4agicz8PFkj7dddyJuhi5hjjRWpxi+h25cwUZAwKNehPQYhxox9aBKK6wiAaKaIwhR4dZ3h8Z/iEUlVEBm5asykIpMgBA8AllwT1i/Mayj4fIOLdYjRt4BBMIGQXVeZAkGRg8V4oZbcUy+MzhmKUNtCgEoh0ogQ8BvpNRxI5yZx/g5M3x6BUTS4XR70hiawjIVipQsJqTOMOROJeN5xGT118rWTs52TH5OSmhuTZNGl+TW57Y8roCPRCqBM6ThMyqxMKqvApM9Caqs8K1y4zpUrj5H1517Q5cbywAjB+c6EXd6cLM0cmcxcWcJdWxpALzoofz5c+h/yNFx5sE5odEIKTEwKDAZ9vRfdtTUzbThyMzX9oKhsD8ML9hoBG8ZI5IwhDcm9YFg4MgrrB1ICKCvThwfTt0WNsYhSU1Ny0jyJfpG8U1wyHk7YS4j9SCaLS5XZWYE9uyU8tzSh6USwwDwg0AjRi8Jy48eB102AMgSZ4bE9EaiAfiEAGhASxAGMyjqjM1VJ9gj9ktnYsMVy8SZZ8Mfkgw0tvU3Er5zAONaSSrmrJCirmSDYrg2TOrGNurqrZhaqytm4Lr8yOUkh1NDyRzxyZqW9WsFrGdttvtxcnM1raRCxSsJqIApqqEntEdZq6cLaksRcMc+EABZa2mcC80IDamXLav89RZXegA6tXXxUC8CpKsxecOYK4LICsKsasz1eW0uM4euWiKIJcbQgW8myEfbZ3L2kW+5IMdCT6oi+FfCQO0XCm82qFRsKgam3oRPaGtPNYoPRQVxWEl2MGyS7NKDXNQscIeG3M3FemjEgAHx3AOQ0gIr71VOyEVKZvzjwEGAAHI31pN64sjeg+DwcJVkZ3icaAyYaq6gxiCQhIBd7AAsEEAA4QQAdRBAAmEF3sZBhMeKzF3uyNkEkF3omIktKH+NovEjwmAAbEwHr0eELo1mNxEiHuxPPHkHwmjzxqiShRE2lFQ2TreFCBcuTnxm4jNXOP/BoFMhLuwBwO0HIDAC4VRR323H4LyDwbEEftfs/u/swIeMfiuAAaAYkBAZ6RRNAo/BPF1hZjmAUgIKgiyErHbFYnfBrmRhqIIaGNrslHo24GRsWUz2AmlppMaqhhzv4yZLapVo6vHgkyqt6q1r5LKzYQ7qeynqkmsv3HUywbSLDIXqXvUiZVXsIdzrNXWlLuy1+wruRzCBNO7txrSOVJNT2Lh09GgnCazEicEWiesJa3GuvJdumvdtp1iaF0tt9ptpWux0LL11Dul1lyUUjqV0ApjtV1wXjsgtOvOrJB0ZsgZGQdU3pNFkPImjmtPUDQwkaCVihRQf7F2nCHUCiHoBiApMtQm2DmBg31ELtkEMnrdSuloCdF6P9GqCJEHsoZipY3UCOq9npjmJBnlFCZtOrwmdbv4jCFWFeJkDDwfhIxyCWnGdvpRrzuiG7twH9PbJvquYlDYjqGXUv1IJLgeBrhdChR0ZvGYCoJ1hLjDGXnrjhE9DDjrQlDMoilKEDDstRGiHIOOpP0cQ1kJf2DWZ0zwCjn/zvqQLuF0YlV3rSMgDWDEe11iQaWgMtlSCgkxLucBlZbQNFE/UtykelEofEnvtgv9jYsBY/WkCJMyq0lQJjEDBiEhbCH5bWFOe5aQx6FMlCaYoLEUOZoNrdENgTmjEob6b+JP0v3wkPJiZazwXjmNlXnxmlYFBhfAdYxdmWQMkjGzgDM3U9n2EtTVbpfWqMBMdypQSaoTBaqsZKvatEzscqp6pkycc1ygHqv+DMZZIscVusZoMLY5I1scd5OwmHk8CGuesYtToKZ5xvPIWgXjkEYQVfgAs0S/gwTQCwXafkCAUUEITUGIUgTIQMEHeWnUEpmmEQGlitG9DoEpjnz0lIQHbvnQGGBIC2CUC2HnSpWpS2C2GFSpQAE5BUNhBUn2n21hhUBAthBUtgiUPYCUCUqVaAqVhgGBkgn3j3V3T3hgBAGAn2SAv3BVBVXhBVkhhglA1hr2r3hUkPhVsOX2qUBAgOGBiVRVhVoPB3hUCUaPr2CUiOtg1gVAt4XRhhkgCUGANglANgBBhg0ANgSBX2IPBVhhhUEOqPT2GO/3khiOf3kg1gFPaANhuORUSBP2qUiUGBhUKQKRlPhVhgn3z3hhBUiVJOIBIBhUCPMOt41g1g4OtgBBhVQOdPIOGBf2SBiOn2MPuPtO0A4OAOf3zOoA0A0AQP0OGBaAGAiUVJt40BqV/OiVaBX3hU0An2iVROtggOmOH2BOoOoFT2qU33kvX3aB/2n3HPaAiV7OkOCVf3+Otgn2wuqUGAiutPtgv3WQCuLOMvxOiUsuiUNgmun26ujOSApVkuyuNhRUUO8PRBaAn2NgCV/PkhVRuuoBBO0BiUwPiVaPBUFuVuP3POCUBBpuGBhglvuOMPlIYu6AzP1vIBhhn3gP/3IPVg1gSAYulA0BBUBAqUGONhwOf20vsPL3kgpUyOCVgvIAtg4ORU+O+ONgiV50BAtPL21gCVCUhPhgtPkehuYvBUEv4vnKHuhuL3Uvpu0ArOBAyisvTPkg9wrPRV0uBA73Mu/vBU51oeX2tgIPaBlIMP/vzvau4PaAMfBU6BNgCUlPIPb2CUNhtP7uV3B3pugO1g/2nvv3n2n3GeMe/uqUqUPPf2CUxfkgAOSACU1gIOxgHugO0eTf4vlv1fHP/PqUiViONhkgtg0uJeGOiU+POfZOIPoeNg7PlOafTP2OP2TvVuWuDOmPRBiOTeXet5khROTulfDBB3FuBAxfWvCeRvr3hUn34OCOquiVaPf2NgDfMfBUhe/2X2bflfYOVBNg8vG4X3OeRU0u/PVvRAkvaBlviUdeOPYf6AHv7OUPPft4mvzvDeVO6+DOovpf+uSA33P3dunuDe0voOYOLP12pYt2d3c53ZaBKYH5j2gA=== -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=boarlabsxyz/razom&utm_content=130):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: VitalyyP
created_at: 2025-03-26T07:41:32Z
body: Maybe height of regionsList_region-search-input set as the same as height of there gionsList_region-selector-item
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-03-27T20:57:37Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=boarlabsxyz_razom&pullRequest=130) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=boarlabsxyz_razom&pullRequest=130&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=boarlabsxyz_razom&pullRequest=130&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=boarlabsxyz_razom&pullRequest=130&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [83.1% Coverage on New Code](https://sonarcloud.io/component_measures?id=boarlabsxyz_razom&pullRequest=130&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=boarlabsxyz_razom&pullRequest=130&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=boarlabsxyz_razom&pullRequest=130)


author_association: NONE