Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/common/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const TOAST_THEMES: Record<
container: 'bg-[#142618]/95 border-emerald-500/25 text-white',
icon: (
<div className="w-8 h-8 rounded-full flex items-center justify-center shrink-0 bg-[#22c55e] text-black shadow-sm select-none">
<Icon name="check" size={15} className="stroke-[3]" />
<Icon name="check" size={15} className="stroke-3" />
</div>
),
defaultTitle: 'موفقیت آمیز',
Expand Down Expand Up @@ -198,9 +198,11 @@ export function showToast(
<div
dir="rtl"
className={cn(
'w-full max-w-[390px] min-w-[320px] rounded-2xl p-3.5 flex items-center justify-between gap-3 shadow-2xl backdrop-blur-xl border select-none transition-all duration-200 pointer-events-auto',
'w-full max-w-97.5 min-w-[320px] rounded-2xl p-3.5 flex items-center justify-between gap-3 shadow-2xl backdrop-blur-xl border select-none transition-all duration-200 pointer-events-auto',
theme.container,
t.visible ? 'opacity-100 translate-y-0 scale-100' : 'opacity-0 -translate-y-2 scale-95'
t.visible
? 'opacity-100 translate-y-0 scale-100'
: 'opacity-0 -translate-y-2 scale-95'
)}
>
<div className="flex items-center flex-1 min-w-0 gap-3">
Expand All @@ -212,7 +214,7 @@ export function showToast(
{message && (
<p
className={cn(
'text-xs font-normal leading-relaxed m-0 mt-0.5 break-words line-clamp-2',
'text-xs font-normal leading-relaxed m-0 mt-0.5 wrap-break-word line-clamp-2',
theme.messageClass
)}
>
Expand Down Expand Up @@ -269,7 +271,7 @@ export function showPreviewToast(itemName: string, onCancel: () => void): string
(t) => (
<div
className={cn(
' rounded-2xl p-2.5 flex items-center justify-between gap-3 shadow-2xl backdrop-blur-xl border border-white/15 bg-[#18181b]/95 text-white select-none transition-all duration-200',
'pointer-events-auto rounded-2xl p-2.5 flex items-center justify-between gap-3 shadow-2xl backdrop-blur-xl border border-white/15 bg-[#18181b]/95 text-white select-none transition-all duration-200',
t.visible ? 'animate-enter' : 'animate-leave'
)}
>
Expand Down
5 changes: 3 additions & 2 deletions src/components/gallery/gallery-picker-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,13 @@ export function GalleryPickerModal({
onClose={onClose}
title={title}
size="xl"
className=""
direction="rtl"
closeOnBackdropClick={true}
>
<div className="flex flex-col gap-4 w-full p-1 min-h-120 max-h-[75vh]">
<div className="flex flex-col w-full gap-4 p-1">
{categories.length > 0 && (
<div className="flex items-center gap-1.5 overflow-x-auto no-scrollbar pb-1">
<div className="flex items-center gap-1.5 overflow-y-hidden h-12 overflow-x-auto no-scrollbar">
<Chip
selected={selectedCategory === 'ALL'}
onClick={() => setSelectedCategory('ALL')}
Expand Down
31 changes: 28 additions & 3 deletions src/components/ui/modal/modal.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -22,8 +22,12 @@ export type ModalProps = VariantProps<typeof modalBoxVariants> & {
closeOnBackdropClick?: boolean
showCloseButton?: boolean
className?: string
zIndex?: number
}

let globalModalCounter = 0
const BASE_MODAL_Z_INDEX = 1000

export function Modal({
isOpen,
onClose,
Expand All @@ -34,8 +38,18 @@ export function Modal({
direction = 'ltr',
showCloseButton = true,
className,
zIndex: customZIndex,
}: ModalProps) {
const dialogRef = useRef<HTMLDialogElement>(null)
const [assignedZIndex, setAssignedZIndex] = useState<number>(() => {
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
Expand All @@ -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
Expand Down Expand Up @@ -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
}
>
<div
onClick={(e) => e.stopPropagation()}
Expand Down
1 change: 0 additions & 1 deletion src/components/ui/modal/modal.variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export const modalDialogVariants = cva([
'modal-middle',
'p-2',
'md:p-4',
'z-[1000]',
])

export type ModalDialogVariant = typeof modalDialogVariants
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export const ProfileDisplay = () => {
label="علایق"
editable
value={
<div className="flex flex-wrap self-end justify-end flex-1 gap-1 overflow-y-auto w-42 sm:w-72">
<div className="flex flex-wrap self-end justify-end flex-1 gap-1 overflow-y-auto max-w-42 sm:max-w-72">
{user?.interests?.map((i) => (
<Chip
onClick={() => {}}
Expand Down
34 changes: 13 additions & 21 deletions src/layouts/widgets-settings/widget-settings-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
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'
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
Expand Down Expand Up @@ -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
Expand All @@ -74,21 +70,17 @@ export function WidgetSettingsModal({
const handleCloseSetting = onCloseSetting || onClose

return (
<>
<AddWidgetModal isOpen={isManageOpen} onClose={onClose} />

<Modal
isOpen={!!activeSettingConfig}
onClose={handleCloseSetting}
title={activeSettingConfig?.title}
size={activeSettingConfig?.size}
direction="rtl"
closeOnBackdropClick
>
{activeSettingConfig && (
<activeSettingConfig.Component {...({ instanceId, size } as any)} />
)}
</Modal>
</>
<Modal
isOpen={!!activeSettingConfig}
onClose={handleCloseSetting}
title={activeSettingConfig?.title}
size={activeSettingConfig?.size}
direction="rtl"
closeOnBackdropClick
>
{activeSettingConfig && (
<activeSettingConfig.Component {...({ instanceId, size } as any)} />
)}
</Modal>
)
}
105 changes: 42 additions & 63 deletions src/layouts/widgets/tools/tools.layout.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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 = [
{
Expand All @@ -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',
Expand All @@ -59,7 +46,7 @@ interface ToolsLayoutProps {
}

export const ToolsLayout: React.FC<ToolsLayoutProps> = ({ size = { w: 2, h: 3 } }) => {
const [activeTab, setActiveTab] = useState<ToolsTabType | null>(null)
const [activeTab, setActiveTab] = useState<ToolsTabType>('pomodoro')
const [activeModalTool, setActiveModalTool] = useState<ToolsTabType | null>(null)
const { selectedDate } = useDate()

Expand All @@ -78,12 +65,8 @@ export const ToolsLayout: React.FC<ToolsLayoutProps> = ({ 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)
}
}

Expand All @@ -110,13 +93,11 @@ export const ToolsLayout: React.FC<ToolsLayoutProps> = ({ size = { w: 2, h: 3 }
size="md"
direction="rtl"
>
<Suspense>
{activeModalTool === 'religious-time' && (
<ReligiousTime currentDate={selectedDate} />
)}
{activeModalTool === 'pomodoro' && <PomodoroTimer />}
{activeModalTool === 'currency-converter' && <CurrencyConverter />}
</Suspense>
{activeModalTool === 'religious-time' && (
<ReligiousTime currentDate={selectedDate} />
)}
{activeModalTool === 'pomodoro' && <PomodoroTimer />}
{activeModalTool === 'currency-converter' && <CurrencyConverter />}
</Modal>
</>
)
Expand All @@ -133,40 +114,38 @@ export const ToolsLayout: React.FC<ToolsLayoutProps> = ({ size = { w: 2, h: 3 }
className="w-full border-none"
/>

<Suspense>
{activeTab === 'religious-time' && (
<motion.div
key="religious-time-view"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<ReligiousTime currentDate={selectedDate} />
</motion.div>
)}
{activeTab === 'religious-time' && (
<motion.div
key="religious-time-view"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<ReligiousTime currentDate={selectedDate} />
</motion.div>
)}

{activeTab === 'pomodoro' && (
<motion.div
key="pomodoro-view"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<PomodoroTimer />
</motion.div>
)}
{activeTab === 'pomodoro' && (
<motion.div
key="pomodoro-view"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<PomodoroTimer />
</motion.div>
)}

{activeTab === 'currency-converter' && (
<motion.div
key="currency-converter-view"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<CurrencyConverter />
</motion.div>
)}
</Suspense>
{activeTab === 'currency-converter' && (
<motion.div
key="currency-converter-view"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<CurrencyConverter />
</motion.div>
)}
</WidgetContainer>
)
}
Loading
Loading