From 720a7894f5a3e54993d9ae96b70e3087620802f4 Mon Sep 17 00:00:00 2001 From: sajjad isvand Date: Fri, 4 Sep 2026 13:20:50 +0330 Subject: [PATCH 1/2] feat: refactor ToolsLayout to remove lazy loading for components and streamline tab management --- src/layouts/widgets/tools/tools.layout.tsx | 105 +++++++++------------ 1 file changed, 42 insertions(+), 63 deletions(-) diff --git a/src/layouts/widgets/tools/tools.layout.tsx b/src/layouts/widgets/tools/tools.layout.tsx index 3ee2816a0..ccc53ba7f 100644 --- a/src/layouts/widgets/tools/tools.layout.tsx +++ b/src/layouts/widgets/tools/tools.layout.tsx @@ -1,5 +1,5 @@ import { Motion as motion } from '@/common/motion' -import React, { Suspense, useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import Analytics from '@/analytics' import { getFromStorage, setToStorage } from '@/common/storage' import { useDate } from '@/context/date.context' @@ -12,6 +12,9 @@ import { } from 'react-icons/md' import { ToolsCompactRow } from './variants/tools-2x1' import type { WidgetSize } from '../layout-engine/types' +import { ReligiousTime } from './religious/religious-time' +import { PomodoroTimer } from './pomodoro/pomodoro-timer' +import { CurrencyConverter } from './currency/currency-converter' const tabs = [ { @@ -31,22 +34,6 @@ const tabs = [ }, ] -const ReligiousTime = React.lazy(() => - import('./religious/religious-time').then((module) => ({ - default: module.ReligiousTime, - })) -) -const PomodoroTimer = React.lazy(() => - import('./pomodoro/pomodoro-timer').then((module) => ({ - default: module.PomodoroTimer, - })) -) -const CurrencyConverter = React.lazy(() => - import('./currency/currency-converter').then((module) => ({ - default: module.CurrencyConverter, - })) -) - export enum ToolsTab { pomodoro = 'pomodoro', 'religious-time' = 'religious-time', @@ -59,7 +46,7 @@ interface ToolsLayoutProps { } export const ToolsLayout: React.FC = ({ size = { w: 2, h: 3 } }) => { - const [activeTab, setActiveTab] = useState(null) + const [activeTab, setActiveTab] = useState('pomodoro') const [activeModalTool, setActiveModalTool] = useState(null) const { selectedDate } = useDate() @@ -78,12 +65,8 @@ export const ToolsLayout: React.FC = ({ size = { w: 2, h: 3 } useEffect(() => { async function load() { const tabFromStorage = await getFromStorage('toolsTab') - if (!tabFromStorage) { - setActiveTab('pomodoro') - } else { - ToolsTab[tabFromStorage] - ? setActiveTab(tabFromStorage) - : setActiveTab('pomodoro') + if (tabFromStorage && ToolsTab[tabFromStorage]) { + setActiveTab(tabFromStorage) } } @@ -110,13 +93,11 @@ export const ToolsLayout: React.FC = ({ size = { w: 2, h: 3 } size="md" direction="rtl" > - - {activeModalTool === 'religious-time' && ( - - )} - {activeModalTool === 'pomodoro' && } - {activeModalTool === 'currency-converter' && } - + {activeModalTool === 'religious-time' && ( + + )} + {activeModalTool === 'pomodoro' && } + {activeModalTool === 'currency-converter' && } ) @@ -133,40 +114,38 @@ export const ToolsLayout: React.FC = ({ size = { w: 2, h: 3 } className="w-full border-none" /> - - {activeTab === 'religious-time' && ( - - - - )} + {activeTab === 'religious-time' && ( + + + + )} - {activeTab === 'pomodoro' && ( - - - - )} + {activeTab === 'pomodoro' && ( + + + + )} - {activeTab === 'currency-converter' && ( - - - - )} - + {activeTab === 'currency-converter' && ( + + + + )} ) } From d29f2ab55feff2fadfe07c0d0b8893b5642c398c Mon Sep 17 00:00:00 2001 From: sajjad isvand Date: Sat, 5 Sep 2026 08:04:16 +0330 Subject: [PATCH 2/2] fix: resolve nested modals z-index stacking and toast action clicks --- src/common/toast.tsx | 12 ++++--- .../gallery/gallery-picker-modal.tsx | 5 +-- src/components/ui/modal/modal.tsx | 31 +++++++++++++++-- src/components/ui/modal/modal.variants.ts | 1 - .../account/components/profile-display.tsx | 2 +- .../widget-settings-modal.tsx | 34 +++++++------------ src/pages/root.tsx | 14 ++++---- 7 files changed, 60 insertions(+), 39 deletions(-) diff --git a/src/common/toast.tsx b/src/common/toast.tsx index 23fae4b29..3b228c11c 100644 --- a/src/common/toast.tsx +++ b/src/common/toast.tsx @@ -152,7 +152,7 @@ const TOAST_THEMES: Record< container: 'bg-[#142618]/95 border-emerald-500/25 text-white', icon: (
- +
), defaultTitle: 'موفقیت آمیز', @@ -198,9 +198,11 @@ export function showToast(
@@ -212,7 +214,7 @@ export function showToast( {message && (

@@ -269,7 +271,7 @@ export function showPreviewToast(itemName: string, onCancel: () => void): string (t) => (

diff --git a/src/components/gallery/gallery-picker-modal.tsx b/src/components/gallery/gallery-picker-modal.tsx index c8f1743b3..7675ebeb9 100644 --- a/src/components/gallery/gallery-picker-modal.tsx +++ b/src/components/gallery/gallery-picker-modal.tsx @@ -89,12 +89,13 @@ export function GalleryPickerModal({ onClose={onClose} title={title} size="xl" + className="" direction="rtl" closeOnBackdropClick={true} > -
+
{categories.length > 0 && ( -
+
setSelectedCategory('ALL')} diff --git a/src/components/ui/modal/modal.tsx b/src/components/ui/modal/modal.tsx index 5e28d6bc6..2844554a6 100644 --- a/src/components/ui/modal/modal.tsx +++ b/src/components/ui/modal/modal.tsx @@ -1,5 +1,5 @@ import type { VariantProps } from 'class-variance-authority' -import React, { type ReactNode, useEffect, useRef } from 'react' +import React, { type ReactNode, useEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' import { cn } from '@/common/utils/cn' import { useGeneralSetting } from '@/context/general-setting.context' @@ -22,8 +22,12 @@ export type ModalProps = VariantProps & { closeOnBackdropClick?: boolean showCloseButton?: boolean className?: string + zIndex?: number } +let globalModalCounter = 0 +const BASE_MODAL_Z_INDEX = 1000 + export function Modal({ isOpen, onClose, @@ -34,8 +38,18 @@ export function Modal({ direction = 'ltr', showCloseButton = true, className, + zIndex: customZIndex, }: ModalProps) { const dialogRef = useRef(null) + const [assignedZIndex, setAssignedZIndex] = useState(() => { + if (isOpen) { + globalModalCounter += 1 + return customZIndex !== undefined + ? customZIndex + : BASE_MODAL_Z_INDEX + globalModalCounter * 20 + } + return customZIndex !== undefined ? customZIndex : BASE_MODAL_Z_INDEX + }) const { isOptimalMode } = useGeneralSetting() const modalDurationMs = isOptimalMode ? 0 : MODAL_EXIT_MS @@ -45,11 +59,17 @@ export function Modal({ if (!dialog) return if (isOpen) { + globalModalCounter += 1 + const computedZ = + customZIndex !== undefined + ? customZIndex + : BASE_MODAL_Z_INDEX + globalModalCounter * 20 + setAssignedZIndex(computedZ) dialog.setAttribute('open', '') } else { dialog.removeAttribute('open') } - }, [isOpen]) + }, [isOpen, customZIndex]) useEffect(() => { const dialog = dialogRef.current @@ -77,7 +97,12 @@ export function Modal({ }} onContextMenu={(e) => e.stopPropagation()} className={cn('flex items-center justify-center', modalDialogVariants())} - style={{ '--modal-duration': `${modalDurationMs}ms` } as React.CSSProperties} + style={ + { + '--modal-duration': `${modalDurationMs}ms`, + zIndex: assignedZIndex ?? (customZIndex !== undefined ? customZIndex : BASE_MODAL_Z_INDEX), + } as React.CSSProperties + } >
e.stopPropagation()} diff --git a/src/components/ui/modal/modal.variants.ts b/src/components/ui/modal/modal.variants.ts index 01db276e5..8e906ecce 100644 --- a/src/components/ui/modal/modal.variants.ts +++ b/src/components/ui/modal/modal.variants.ts @@ -60,7 +60,6 @@ export const modalDialogVariants = cva([ 'modal-middle', 'p-2', 'md:p-4', - 'z-[1000]', ]) export type ModalDialogVariant = typeof modalDialogVariants diff --git a/src/layouts/setting/tabs/account/components/profile-display.tsx b/src/layouts/setting/tabs/account/components/profile-display.tsx index 10240c3d2..3b5d741fd 100644 --- a/src/layouts/setting/tabs/account/components/profile-display.tsx +++ b/src/layouts/setting/tabs/account/components/profile-display.tsx @@ -226,7 +226,7 @@ export const ProfileDisplay = () => { label="علایق" editable value={ -
+
{user?.interests?.map((i) => ( {}} diff --git a/src/layouts/widgets-settings/widget-settings-modal.tsx b/src/layouts/widgets-settings/widget-settings-modal.tsx index 29044b057..c975e2b4f 100644 --- a/src/layouts/widgets-settings/widget-settings-modal.tsx +++ b/src/layouts/widgets-settings/widget-settings-modal.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import type React from 'react' import { Modal } from '@/components/ui' import { PetSettings } from '../widgetify-card/pets/setting/pet-setting' import { RssFeedSetting } from '../widgets/news/rss-feed-setting' @@ -6,7 +6,6 @@ import { WeatherSetting } from '../widgets/weather/weather-setting' import { WigiArzSetting } from '../widgets/wigi-arz/wigi-arz-setting' import { WigiPadSetting } from '../widgets/wigi-pad/wigi-pad-setting' import { WidgetTabKeys } from './constant/tab-keys' -import { AddWidgetModal } from '../widgets-manager' interface WidgetSettingModalConfig { title: string @@ -61,9 +60,6 @@ export function WidgetSettingsModal({ size, onCloseSetting, }: WidgetSettingsModalProps) { - const isManageOpen = - isOpen && (!selectedTab || selectedTab === WidgetTabKeys.widget_management) - const settingKey = activeSettingTab || (selectedTab && selectedTab !== WidgetTabKeys.widget_management @@ -74,21 +70,17 @@ export function WidgetSettingsModal({ const handleCloseSetting = onCloseSetting || onClose return ( - <> - - - - {activeSettingConfig && ( - - )} - - + + {activeSettingConfig && ( + + )} + ) } diff --git a/src/pages/root.tsx b/src/pages/root.tsx index 5caad924c..b6b001fcd 100644 --- a/src/pages/root.tsx +++ b/src/pages/root.tsx @@ -2,7 +2,7 @@ import { useState } from 'react' import { Toaster } from 'react-hot-toast' import Analytics from '@/analytics' import { purgeDeprecatedStorageKeys } from '@/common/storage' -import { listenEvent } from '@/common/utils/call-event' +import { callEvent, listenEvent } from '@/common/utils/call-event' import { TOAST_TOP_LAYER_ID } from '@/common/toast' import { Portal } from '@/components/ui' import { @@ -41,7 +41,10 @@ export function RootLayout() {
-
+
{ if (!data.tab || data.tab === WidgetTabKeys.widget_management) { - setShowManageWidgets(true) + callEvent('openAddCustomWidgetModal') } else { setActiveSettingPayload(data) } @@ -132,8 +134,8 @@ function Main() { setShowManageWidgets(false)} + isOpen={!!activeSettingPayload} + onClose={() => setActiveSettingPayload(null)} selectedTab={null} activeSettingTab={activeSettingPayload?.tab} instanceId={activeSettingPayload?.instanceId}