diff --git a/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.spec.tsx b/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.spec.tsx index 13cf6632501..ed9d348b7dd 100644 --- a/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.spec.tsx +++ b/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.spec.tsx @@ -4,6 +4,7 @@ import type { PublicProfile } from '../../../../lib/user'; import { ProfileUserWorkspacePhotos } from './ProfileUserWorkspacePhotos'; import { useUserWorkspacePhotos } from '../../hooks/useUserWorkspacePhotos'; import { useGear } from '../../hooks/useGear'; +import { LazyModal } from '../../../../components/modals/common/types'; jest.mock('../../hooks/useUserWorkspacePhotos', () => ({ ...jest.requireActual('../../hooks/useUserWorkspacePhotos'), @@ -22,6 +23,11 @@ jest.mock('../../../../hooks/usePrompt', () => ({ usePrompt: () => ({ showPrompt: jest.fn() }), })); +const mockOpenModal = jest.fn(); +jest.mock('../../../../hooks/useLazyModal', () => ({ + useLazyModal: () => ({ openModal: mockOpenModal }), +})); + const mockUseUserWorkspacePhotos = useUserWorkspacePhotos as jest.MockedFunction; const mockUseGear = useGear as jest.MockedFunction; @@ -39,11 +45,6 @@ const baseUser: PublicProfile = { const photo = { id: 'p1', image: 'https://daily.dev/desk.png', position: 0 }; -const renderAndOpenLightbox = () => { - render(); - fireEvent.click(screen.getByRole('button', { name: 'View workspace photo' })); -}; - beforeEach(() => { jest.clearAllMocks(); mockUseUserWorkspacePhotos.mockReturnValue({ @@ -63,27 +64,28 @@ beforeEach(() => { }); describe('ProfileUserWorkspacePhotos lightbox', () => { - it('opens a dialog with a blurred backdrop when a photo is clicked', () => { - renderAndOpenLightbox(); - - expect( - screen.getByRole('dialog', { name: 'Workspace photo lightbox' }), - ).toBeInTheDocument(); - const backdrop = screen.getByRole('button', { name: 'Close lightbox' }); - expect(backdrop.className).toMatch(/backdrop-blur/); - }); - - it('closes the lightbox when the backdrop is clicked', () => { - renderAndOpenLightbox(); - - fireEvent.click(screen.getByRole('button', { name: 'Close lightbox' })); - expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - }); + it('opens the shared image lightbox with the photo when clicked', () => { + render(); - it('closes the lightbox when the close button is clicked', () => { - renderAndOpenLightbox(); + fireEvent.click( + screen.getByRole('button', { name: 'View workspace photo' }), + ); - fireEvent.click(screen.getByRole('button', { name: 'Close' })); - expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + expect(mockOpenModal).toHaveBeenCalledTimes(1); + expect(mockOpenModal).toHaveBeenCalledWith( + expect.objectContaining({ + type: LazyModal.ImageView, + props: expect.objectContaining({ + src: photo.image, + alt: 'Workspace', + originRect: expect.objectContaining({ + top: expect.any(Number), + left: expect.any(Number), + width: expect.any(Number), + height: expect.any(Number), + }), + }), + }), + ); }); }); diff --git a/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.tsx b/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.tsx index 22381f51518..cbe82924db8 100644 --- a/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.tsx +++ b/packages/shared/src/features/profile/components/workspacePhotos/ProfileUserWorkspacePhotos.tsx @@ -15,7 +15,6 @@ import { sortableKeyboardCoordinates, rectSortingStrategy, } from '@dnd-kit/sortable'; -import { useEventListener } from '../../../../hooks/useEventListener'; import type { PublicProfile } from '../../../../lib/user'; import { useUserWorkspacePhotos, @@ -33,7 +32,9 @@ import { ButtonVariant, } from '../../../../components/buttons/Button'; import { CameraIcon, SettingsIcon } from '../../../../components/icons'; -import CloseButton from '../../../../components/CloseButton'; +import { useLazyModal } from '../../../../hooks/useLazyModal'; +import { LazyModal } from '../../../../components/modals/common/types'; +import { getImageOriginRect } from '../../../../components/modals/ImageModal'; import { SortableWorkspacePhotoItem } from './WorkspacePhotoItem'; import { WorkspacePhotoUploadModal } from './WorkspacePhotoUploadModal'; import { GearModal } from '../gear/GearModal'; @@ -63,10 +64,10 @@ export function ProfileUserWorkspacePhotos({ const { displayToast } = useToastNotification(); const { showPrompt } = usePrompt(); const { logEvent } = useLogContext(); + const { openModal } = useLazyModal(); const [isPhotoModalOpen, setIsPhotoModalOpen] = useState(false); const [isGearModalOpen, setIsGearModalOpen] = useState(false); - const [selectedPhoto, setSelectedPhoto] = useState(null); const sensors = useSensors( useSensor(PointerSensor, { @@ -197,20 +198,19 @@ export function ProfileUserWorkspacePhotos({ setIsGearModalOpen(false); }, []); - const handlePhotoClick = useCallback((photo: { image: string }) => { - setSelectedPhoto(photo.image); - }, []); - - const handleCloseLightbox = useCallback(() => { - setSelectedPhoto(null); - }, []); - - // Close lightbox on ESC key - useEventListener(globalThis as unknown as Window, 'keydown', (event) => { - if (event.key === 'Escape' && selectedPhoto) { - handleCloseLightbox(); - } - }); + const handlePhotoClick = useCallback( + (photo: { image: string }, event: React.MouseEvent) => { + openModal({ + type: LazyModal.ImageView, + props: { + src: photo.image, + alt: 'Workspace', + originRect: getImageOriginRect(event.currentTarget), + }, + }); + }, + [openModal], + ); const hasPhotos = photos.length > 0; const hasGear = gearItems.length > 0; @@ -355,33 +355,6 @@ export function ProfileUserWorkspacePhotos({ onSubmit={handleAddGear} /> )} - - {selectedPhoto && ( -
-
- )} ); } diff --git a/packages/shared/src/features/profile/components/workspacePhotos/WorkspacePhotoItem.tsx b/packages/shared/src/features/profile/components/workspacePhotos/WorkspacePhotoItem.tsx index 472f70e60f2..b548674bf5d 100644 --- a/packages/shared/src/features/profile/components/workspacePhotos/WorkspacePhotoItem.tsx +++ b/packages/shared/src/features/profile/components/workspacePhotos/WorkspacePhotoItem.tsx @@ -15,7 +15,10 @@ interface WorkspacePhotoItemProps { photo: UserWorkspacePhoto; isOwner: boolean; onDelete?: (photo: UserWorkspacePhoto) => void; - onClick?: (photo: UserWorkspacePhoto) => void; + onClick?: ( + photo: UserWorkspacePhoto, + event: React.MouseEvent, + ) => void; } export function WorkspacePhotoItem({ @@ -35,7 +38,7 @@ export function WorkspacePhotoItem({