From 6e4148f8a0b9d45855ad21fa3fc9faef6543df2e Mon Sep 17 00:00:00 2001 From: Niranjan Kumar Date: Thu, 15 Oct 2026 14:37:20 +0530 Subject: [PATCH 1/5] G2P-5805 fix: improve responsiveness of homepage, register, change request, version history pages, and related components --- ui/staff-ui/src/app/[locale]/page.tsx | 14 +- .../[type]/[id]/change-request/page.tsx | 12 +- .../[type]/[id]/version-history/page.tsx | 16 +-- .../src/app/[locale]/register/[type]/page.tsx | 2 +- ui/staff-ui/src/commons/globals.css | 1 + ui/staff-ui/src/components/layout/Header.tsx | 12 +- .../src/components/layout/ProfileDropdown.tsx | 8 +- .../src/components/shared/BreadcrumbBar.tsx | 33 ++--- .../src/components/shared/CapsuleDropdown.tsx | 22 ++-- .../src/components/shared/PaginationBar.tsx | 22 ++-- .../src/components/shared/TabsLayout.tsx | 48 ++++--- ui/staff-ui/src/components/shared/ViewAll.tsx | 4 +- .../shared/entity-list/CompactCard.tsx | 120 ++++++++++-------- .../entity-list/CompactCardSkeleton.tsx | 37 +++--- .../shared/entity-list/EntityListPage.tsx | 14 +- .../shared/entity-list/MoreMenu.tsx | 4 +- .../shared/entity-list/StackedCard.tsx | 13 +- .../entity-list/StackedCardSkeleton.tsx | 14 +- ui/staff-ui/src/components/ui/KeyValue.tsx | 4 +- ui/staff-ui/src/components/ui/SearchBar.tsx | 13 +- .../src/components/ui/SearchBarDropdown.tsx | 10 +- ui/staff-ui/src/components/ui/StatsCard.tsx | 20 +-- .../src/components/ui/StatsCardsCarousel.tsx | 35 +++-- .../approval/components/ApprovalCard.tsx | 2 +- .../components/ChangeRequestValuesTabs.tsx | 2 +- .../components/DeduplicationCard.tsx | 49 +++++-- .../components/RegisterChangeRequestCard.tsx | 42 +++--- .../register/components/ExportQueuePanel.tsx | 4 +- .../components/ExportRecordsModal.tsx | 6 +- .../filter/components/FilterDropdown.tsx | 11 +- .../filter/components/SelectedFilters.tsx | 21 +-- .../RegisterDetailsPageSkeleton.tsx | 42 +++--- .../components/VersionHistoryCard.tsx | 42 +++--- .../components/VersionHistoryPageSkeleton.tsx | 40 +++--- .../shared/components/DocumentsPopup.tsx | 6 +- .../components/VpVerificationModal.tsx | 6 +- 36 files changed, 416 insertions(+), 335 deletions(-) diff --git a/ui/staff-ui/src/app/[locale]/page.tsx b/ui/staff-ui/src/app/[locale]/page.tsx index a54986b7..ffac25b5 100644 --- a/ui/staff-ui/src/app/[locale]/page.tsx +++ b/ui/staff-ui/src/app/[locale]/page.tsx @@ -174,9 +174,9 @@ export default function Home() { const useStatsCarousel = STATS_CARDS.length > 4; return ( -
+
-
+
{/* stats cards */} {useStatsCarousel ? ( @@ -209,19 +209,21 @@ export default function Home() { action={activeStatsCard === 'tasks' ? undefined : viewAction} anyOf={activeStatsCard === 'tasks' ? taskSearchAnyOf : undefined} fallback={ -
-
+
+
{ }} + textClass="text-base sm:text-[20px]" + iconClassName="h-4 w-4 sm:h-5 sm:w-5 lg:h-6 lg:w-6" />
} > -
+
{(activeStatsCard === 'registers' || activeStatsCard === 'form-submissions') && registerList?.length > 0 && ( @@ -252,6 +254,8 @@ export default function Home() { placeholder={searchPlaceholders[activeStatsCard]} category={selectedRegister} onSearch={handleSearch} + textClass="text-base sm:text-[20px]" + iconClassName="h-4 w-4 sm:h-5 sm:w-5 lg:h-6 lg:w-6" />
diff --git a/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx b/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx index 9ef878cb..ac688a9f 100644 --- a/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx +++ b/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx @@ -74,18 +74,18 @@ export default function ChangeRequestPage() { // Right side of TabsLayout-- Pending request + pagination const pendingRequestsCount = pendingData?.number_of_pending_change_requests ?? 0; const rightContent = !loading && ( -
+
{pendingRequestsCount !== undefined && ( -
- +
+ {t('pending_requests')} - + {pendingRequestsCount.toString().padStart(2, '0')}
)} -
+
{loading ? ( <> - {(tabs.length === 0 &&
+ {(tabs.length === 0 &&
{[1, 2, 3].map(i => (
) : ( -
-
+
+
{hasVersionHistory && ( -
-
+
+
v.value === selectedVersionId)?.label} onChange={onVersionSelect} key={`${selectedDate}-${selectedSectionId}`} - maxWidth='w-20' + maxWidth="sm:w-20" />
-
- {t("total_versions")} {versionHistory.number_of_versions} +
+ {t("total_versions")} {versionHistory.number_of_versions}
@@ -407,7 +407,7 @@ export default function VersionHistoryPage() {
{hasVersionHistory && ( -
+
{!!aweRequestId && loadingTasks ? ( ) : ( diff --git a/ui/staff-ui/src/app/[locale]/register/[type]/page.tsx b/ui/staff-ui/src/app/[locale]/register/[type]/page.tsx index 40ef0d99..b3ff3e15 100644 --- a/ui/staff-ui/src/app/[locale]/register/[type]/page.tsx +++ b/ui/staff-ui/src/app/[locale]/register/[type]/page.tsx @@ -171,7 +171,7 @@ export default function RegisterTypePage() { {viewQueueLabel}
, - { autoClose: 8000, style: { width: '28rem', minWidth: '28rem' } }, + { autoClose: 8000, style: { width: 'min(28rem, calc(100vw - 2rem))' } }, ); }; diff --git a/ui/staff-ui/src/commons/globals.css b/ui/staff-ui/src/commons/globals.css index 65e51307..644a7b16 100644 --- a/ui/staff-ui/src/commons/globals.css +++ b/ui/staff-ui/src/commons/globals.css @@ -1,6 +1,7 @@ @import "tailwindcss"; @config "../../tailwind.config.mjs"; @source "../../node_modules/@openg2p/registry-widgets/dist"; +@source "../../../ui-widgets/dist"; @source "../../node_modules/@openg2p/notification/dist"; @layer base { diff --git a/ui/staff-ui/src/components/layout/Header.tsx b/ui/staff-ui/src/components/layout/Header.tsx index 77a2d053..201cee49 100644 --- a/ui/staff-ui/src/components/layout/Header.tsx +++ b/ui/staff-ui/src/components/layout/Header.tsx @@ -28,14 +28,14 @@ export default function Header() { return (
-
- +
+ {isHorizontalLogo ? ( // eslint-disable-next-line @next/next/no-img-element Registry Logo ) : ( Registry Logo )} {!isHorizontalLogo && ( -
+
{config?.registryName ? t(config?.registryName) : t('registryGen2')} diff --git a/ui/staff-ui/src/components/layout/ProfileDropdown.tsx b/ui/staff-ui/src/components/layout/ProfileDropdown.tsx index 771ebee0..ee667579 100644 --- a/ui/staff-ui/src/components/layout/ProfileDropdown.tsx +++ b/ui/staff-ui/src/components/layout/ProfileDropdown.tsx @@ -31,14 +31,14 @@ export default function ProfileDropdown() {
diff --git a/ui/staff-ui/src/components/shared/TabsLayout.tsx b/ui/staff-ui/src/components/shared/TabsLayout.tsx index f75a572f..d52e946b 100644 --- a/ui/staff-ui/src/components/shared/TabsLayout.tsx +++ b/ui/staff-ui/src/components/shared/TabsLayout.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ReactNode, useEffect, useRef, useState } from "react"; +import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from "react"; import { ChevronDown } from "lucide-react"; import { BreadcrumbBar } from "@/components/shared"; import { TabsResponse } from "@/features/shared/types"; @@ -26,16 +26,32 @@ export default function TabsLayout({ const t = useTranslations(); const [isMoreOpen, setIsMoreOpen] = useState(false); const moreMenuRef = useRef(null); - - const MAX_VISIBLE_TABS = 5; + const [maxVisibleTabs, setMaxVisibleTabs] = useState(5); + + useLayoutEffect(() => { + const compact = window.matchMedia("(max-width: 374px)"); + const wide = window.matchMedia("(min-width: 640px)"); + const update = () => { + if (wide.matches) setMaxVisibleTabs(5); + else if (compact.matches) setMaxVisibleTabs(1); + else setMaxVisibleTabs(2); + }; + update(); + compact.addEventListener("change", update); + wide.addEventListener("change", update); + return () => { + compact.removeEventListener("change", update); + wide.removeEventListener("change", update); + }; + }, []); const allTabs = tabs?.tabs ?? []; - const visibleTabs = allTabs.slice(0, MAX_VISIBLE_TABS); - const moreTabs = allTabs.slice(MAX_VISIBLE_TABS); + const visibleTabs = allTabs.slice(0, maxVisibleTabs); + const moreTabs = allTabs.slice(maxVisibleTabs); const hasMoreTabs = moreTabs.length > 0; const isMoreActive = - hasMoreTabs && activeTab !== undefined && activeTab >= MAX_VISIBLE_TABS; + hasMoreTabs && activeTab !== undefined && activeTab >= maxVisibleTabs; useEffect(() => { if (!isMoreOpen) return; @@ -63,21 +79,21 @@ export default function TabsLayout({ const activeMoreTab = hasMoreTabs && activeTab !== undefined && - activeTab >= MAX_VISIBLE_TABS && + activeTab >= maxVisibleTabs && activeTab < allTabs.length ? allTabs[activeTab] : undefined; return (
-
+
-
+
{tabs && activeTab !== undefined && onTabChange && ( -
-
+
+
{visibleTabs.map((tab, index) => { const tabIndex = index; const isActive = activeTab === tabIndex; @@ -86,7 +102,7 @@ export default function TabsLayout({ {kebabOpen && ( diff --git a/ui/staff-ui/src/components/shared/entity-list/StackedCard.tsx b/ui/staff-ui/src/components/shared/entity-list/StackedCard.tsx index c31f982c..9a8db5b7 100644 --- a/ui/staff-ui/src/components/shared/entity-list/StackedCard.tsx +++ b/ui/staff-ui/src/components/shared/entity-list/StackedCard.tsx @@ -39,7 +39,7 @@ export default function StackedCard({ const heading = title?.trim() || '—'; return ( -
+
{selectable ? (
-
+
{columns.map((column, index) => ( -
+
0 ? 'border-l-2 border-secondary-second pl-6' : '' + index % 2 === 1 ? 'sm:border-l-2 sm:border-secondary-second sm:pl-6' : '' + } ${ + index > 0 ? 'xl:border-l-2 xl:border-secondary-second xl:pl-6' : 'xl:border-l-0 xl:pl-0' }`} > {column.content ?? @@ -92,7 +94,7 @@ export default function StackedCard({ type="button" disabled={viewDetailsDisabled || !onViewDetails} onClick={() => onViewDetails?.()} - className="flex items-center gap-2 text-[14px] font-normal text-neutral-first opacity-60 transition hover:opacity-100 disabled:cursor-default disabled:opacity-40 disabled:hover:opacity-40" + className="flex items-center gap-2 whitespace-nowrap text-[14px] font-normal text-neutral-first opacity-60 transition hover:opacity-100 disabled:cursor-default disabled:opacity-40 disabled:hover:opacity-40" > {t.has('view_details') ? t('view_details') : 'View details'}
diff --git a/ui/staff-ui/src/components/shared/entity-list/StackedCardSkeleton.tsx b/ui/staff-ui/src/components/shared/entity-list/StackedCardSkeleton.tsx index b9561ab4..2dbd877e 100644 --- a/ui/staff-ui/src/components/shared/entity-list/StackedCardSkeleton.tsx +++ b/ui/staff-ui/src/components/shared/entity-list/StackedCardSkeleton.tsx @@ -2,19 +2,19 @@ export default function StackedCardSkeleton() { return ( -
-
+
+
-
+
-
-
-
+
+
+
{[...Array(3)].map((_, i) => (
-
+
diff --git a/ui/staff-ui/src/components/ui/KeyValue.tsx b/ui/staff-ui/src/components/ui/KeyValue.tsx index 36ad7ab3..4758a360 100644 --- a/ui/staff-ui/src/components/ui/KeyValue.tsx +++ b/ui/staff-ui/src/components/ui/KeyValue.tsx @@ -32,11 +32,11 @@ export function KeyValue({
- + {label} :{' '} {value} diff --git a/ui/staff-ui/src/components/ui/SearchBar.tsx b/ui/staff-ui/src/components/ui/SearchBar.tsx index c0dac5e3..512daf15 100644 --- a/ui/staff-ui/src/components/ui/SearchBar.tsx +++ b/ui/staff-ui/src/components/ui/SearchBar.tsx @@ -10,6 +10,7 @@ interface SearchBarProps { category: string; onSearch: (value: string, category: string) => void; iconSize?: number; + iconClassName?: string; pxClass?: string; textClass?: string; } @@ -20,6 +21,7 @@ const SearchBar = ({ category, onSearch, iconSize = 24, + iconClassName, pxClass = "px-2", textClass = "text-[20px]" }: SearchBarProps) => { @@ -27,25 +29,26 @@ const SearchBar = ({ const [value, setValue] = useState(searchValue || ""); return ( -
+
setValue(e.target.value)} onKeyDown={(e) => e.key === "Enter" && onSearch(value, category)} - className={`border-none outline-none flex-1 bg-transparent px-2 pl-3 py-0 font-normal text-neutral-first placeholder-neutral-first/50 ${textClass}`} + className={`min-w-0 border-none outline-none flex-1 bg-transparent px-2 pl-3 py-0 font-normal text-neutral-first placeholder-neutral-first/50 ${textClass}`} />
diff --git a/ui/staff-ui/src/components/ui/SearchBarDropdown.tsx b/ui/staff-ui/src/components/ui/SearchBarDropdown.tsx index ca4c9fd9..617ea4c4 100644 --- a/ui/staff-ui/src/components/ui/SearchBarDropdown.tsx +++ b/ui/staff-ui/src/components/ui/SearchBarDropdown.tsx @@ -40,22 +40,22 @@ const SearchBarDropdown = ({ options.find((o) => o.value === selected)?.label || t('select'); return ( -
+
{/* BUTTON */} @@ -72,7 +72,7 @@ const SearchBarDropdown = ({ onChange(opt.value); setOpen(false); }} - className={`block w-full h-14 px-6 py-1 text-left text-[20px] font-medium transition-colors ${selected === opt.value ? "bg-secondary-second" : ""}`} + className={`block w-full min-h-14 h-auto px-3 sm:px-6 py-2 text-left text-base sm:text-[20px] font-medium break-words transition-colors ${selected === opt.value ? "bg-secondary-second" : ""}`} > {opt.label} diff --git a/ui/staff-ui/src/components/ui/StatsCard.tsx b/ui/staff-ui/src/components/ui/StatsCard.tsx index c72af627..3a9837e5 100644 --- a/ui/staff-ui/src/components/ui/StatsCard.tsx +++ b/ui/staff-ui/src/components/ui/StatsCard.tsx @@ -194,17 +194,17 @@ const StatsCard = ({ width={20} height={20} alt="" - className={active ? "invert" : "opacity-60"} + className={`shrink-0 ${active ? "invert" : "opacity-60"}`} /> )} {/* value */} - + {row.value} {/* label */} - + {row.label} @@ -216,7 +216,7 @@ const StatsCard = ({ tabIndex={0} onClick={handleCardClick} onKeyDown={handleCardKeyDown} - className={`flex flex-col justify-between transition-all duration-200 w-full rounded-[10px] px-7 py-6 cursor-pointer ${active ? "border-black bg-neutral-first text-neutral-second" : "bg-secondary-second text-secondary-third"}`} + className={`flex flex-col justify-between transition-all duration-200 w-full min-w-0 rounded-[10px] px-4 py-5 sm:px-5 sm:py-6 cursor-pointer ${active ? "border-black bg-neutral-first text-neutral-second" : "bg-secondary-second text-secondary-third"}`} >
{/* count and title */} @@ -228,10 +228,10 @@ const StatsCard = ({
) : ( <> -

+

{totalCount}

-

+

{title}

@@ -248,19 +248,19 @@ const StatsCard = ({

{t('failed_to_load')}

) : ( // items -
    +
      {rows.map((row) => ( -
    • +
    • {row.href ? ( event.stopPropagation()} - className="flex items-center gap-2 cursor-pointer no-underline" + className="flex items-center gap-2 min-w-0 cursor-pointer no-underline" > {rowContent(row)} ) : ( -
      +
      {rowContent(row)}
      )} diff --git a/ui/staff-ui/src/components/ui/StatsCardsCarousel.tsx b/ui/staff-ui/src/components/ui/StatsCardsCarousel.tsx index b0882c6f..4d3a5338 100644 --- a/ui/staff-ui/src/components/ui/StatsCardsCarousel.tsx +++ b/ui/staff-ui/src/components/ui/StatsCardsCarousel.tsx @@ -10,7 +10,14 @@ import { } from "react"; import Image from "next/image"; -const VISIBLE_COUNT = 4; +const DESKTOP_VISIBLE_COUNT = 4; + +function visibleCountForWidth(width: number) { + if (width < 520) return 1; + if (width < 780) return 2; + if (width < 1100) return 3; + return DESKTOP_VISIBLE_COUNT; +} interface StatsCardsCarouselProps { cards: T[]; @@ -34,7 +41,7 @@ export default function StatsCardsCarousel({ StatsCardComponent, statsEndpointFor, }: StatsCardsCarouselProps) { - const maxOffset = Math.max(0, cards.length - VISIBLE_COUNT); + const [visibleCount, setVisibleCount] = useState(DESKTOP_VISIBLE_COUNT); const [offset, setOffset] = useState(0); const containerRef = useRef(null); const viewportRef = useRef(null); @@ -43,6 +50,7 @@ export default function StatsCardsCarousel({ const wheelLockRef = useRef(false); const [cardWidth, setCardWidth] = useState(0); const [slideStep, setSlideStep] = useState(0); + const maxOffset = Math.max(0, cards.length - visibleCount); offsetRef.current = offset; @@ -53,9 +61,13 @@ export default function StatsCardsCarousel({ const track = trackRef.current; if (!viewport || !track || cards.length === 0) return; + const count = Math.min( + cards.length, + visibleCountForWidth(viewport.clientWidth), + ); const gap = parseFloat(getComputedStyle(track).columnGap || "0") || 0; - const width = - (viewport.clientWidth - gap * (VISIBLE_COUNT - 1)) / VISIBLE_COUNT; + const width = (viewport.clientWidth - gap * (count - 1)) / count; + setVisibleCount(count); setCardWidth(width); setSlideStep(width + gap); }, [cards.length]); @@ -73,16 +85,21 @@ export default function StatsCardsCarousel({ return () => observer.disconnect(); }, [measureLayout]); + useLayoutEffect(() => { + setOffset((current) => Math.min(current, maxOffset)); + }, [maxOffset]); + useEffect(() => { if (activeIndex < 0) return; setOffset((current) => { - if (activeIndex < current) return activeIndex; - if (activeIndex >= current + VISIBLE_COUNT) { - return activeIndex - VISIBLE_COUNT + 1; + const next = Math.min(current, maxOffset); + if (activeIndex < next) return activeIndex; + if (activeIndex >= next + visibleCount) { + return Math.min(maxOffset, activeIndex - visibleCount + 1); } - return current; + return next; }); - }, [activeIndex]); + }, [activeIndex, visibleCount, maxOffset]); const canScrollBack = offset > 0; const canScrollForward = offset < maxOffset; diff --git a/ui/staff-ui/src/features/approval/components/ApprovalCard.tsx b/ui/staff-ui/src/features/approval/components/ApprovalCard.tsx index 979efdaf..38f37885 100644 --- a/ui/staff-ui/src/features/approval/components/ApprovalCard.tsx +++ b/ui/staff-ui/src/features/approval/components/ApprovalCard.tsx @@ -144,7 +144,7 @@ export default function ApprovalCard({
      {comment.length}/{MESSAGE_MAX_LENGTH}
      -
      +
      {/* Left Sidebar */} -
      +
      {sortedConfig.map(filter => { const isActive = filter.field_name === selectedFieldName; return (
      {/* Right Side Content */} -
      +
      {selectedFilter && t("filter_search_by", { field: t(selectedFilter.display_label) })}
      diff --git a/ui/staff-ui/src/features/filter/components/SelectedFilters.tsx b/ui/staff-ui/src/features/filter/components/SelectedFilters.tsx index fbdc5f8a..b956ae54 100644 --- a/ui/staff-ui/src/features/filter/components/SelectedFilters.tsx +++ b/ui/staff-ui/src/features/filter/components/SelectedFilters.tsx @@ -109,20 +109,20 @@ export default function SelectedFilters({ aria-label={t('remove')} className="shrink-0" > - {t('common.remove')} + {t('common.remove')}
      ); return ( -
      -
      +
      +
      {leading ? ( -
      +
      {leading}
      ) : null} - + {t('selected_filters')} @@ -131,7 +131,7 @@ export default function SelectedFilters({ {t('none')}
      ) : ( -
      +
      {visibleFilters.map((filter, index) => renderChip(filter, index, true))} {hiddenCount > 0 ? (
      @@ -145,7 +145,7 @@ export default function SelectedFilters({ : `+${hiddenCount} more`} {moreOpen ? ( -
      +
      {appliedFilters.slice(VISIBLE_FILTER_COUNT).map((filter, offset) => renderChip(filter, offset + VISIBLE_FILTER_COUNT), )} @@ -168,8 +168,8 @@ export default function SelectedFilters({
      {onSearch && ( -
      -
      +
      +
      {showFilters && ( -
      -

      +
      +

      {t('attached_documents')}

      +
      - Close + Close
      From d9100d11b057de8d90303b25759617dd6a1ef562 Mon Sep 17 00:00:00 2001 From: Niranjan Kumar Date: Thu, 15 Oct 2026 15:27:39 +0530 Subject: [PATCH 2/5] G2P-5807 fix: improve responsiveness of the intake page and related components --- .../[type]/new/[intakeFormId]/page.tsx | 2 +- .../[type]/[id]/change-request/page.tsx | 2 +- .../src/components/shared/BreadcrumbBar.tsx | 16 +++--- ui/staff-ui/src/components/shared/TopBar.tsx | 10 ++-- .../shared/entity-list/EntityListPage.tsx | 8 +-- .../shared/entity-list/MoreMenu.tsx | 20 +++++++- .../src/components/ui/AddNewDropdown.tsx | 30 ++++++++++-- .../components/DeduplicationCardForIntake.tsx | 49 ++++++++++++++++--- .../components/FormDetailsCard.tsx | 4 +- .../IntakeFormDeduplicationTabs.tsx | 8 +-- .../components/IntakeFormSubmissionView.tsx | 2 +- .../components/MultiSectionAccordionForms.tsx | 35 +++++++++++-- 12 files changed, 144 insertions(+), 42 deletions(-) diff --git a/ui/staff-ui/src/app/[locale]/intake-form/[type]/new/[intakeFormId]/page.tsx b/ui/staff-ui/src/app/[locale]/intake-form/[type]/new/[intakeFormId]/page.tsx index c91b6757..4e2103e8 100644 --- a/ui/staff-ui/src/app/[locale]/intake-form/[type]/new/[intakeFormId]/page.tsx +++ b/ui/staff-ui/src/app/[locale]/intake-form/[type]/new/[intakeFormId]/page.tsx @@ -67,7 +67,7 @@ export default function NewIntakeFormSubmissionPage() { showCapsule={false} /> -
      +
      {loading ? (
      {t('loading')} diff --git a/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx b/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx index ac688a9f..02be1536 100644 --- a/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx +++ b/ui/staff-ui/src/app/[locale]/register/[type]/[id]/change-request/page.tsx @@ -74,7 +74,7 @@ export default function ChangeRequestPage() { // Right side of TabsLayout-- Pending request + pagination const pendingRequestsCount = pendingData?.number_of_pending_change_requests ?? 0; const rightContent = !loading && ( -
      +
      {pendingRequestsCount !== undefined && (
      diff --git a/ui/staff-ui/src/components/shared/BreadcrumbBar.tsx b/ui/staff-ui/src/components/shared/BreadcrumbBar.tsx index d6a46cb4..9978ad7f 100644 --- a/ui/staff-ui/src/components/shared/BreadcrumbBar.tsx +++ b/ui/staff-ui/src/components/shared/BreadcrumbBar.tsx @@ -35,24 +35,23 @@ export default function BreadcrumbBar({ breadcrumb = [] }: BreadcrumbBarProps) { } return ( -
      - -
      - {t('home')} -
      +
      + + {t('home')} +
      {breadcrumb.map((item, index) => { const isLast = index === breadcrumb.length - 1; const textColor = isLast ? "text-neutral-first" : "text-neutral-first/50"; - const labelClass = `block whitespace-nowrap ${textColor}`; + const labelClass = `block max-w-full truncate whitespace-nowrap ${textColor}`; return (
      -
      +
      {item.href && !isLast ? ( {item.label} ) : ( @@ -73,6 +72,7 @@ export default function BreadcrumbBar({ breadcrumb = [] }: BreadcrumbBarProps) {
      ); })} +
      ); } diff --git a/ui/staff-ui/src/components/shared/TopBar.tsx b/ui/staff-ui/src/components/shared/TopBar.tsx index 67439323..d5a7213b 100644 --- a/ui/staff-ui/src/components/shared/TopBar.tsx +++ b/ui/staff-ui/src/components/shared/TopBar.tsx @@ -91,18 +91,18 @@ export default function TopBar({
      -
      +
      {breadcrumb && breadcrumb.length > 0 && ( )} @@ -115,7 +115,7 @@ export default function TopBar({
      )}
      -
      +
      {showSearch && onSearch && (
      ({ ); const topBar = ( -
      -
      -
      +
      +
      +
      {breadcrumb.length > 0 && }
      -
      +
      {actions} {showPagination && onPrev && onNext && ( diff --git a/ui/staff-ui/src/components/shared/entity-list/MoreMenu.tsx b/ui/staff-ui/src/components/shared/entity-list/MoreMenu.tsx index bddc6eec..2c660ab4 100644 --- a/ui/staff-ui/src/components/shared/entity-list/MoreMenu.tsx +++ b/ui/staff-ui/src/components/shared/entity-list/MoreMenu.tsx @@ -35,6 +35,9 @@ export default function MoreMenu({ const [kebabOpen, setKebabOpen] = useState(false); const [openSubmenuId, setOpenSubmenuId] = useState(null); const containerRef = useRef(null); + const buttonRef = useRef(null); + const [narrowMenu, setNarrowMenu] = useState(false); + const [menuTop, setMenuTop] = useState(0); const hasViewToggle = showViewToggle && !!onViewChange; const hasExtraItems = extraItems.length > 0; @@ -74,7 +77,15 @@ export default function MoreMenu({ aria-label={t.has('more') ? t('more') : 'More options'} aria-haspopup="true" aria-expanded={kebabOpen} + ref={buttonRef} onClick={() => { + if (!kebabOpen && buttonRef.current) { + const narrow = window.matchMedia('(max-width: 639px)').matches; + setNarrowMenu(narrow); + if (narrow) { + setMenuTop(buttonRef.current.getBoundingClientRect().bottom + 8); + } + } setKebabOpen((prev) => !prev); setOpenSubmenuId(null); }} @@ -84,7 +95,14 @@ export default function MoreMenu({ {kebabOpen && ( -
      +
      {hasExtraItems && ( <> {extraItems.map((item) => ( diff --git a/ui/staff-ui/src/components/ui/AddNewDropdown.tsx b/ui/staff-ui/src/components/ui/AddNewDropdown.tsx index eead4602..3e328dc1 100644 --- a/ui/staff-ui/src/components/ui/AddNewDropdown.tsx +++ b/ui/staff-ui/src/components/ui/AddNewDropdown.tsx @@ -209,6 +209,9 @@ export default function AddNewDropdown({ const t = useTranslations(); const [open, setOpen] = useState(false); + const [narrowMenu, setNarrowMenu] = useState(false); + const [menuTop, setMenuTop] = useState(0); + const buttonRef = useRef(null); const [showImportModal, setShowImportModal] = useState(false); const [selectedVC, setSelectedVC] = useState(null); @@ -242,14 +245,24 @@ export default function AddNewDropdown({ return ( <> -
      +
      {open && ( -
      +
      string; } +function fieldSpacing(index: number) { + const smStart = index % 2 === 0; + const smEnd = (index + 1) % 2 === 0; + const lgStart = index % 3 === 0; + const lgEnd = (index + 1) % 3 === 0; + const xlStart = index % 4 === 0; + const xlEnd = (index + 1) % 4 === 0; + + const inset = [ + smStart ? "sm:pl-0" : "sm:pl-6", + lgStart ? "lg:pl-0" : "lg:pl-6", + xlStart ? "xl:pl-0" : "xl:pl-6", + ].join(" "); + + const trail = [ + smEnd ? "sm:pr-0" : "sm:pr-6", + lgEnd ? "lg:pr-0" : "lg:pr-6", + xlEnd ? "xl:pr-0" : "xl:pr-6", + ].join(" "); + + const rule = [ + smStart ? "sm:border-l-0" : "sm:border-l sm:border-primary-first", + lgStart ? "lg:border-l-0" : "lg:border-l lg:border-primary-first", + xlStart ? "xl:border-l-0" : "xl:border-l xl:border-primary-first", + ].join(" "); + + return { inset, trail, rule }; +} + export default function DeduplicationCardForIntake({ results, loading, type, t }: Props) { const [expandedIndex, setExpandedIndex] = useState(null); @@ -99,28 +128,32 @@ export default function DeduplicationCardForIntake({ results, loading, type, t } {expanded && fields.length > 0 && (
      -
      - {fields.map(([fieldKey, match]: [string, any], i) => ( +
      + {fields.map(([fieldKey, match]: [string, any], i) => { + const { inset, trail, rule } = fieldSpacing(i); + return (
      0 ? "md:pl-10" : ""}`} + className={`min-w-0 space-y-0 overflow-hidden py-2 ${trail}`} > -
      0 ? "md:pl-6" : ""}> +

      {t(fieldKey)}

      -
      0 ? "md:border-l md:border-primary-first md:pl-6" : ""}`}> - - +
      + +
      - ))} + ); + })}

      + )} +
      + )} + +
      Date: Thu, 15 Oct 2026 17:47:31 +0530 Subject: [PATCH 3/5] G2P-5815 fix: improve responsiveness of the registry configuration --- .../configuration/registry/details/page.tsx | 18 ++--- .../configuration/registry/languages/page.tsx | 12 ++-- .../registry/themes/create/page.tsx | 16 ++--- .../configuration/registry/themes/page.tsx | 12 ++-- .../src/components/shared/ImageCropper.tsx | 8 +-- .../registry/components/EditRegistry.tsx | 36 +++++----- .../registry/components/LanguageSelector.tsx | 7 +- .../components/LanguageTranslationEditor.tsx | 32 ++++----- .../registry/components/ThemeColorEditor.tsx | 54 ++++++++++----- .../registry/components/ThemeSelector.tsx | 4 +- .../components/TranslationJsonEditorPanel.tsx | 8 +-- .../shared/components/ConfigLayout.tsx | 68 ++++++++++++++++++- .../shared/components/ConfigSidebar.tsx | 10 ++- 13 files changed, 190 insertions(+), 95 deletions(-) diff --git a/ui/staff-ui/src/app/[locale]/configuration/registry/details/page.tsx b/ui/staff-ui/src/app/[locale]/configuration/registry/details/page.tsx index e8232d2b..6ad3dd29 100644 --- a/ui/staff-ui/src/app/[locale]/configuration/registry/details/page.tsx +++ b/ui/staff-ui/src/app/[locale]/configuration/registry/details/page.tsx @@ -141,7 +141,7 @@ const RegistryConfigurationPage = () => { showAddNewButton={false} /> -
      +
      {isLoading ? (
      Loading @@ -162,23 +162,23 @@ const RegistryConfigurationPage = () => { onCancel={() => setIsEditing(false)} /> ) : ( -
      +
      -
      +
      {t('registry_logo')} -
      +
      {hasCustomLogo ? ( { unoptimized /> ) : ( -
      +
      {t('no_file_selected')}
      @@ -224,7 +224,7 @@ const RegistryConfigurationPage = () => { {!isHorizontalLogo && (
      {t('registry_name')} -

      +

      {resolvedName}

      @@ -239,7 +239,7 @@ const RegistryConfigurationPage = () => {
      {t('registry_theme')} - + {selectedTheme?.theme_mnemonic || t('no_items_found')}
      @@ -278,7 +278,7 @@ const RegistryConfigurationPage = () => { )}
      {t('registry_language')} - + {selectedLanguage?.language_label || t('no_items_found')}
      diff --git a/ui/staff-ui/src/app/[locale]/configuration/registry/languages/page.tsx b/ui/staff-ui/src/app/[locale]/configuration/registry/languages/page.tsx index 1bd768f8..5b22f464 100644 --- a/ui/staff-ui/src/app/[locale]/configuration/registry/languages/page.tsx +++ b/ui/staff-ui/src/app/[locale]/configuration/registry/languages/page.tsx @@ -36,13 +36,13 @@ const LanguagesConfigurationPage = () => { showAddNewButton={false} /> -
      -
      -
      +
      +
      +

      Language configuration

      -
      -
      +
      +
      {
      -
      +
      -
      +