From 485431ca18dd821d5cb404a5539cb5a010e94937 Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Mon, 27 Jul 2026 18:33:38 +0530 Subject: [PATCH 1/9] fix: enhance category selection for ios devices --- .../ResourceDefinitionCategoryPicker.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index 2bc5a17e050..74a2f9ca9e9 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -583,6 +583,12 @@ export function ResourceDefinitionCategoryPicker({ onSelect={() => handleCategorySelect(category.slug, category.title) } + onPointerUp={(e) => { + if (e.pointerType !== "mouse") { + e.preventDefault(); + handleCategorySelect(category.slug, category.title); + } + }} className="flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 border-b border-gray-200" >
@@ -610,6 +616,12 @@ export function ResourceDefinitionCategoryPicker({ key={category.id} value={category.title} onSelect={() => handleCategorySelect(category.slug, category.title)} + onPointerUp={(e) => { + if (e.pointerType !== "mouse") { + e.preventDefault(); + handleCategorySelect(category.slug, category.title); + } + }} className="flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 border-b border-gray-200" >
@@ -640,6 +652,14 @@ export function ResourceDefinitionCategoryPicker({ key={definition.id} value={`${definition.title}-${definition.id}`} onSelect={() => handleDefinitionSelect(definition)} + onPointerUp={(e) => { + if (e.pointerType !== "mouse") { + // Ignore taps on the favorite toggle button + if ((e.target as HTMLElement).closest("button")) return; + e.preventDefault(); + handleDefinitionSelect(definition); + } + }} className={cn( "flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 border-b border-gray-200 last:border-b-0", searchQuery && definition.category && "py-1", From 8351b0d308d861d0d303f419fd8c68b0df839921 Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Tue, 28 Jul 2026 13:38:12 +0530 Subject: [PATCH 2/9] fix: prevent double selection in category picker --- .../ResourceDefinitionCategoryPicker.tsx | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index 74a2f9ca9e9..86c1973ee6b 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -12,7 +12,7 @@ import { Star, X, } from "lucide-react"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { Badge } from "@/components/ui/badge"; @@ -159,6 +159,8 @@ export function ResourceDefinitionCategoryPicker({ ); const [searchQuery, setSearchQuery] = useState(""); const [breadcrumbsExpanded, setBreadcrumbsExpanded] = useState(false); + // Set on touch/pen pointerup to avoid double selection from the following onSelect. + const pointerSelectedRef = useRef(false); // Sync open state with defaultOpen prop for controlled auto-open behavior useEffect(() => { @@ -580,12 +582,16 @@ export function ResourceDefinitionCategoryPicker({ - handleCategorySelect(category.slug, category.title) - } + onSelect={() => { + if (pointerSelectedRef.current) { + pointerSelectedRef.current = false; + return; + } + handleCategorySelect(category.slug, category.title); + }} onPointerUp={(e) => { if (e.pointerType !== "mouse") { - e.preventDefault(); + pointerSelectedRef.current = true; handleCategorySelect(category.slug, category.title); } }} @@ -615,10 +621,16 @@ export function ResourceDefinitionCategoryPicker({ handleCategorySelect(category.slug, category.title)} + onSelect={() => { + if (pointerSelectedRef.current) { + pointerSelectedRef.current = false; + return; + } + handleCategorySelect(category.slug, category.title); + }} onPointerUp={(e) => { if (e.pointerType !== "mouse") { - e.preventDefault(); + pointerSelectedRef.current = true; handleCategorySelect(category.slug, category.title); } }} @@ -651,12 +663,19 @@ export function ResourceDefinitionCategoryPicker({ handleDefinitionSelect(definition)} + onSelect={() => { + if (pointerSelectedRef.current) { + pointerSelectedRef.current = false; + return; + } + handleDefinitionSelect(definition); + }} onPointerUp={(e) => { if (e.pointerType !== "mouse") { // Ignore taps on the favorite toggle button - if ((e.target as HTMLElement).closest("button")) return; - e.preventDefault(); + if (e.target instanceof Element && e.target.closest("button")) + return; + pointerSelectedRef.current = true; handleDefinitionSelect(definition); } }} From c3a3c2eb420700ae4dfb1b92987ff1989a863b7d Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Tue, 28 Jul 2026 14:35:28 +0530 Subject: [PATCH 3/9] fix: prevent drag on category picker items for better usability --- src/components/Common/ResourceDefinitionCategoryPicker.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index 86c1973ee6b..5319a440f69 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -727,6 +727,7 @@ export function ResourceDefinitionCategoryPicker({ const renderRecentItems = () => (
({ const renderFavoriteItems = () => (
({ {renderSearchInput()} {renderBreadcrumbs()} {renderEmptyState()} From ef5fa1b4701c4e2cbd7f9c87c0130fd6d1aff8b8 Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Tue, 28 Jul 2026 18:42:32 +0530 Subject: [PATCH 4/9] fix: improve touch handling and keyboard dismissal in category picker for better mobile experience --- .../ResourceDefinitionCategoryPicker.tsx | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index 5319a440f69..862904af4dd 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -161,6 +161,24 @@ export function ResourceDefinitionCategoryPicker({ const [breadcrumbsExpanded, setBreadcrumbsExpanded] = useState(false); // Set on touch/pen pointerup to avoid double selection from the following onSelect. const pointerSelectedRef = useRef(false); + // Records where a touch/pen press started so a moved pointer (scroll) is not + // treated as a tap on pointerup. + const pointerStartRef = useRef<{ x: number; y: number } | null>(null); + + const handleItemPointerDown = (e: React.PointerEvent) => { + pointerStartRef.current = + e.pointerType === "mouse" ? null : { x: e.clientX, y: e.clientY }; + }; + + // True only for a touch/pen release that stayed within the tap threshold. + const isPointerTap = (e: React.PointerEvent) => { + const start = pointerStartRef.current; + pointerStartRef.current = null; + if (!start) return false; + return ( + Math.abs(e.clientX - start.x) <= 10 && Math.abs(e.clientY - start.y) <= 10 + ); + }; // Sync open state with defaultOpen prop for controlled auto-open behavior useEffect(() => { @@ -310,6 +328,17 @@ export function ResourceDefinitionCategoryPicker({ // Reset search when navigating const resetSearch = () => setSearchQuery(""); + // On mobile, blur the focused search input when the list is scrolled. While it + // stays focused, vaul re-sizes the drawer to the keyboard on every + // visualViewport event fired during scroll, which shows up as a blink. + const dismissKeyboardOnScroll = () => { + if (!isMobile) return; + const active = document.activeElement; + if (active instanceof HTMLElement && active.tagName === "INPUT") { + active.blur(); + } + }; + const handleCategorySelect = ( categorySlug: string, categoryTitle: string, @@ -362,6 +391,11 @@ export function ResourceDefinitionCategoryPicker({ } } else { onValueChange(definition as T); + // Blur the focused search input first so the mobile keyboard dismisses + // cleanly instead of the page scrolling to the input as the drawer closes. + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } setOpen(false); resetSearch(); } @@ -589,8 +623,9 @@ export function ResourceDefinitionCategoryPicker({ } handleCategorySelect(category.slug, category.title); }} + onPointerDown={handleItemPointerDown} onPointerUp={(e) => { - if (e.pointerType !== "mouse") { + if (isPointerTap(e)) { pointerSelectedRef.current = true; handleCategorySelect(category.slug, category.title); } @@ -628,8 +663,9 @@ export function ResourceDefinitionCategoryPicker({ } handleCategorySelect(category.slug, category.title); }} + onPointerDown={handleItemPointerDown} onPointerUp={(e) => { - if (e.pointerType !== "mouse") { + if (isPointerTap(e)) { pointerSelectedRef.current = true; handleCategorySelect(category.slug, category.title); } @@ -670,11 +706,11 @@ export function ResourceDefinitionCategoryPicker({ } handleDefinitionSelect(definition); }} + onPointerDown={handleItemPointerDown} onPointerUp={(e) => { - if (e.pointerType !== "mouse") { - // Ignore taps on the favorite toggle button - if (e.target instanceof Element && e.target.closest("button")) - return; + // Ignore taps on the favorite toggle button + if (e.target instanceof Element && e.target.closest("button")) return; + if (isPointerTap(e)) { pointerSelectedRef.current = true; handleDefinitionSelect(definition); } @@ -818,6 +854,7 @@ export function ResourceDefinitionCategoryPicker({ {renderBreadcrumbs()} {renderEmptyState()} From 8ef20712eef7ba91b536d1bbaf56b1ec28774bd6 Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Tue, 28 Jul 2026 19:26:32 +0530 Subject: [PATCH 5/9] fix: simplify category picker touch handling for improved mobile usability --- .../ResourceDefinitionCategoryPicker.tsx | 93 ++----------------- 1 file changed, 9 insertions(+), 84 deletions(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index 862904af4dd..b3155b53c8d 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -12,7 +12,7 @@ import { Star, X, } from "lucide-react"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Badge } from "@/components/ui/badge"; @@ -50,6 +50,7 @@ import resourceCategoryApi from "@/types/base/resourceCategory/resourceCategoryA import { ProductKnowledgeType } from "@/types/inventory/productKnowledge/productKnowledge"; import mutate from "@/Utils/request/mutate"; import query from "@/Utils/request/query"; +import { isIOSDevice } from "@/Utils/utils"; interface CategoryBreadcrumb { slug: string; @@ -159,26 +160,6 @@ export function ResourceDefinitionCategoryPicker({ ); const [searchQuery, setSearchQuery] = useState(""); const [breadcrumbsExpanded, setBreadcrumbsExpanded] = useState(false); - // Set on touch/pen pointerup to avoid double selection from the following onSelect. - const pointerSelectedRef = useRef(false); - // Records where a touch/pen press started so a moved pointer (scroll) is not - // treated as a tap on pointerup. - const pointerStartRef = useRef<{ x: number; y: number } | null>(null); - - const handleItemPointerDown = (e: React.PointerEvent) => { - pointerStartRef.current = - e.pointerType === "mouse" ? null : { x: e.clientX, y: e.clientY }; - }; - - // True only for a touch/pen release that stayed within the tap threshold. - const isPointerTap = (e: React.PointerEvent) => { - const start = pointerStartRef.current; - pointerStartRef.current = null; - if (!start) return false; - return ( - Math.abs(e.clientX - start.x) <= 10 && Math.abs(e.clientY - start.y) <= 10 - ); - }; // Sync open state with defaultOpen prop for controlled auto-open behavior useEffect(() => { @@ -328,17 +309,6 @@ export function ResourceDefinitionCategoryPicker({ // Reset search when navigating const resetSearch = () => setSearchQuery(""); - // On mobile, blur the focused search input when the list is scrolled. While it - // stays focused, vaul re-sizes the drawer to the keyboard on every - // visualViewport event fired during scroll, which shows up as a blink. - const dismissKeyboardOnScroll = () => { - if (!isMobile) return; - const active = document.activeElement; - if (active instanceof HTMLElement && active.tagName === "INPUT") { - active.blur(); - } - }; - const handleCategorySelect = ( categorySlug: string, categoryTitle: string, @@ -391,11 +361,6 @@ export function ResourceDefinitionCategoryPicker({ } } else { onValueChange(definition as T); - // Blur the focused search input first so the mobile keyboard dismisses - // cleanly instead of the page scrolling to the input as the drawer closes. - if (document.activeElement instanceof HTMLElement) { - document.activeElement.blur(); - } setOpen(false); resetSearch(); } @@ -503,7 +468,7 @@ export function ResourceDefinitionCategoryPicker({ value={searchQuery} onValueChange={setSearchQuery} className="h-9 border-0 focus:ring-0 text-base sm:text-sm" - autoFocus + autoFocus={!isIOSDevice} />
); @@ -616,20 +581,9 @@ export function ResourceDefinitionCategoryPicker({ { - if (pointerSelectedRef.current) { - pointerSelectedRef.current = false; - return; - } - handleCategorySelect(category.slug, category.title); - }} - onPointerDown={handleItemPointerDown} - onPointerUp={(e) => { - if (isPointerTap(e)) { - pointerSelectedRef.current = true; - handleCategorySelect(category.slug, category.title); - } - }} + onSelect={() => + handleCategorySelect(category.slug, category.title) + } className="flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 border-b border-gray-200" >
@@ -656,20 +610,7 @@ export function ResourceDefinitionCategoryPicker({ { - if (pointerSelectedRef.current) { - pointerSelectedRef.current = false; - return; - } - handleCategorySelect(category.slug, category.title); - }} - onPointerDown={handleItemPointerDown} - onPointerUp={(e) => { - if (isPointerTap(e)) { - pointerSelectedRef.current = true; - handleCategorySelect(category.slug, category.title); - } - }} + onSelect={() => handleCategorySelect(category.slug, category.title)} className="flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 border-b border-gray-200" >
@@ -699,22 +640,7 @@ export function ResourceDefinitionCategoryPicker({ { - if (pointerSelectedRef.current) { - pointerSelectedRef.current = false; - return; - } - handleDefinitionSelect(definition); - }} - onPointerDown={handleItemPointerDown} - onPointerUp={(e) => { - // Ignore taps on the favorite toggle button - if (e.target instanceof Element && e.target.closest("button")) return; - if (isPointerTap(e)) { - pointerSelectedRef.current = true; - handleDefinitionSelect(definition); - } - }} + onSelect={() => handleDefinitionSelect(definition)} className={cn( "flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 border-b border-gray-200 last:border-b-0", searchQuery && definition.category && "py-1", @@ -854,7 +780,6 @@ export function ResourceDefinitionCategoryPicker({ {renderBreadcrumbs()} {renderEmptyState()} @@ -967,7 +892,7 @@ export function ResourceDefinitionCategoryPicker({
- + {renderMainContent()} From 4094dff6920feb7d65ce50a1d342ce59089e024b Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Tue, 28 Jul 2026 19:29:31 +0530 Subject: [PATCH 6/9] fix: remove drag prevention attributes from category picker components for improved usability --- src/components/Common/ResourceDefinitionCategoryPicker.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index b3155b53c8d..f1ae05d5374 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -689,7 +689,6 @@ export function ResourceDefinitionCategoryPicker({ const renderRecentItems = () => (
({ const renderFavoriteItems = () => (
({ {renderSearchInput()} {renderBreadcrumbs()} {renderEmptyState()} From 3bd016e0a71668ad3887c9b00094325f87459054 Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Tue, 28 Jul 2026 20:05:31 +0530 Subject: [PATCH 7/9] fix: add autoFocus prop to TabsContent for improved accessibility on iOS devices --- src/components/Common/ResourceDefinitionCategoryPicker.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index f1ae05d5374..0cbb6ed9e9b 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -889,7 +889,11 @@ export function ResourceDefinitionCategoryPicker({
- + {renderMainContent()} From 4a47370aa275aebb8ba731378d7aa70de925378f Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Wed, 29 Jul 2026 16:56:18 +0530 Subject: [PATCH 8/9] fix: enable autoFocus and adjust repositioning for iOS in ResourceDefinitionCategoryPicker --- .../Common/ResourceDefinitionCategoryPicker.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index 0cbb6ed9e9b..e0147e79dff 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -468,7 +468,7 @@ export function ResourceDefinitionCategoryPicker({ value={searchQuery} onValueChange={setSearchQuery} className="h-9 border-0 focus:ring-0 text-base sm:text-sm" - autoFocus={!isIOSDevice} + autoFocus />
); @@ -794,6 +794,10 @@ export function ResourceDefinitionCategoryPicker({ {isMobile ? ( { setOpen(newOpen); resetSearch(); @@ -889,11 +893,7 @@ export function ResourceDefinitionCategoryPicker({
- + {renderMainContent()} From 0202f81f8f78c178018ce99b2f7a082e51484c8e Mon Sep 17 00:00:00 2001 From: Muhammed Navas Date: Wed, 29 Jul 2026 17:56:42 +0530 Subject: [PATCH 9/9] fix: disable repositioning of inputs in Drawer for improved category selection on iOS --- src/components/Common/ResourceDefinitionCategoryPicker.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/Common/ResourceDefinitionCategoryPicker.tsx b/src/components/Common/ResourceDefinitionCategoryPicker.tsx index e0147e79dff..181433837f4 100644 --- a/src/components/Common/ResourceDefinitionCategoryPicker.tsx +++ b/src/components/Common/ResourceDefinitionCategoryPicker.tsx @@ -50,7 +50,6 @@ import resourceCategoryApi from "@/types/base/resourceCategory/resourceCategoryA import { ProductKnowledgeType } from "@/types/inventory/productKnowledge/productKnowledge"; import mutate from "@/Utils/request/mutate"; import query from "@/Utils/request/query"; -import { isIOSDevice } from "@/Utils/utils"; interface CategoryBreadcrumb { slug: string; @@ -794,10 +793,7 @@ export function ResourceDefinitionCategoryPicker({ {isMobile ? ( { setOpen(newOpen); resetSearch();