From c836bbbfc2123fd04f536f6c4173e65f20df8653 Mon Sep 17 00:00:00 2001 From: nitin <142569587+ehconitin@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:07:32 +0530 Subject: [PATCH] Fixed SignInUp Modal misalignment for devices smaller than 400px width (#6386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi @Bonapara, Issue #6385 I encountered an issue with the Modal component where its width was fixed at 400px. While the container housing the Modal adjusted its size based on the screen width, the Modal itself remained at 400px regardless of the screen size. I have implemented a change to address this problem. Could you please review the changes and let me know your thoughts? Thank you! https://github.com/user-attachments/assets/8358aacb-d6c3-440e-895e-7abc4f8a3534 --------- Co-authored-by: FĂ©lix Malfait --- .../components/{Modal.tsx => AuthModal.tsx} | 13 +- .../components/ModalWrapper.tsx | 20 +- .../components/StepNavigationButton.tsx | 1 + .../MatchColumnsStep/MatchColumnsStep.tsx | 2 +- .../SelectHeaderStep/SelectHeaderStep.tsx | 2 +- .../SelectSheetStep/SelectSheetStep.tsx | 3 +- .../steps/components/Steps.tsx | 3 +- .../steps/components/UploadFlow.tsx | 2 +- .../components/UploadStep/UploadStep.tsx | 3 +- .../ValidationStep/ValidationStep.tsx | 2 +- .../dialog-manager/components/Dialog.tsx | 2 +- .../modal/components/ConfirmationModal.tsx | 100 +++---- .../ui/layout/modal/components/Modal.tsx | 249 ++++++++++++++---- .../layout/modal/components/ModalLayout.tsx | 173 ------------ .../components/__stories__/Modal.stories.tsx | 3 - .../__stories__/ModalLayout.stories.tsx | 36 --- .../modules/ui/layout/page/DefaultLayout.tsx | 3 +- .../src/theme/constants/BackgroundDark.ts | 3 +- .../src/theme/constants/BackgroundLight.ts | 3 +- .../twenty-ui/src/theme/constants/Modal.ts | 1 + 20 files changed, 286 insertions(+), 338 deletions(-) rename packages/twenty-front/src/modules/auth/components/{Modal.tsx => AuthModal.tsx} (51%) delete mode 100644 packages/twenty-front/src/modules/ui/layout/modal/components/ModalLayout.tsx delete mode 100644 packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ModalLayout.stories.tsx diff --git a/packages/twenty-front/src/modules/auth/components/Modal.tsx b/packages/twenty-front/src/modules/auth/components/AuthModal.tsx similarity index 51% rename from packages/twenty-front/src/modules/auth/components/Modal.tsx rename to packages/twenty-front/src/modules/auth/components/AuthModal.tsx index f40de47cf5..0bef31d15d 100644 --- a/packages/twenty-front/src/modules/auth/components/Modal.tsx +++ b/packages/twenty-front/src/modules/auth/components/AuthModal.tsx @@ -1,17 +1,16 @@ -import React from 'react'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import styled from '@emotion/styled'; +import React from 'react'; -import { ModalLayout } from '@/ui/layout/modal/components/ModalLayout'; - -const StyledContent = styled(ModalLayout.Content)` +const StyledContent = styled(Modal.Content)` align-items: center; - width: calc(400px - ${({ theme }) => theme.spacing(10 * 2)}); + justify-content: center; `; type AuthModalProps = { children: React.ReactNode }; export const AuthModal = ({ children }: AuthModalProps) => ( - + {children} - + ); diff --git a/packages/twenty-front/src/modules/spreadsheet-import/components/ModalWrapper.tsx b/packages/twenty-front/src/modules/spreadsheet-import/components/ModalWrapper.tsx index d9de117e24..1b69206fd8 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/components/ModalWrapper.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/components/ModalWrapper.tsx @@ -2,8 +2,8 @@ import styled from '@emotion/styled'; import { MOBILE_VIEWPORT } from 'twenty-ui'; import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal'; -import { Modal } from '@/ui/layout/modal/components/Modal'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import { ModalCloseButton } from './ModalCloseButton'; const StyledModal = styled(Modal)` @@ -16,7 +16,7 @@ const StyledModal = styled(Modal)` min-width: auto; min-height: auto; width: 100%; - height: 100%; + height: 80%; } `; @@ -40,11 +40,15 @@ export const ModalWrapper = ({ const { rtl } = useSpreadsheetImportInternal(); return ( - - - - {children} - - + <> + {isOpen && ( + + + + {children} + + + )} + ); }; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/components/StepNavigationButton.tsx b/packages/twenty-front/src/modules/spreadsheet-import/components/StepNavigationButton.tsx index 85f58d9231..2f09b9f410 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/components/StepNavigationButton.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/components/StepNavigationButton.tsx @@ -2,6 +2,7 @@ import styled from '@emotion/styled'; import { CircularProgressBar } from '@/ui/feedback/progress-bar/components/CircularProgressBar'; import { MainButton } from '@/ui/input/button/components/MainButton'; + import { Modal } from '@/ui/layout/modal/components/Modal'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx index 866ad298e6..666af5c1f4 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx @@ -14,8 +14,8 @@ import { setSubColumn } from '@/spreadsheet-import/utils/setSubColumn'; import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; -import { Modal } from '@/ui/layout/modal/components/Modal'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import { ColumnGrid } from './components/ColumnGrid'; import { TemplateColumn } from './components/TemplateColumn'; import { UserTableColumn } from './components/UserTableColumn'; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectHeaderStep/SelectHeaderStep.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectHeaderStep/SelectHeaderStep.tsx index 6958e32757..a7107cb71b 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectHeaderStep/SelectHeaderStep.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectHeaderStep/SelectHeaderStep.tsx @@ -4,8 +4,8 @@ import { useCallback, useState } from 'react'; import { Heading } from '@/spreadsheet-import/components/Heading'; import { StepNavigationButton } from '@/spreadsheet-import/components/StepNavigationButton'; import { ImportedRow } from '@/spreadsheet-import/types'; -import { Modal } from '@/ui/layout/modal/components/Modal'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import { SelectHeaderTable } from './components/SelectHeaderTable'; const StyledHeading = styled(Heading)` diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectSheetStep/SelectSheetStep.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectSheetStep/SelectSheetStep.tsx index 713b17ff77..58e61ba972 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectSheetStep/SelectSheetStep.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/SelectSheetStep/SelectSheetStep.tsx @@ -1,10 +1,11 @@ -import { useCallback, useState } from 'react'; import styled from '@emotion/styled'; +import { useCallback, useState } from 'react'; import { Heading } from '@/spreadsheet-import/components/Heading'; import { StepNavigationButton } from '@/spreadsheet-import/components/StepNavigationButton'; import { Radio } from '@/ui/input/components/Radio'; import { RadioGroup } from '@/ui/input/components/RadioGroup'; + import { Modal } from '@/ui/layout/modal/components/Modal'; const StyledContent = styled(Modal.Content)` diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/Steps.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/Steps.tsx index d478fc86e9..1b21a981be 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/Steps.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/Steps.tsx @@ -3,10 +3,11 @@ import { MOBILE_VIEWPORT } from 'twenty-ui'; import { useSpreadsheetImportInitialStep } from '@/spreadsheet-import/hooks/useSpreadsheetImportInitialStep'; import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal'; -import { Modal } from '@/ui/layout/modal/components/Modal'; + import { StepBar } from '@/ui/navigation/step-bar/components/StepBar'; import { useStepBar } from '@/ui/navigation/step-bar/hooks/useStepBar'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import { UploadFlow } from './UploadFlow'; const StyledHeader = styled(Modal.Header)` diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadFlow.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadFlow.tsx index ae84f9d794..a74495da4f 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadFlow.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadFlow.tsx @@ -10,8 +10,8 @@ import { mapWorkbook } from '@/spreadsheet-import/utils/mapWorkbook'; import { CircularProgressBar } from '@/ui/feedback/progress-bar/components/CircularProgressBar'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; -import { Modal } from '@/ui/layout/modal/components/Modal'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import { Columns, MatchColumnsStep } from './MatchColumnsStep/MatchColumnsStep'; import { SelectHeaderStep } from './SelectHeaderStep/SelectHeaderStep'; import { SelectSheetStep } from './SelectSheetStep/SelectSheetStep'; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadStep/UploadStep.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadStep/UploadStep.tsx index f0cdc1bb43..54f1a04037 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadStep/UploadStep.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/UploadStep/UploadStep.tsx @@ -1,9 +1,8 @@ -import { useCallback, useState } from 'react'; import styled from '@emotion/styled'; +import { useCallback, useState } from 'react'; import { WorkBook } from 'xlsx-ugnis'; import { Modal } from '@/ui/layout/modal/components/Modal'; - import { DropZone } from './components/DropZone'; const StyledContent = styled(Modal.Content)` diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/ValidationStep.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/ValidationStep.tsx index fb8f15f5d3..2c20ed969c 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/ValidationStep.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/ValidationStep.tsx @@ -20,9 +20,9 @@ import { addErrorsAndRunHooks } from '@/spreadsheet-import/utils/dataMutations'; import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager'; import { Button } from '@/ui/input/button/components/Button'; import { Toggle } from '@/ui/input/components/Toggle'; -import { Modal } from '@/ui/layout/modal/components/Modal'; import { isDefined } from '~/utils/isDefined'; +import { Modal } from '@/ui/layout/modal/components/Modal'; import { generateColumns } from './components/columns'; import { ImportedStructuredRowMetadata } from './types'; diff --git a/packages/twenty-front/src/modules/ui/feedback/dialog-manager/components/Dialog.tsx b/packages/twenty-front/src/modules/ui/feedback/dialog-manager/components/Dialog.tsx index 90e0a4d224..c8e5d05cbd 100644 --- a/packages/twenty-front/src/modules/ui/feedback/dialog-manager/components/Dialog.tsx +++ b/packages/twenty-front/src/modules/ui/feedback/dialog-manager/components/Dialog.tsx @@ -11,7 +11,7 @@ import { DialogHotkeyScope } from '../types/DialogHotkeyScope'; const StyledDialogOverlay = styled(motion.div)` align-items: center; - background: ${({ theme }) => theme.background.overlay}; + background: ${({ theme }) => theme.background.overlayPrimary}; display: flex; height: 100dvh; justify-content: center; diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx index 402b94c51c..67cb20253e 100644 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx +++ b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx @@ -6,6 +6,7 @@ import { useDebouncedCallback } from 'use-debounce'; import { Button, ButtonAccent } from '@/ui/input/button/components/Button'; import { TextInput } from '@/ui/input/components/TextInput'; + import { Modal } from '@/ui/layout/modal/components/Modal'; import { Section, @@ -27,8 +28,8 @@ export type ConfirmationModalProps = { const StyledConfirmationModal = styled(Modal)` border-radius: ${({ theme }) => theme.spacing(1)}; - padding: ${({ theme }) => theme.spacing(6)}; width: calc(400px - ${({ theme }) => theme.spacing(32)}); + height: auto; `; const StyledCenteredButton = styled(Button)` @@ -85,54 +86,57 @@ export const ConfirmationModal = ({ return ( - { - if (isOpen) { - setIsOpen(false); - } - }} - onEnter={onConfirmClick} - > - - - - - {subtitle} - - {confirmationValue && ( -
- -
- )} - setIsOpen(false)} - variant="secondary" - title="Cancel" - fullWidth - /> - { - await onConfirmClick(); - setIsOpen(false); + {isOpen && ( + { + if (isOpen) { + setIsOpen(false); + } }} - variant="secondary" - accent={confirmButtonAccent} - title={deleteButtonText} - disabled={!isValidValue} - fullWidth - dataTestId="confirmation-modal-confirm-button" - /> - + onEnter={onConfirmClick} + isClosable={true} + padding="large" + > + + + + + {subtitle} + + {confirmationValue && ( +
+ +
+ )} + setIsOpen(false)} + variant="secondary" + title="Cancel" + fullWidth + /> + { + await onConfirmClick(); + setIsOpen(false); + }} + variant="secondary" + accent={confirmButtonAccent} + title={deleteButtonText} + disabled={!isValidValue} + fullWidth + dataTestId="confirmation-modal-confirm-button" + /> +
+ )}
); diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx index d9fd4f181c..abd6bb2f05 100644 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx +++ b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx @@ -1,46 +1,183 @@ -import { useEffect, useRef } from 'react'; -import { Key } from 'ts-key-enum'; - -import { - ModalLayout, - ModalLayoutProps, -} from '@/ui/layout/modal/components/ModalLayout'; +import { ModalHotkeyScope } from '@/ui/layout/modal/components/types/ModalHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; - import { useListenClickOutsideV2 } from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2'; -import { ModalHotkeyScope } from './types/ModalHotkeyScope'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import styled from '@emotion/styled'; +import { motion } from 'framer-motion'; +import React, { useEffect, useRef } from 'react'; +import { Key } from 'ts-key-enum'; -type ModalProps = ModalLayoutProps & { - isOpen?: boolean; +const StyledModalDiv = styled(motion.div)<{ + size?: ModalSize; + padding?: ModalPadding; + isMobile: boolean; +}>` + display: flex; + flex-direction: column; + background: ${({ theme }) => theme.background.primary}; + color: ${({ theme }) => theme.font.color.primary}; + border-radius: ${({ theme, isMobile }) => { + if (isMobile) return `0`; + return theme.border.radius.md; + }}; + overflow: hidden; + z-index: 10000; // should be higher than Backdrop's z-index + + width: ${({ isMobile, size, theme }) => { + if (isMobile) return theme.modal.size.fullscreen; + switch (size) { + case 'small': + return theme.modal.size.sm; + case 'medium': + return theme.modal.size.md; + case 'large': + return theme.modal.size.lg; + default: + return 'auto'; + } + }}; + + padding: ${({ padding, theme }) => { + switch (padding) { + case 'none': + return theme.spacing(0); + case 'small': + return theme.spacing(2); + case 'medium': + return theme.spacing(4); + case 'large': + return theme.spacing(6); + default: + return 'auto'; + } + }}; + height: ${({ isMobile, theme }) => + isMobile ? theme.modal.size.fullscreen : 'auto'}; + max-height: ${({ isMobile }) => (isMobile ? 'none' : '90dvh')}; +`; + +const StyledHeader = styled.div` + align-items: center; + display: flex; + flex-direction: row; + height: 60px; + overflow: hidden; + padding: ${({ theme }) => theme.spacing(5)}; +`; + +const StyledContent = styled.div` + display: flex; + flex: 1; + flex: 1 1 0%; + flex-direction: column; + overflow-y: auto; + padding: ${({ theme }) => theme.spacing(10)}; +`; + +const StyledFooter = styled.div` + align-items: center; + display: flex; + flex-direction: row; + height: 60px; + overflow: hidden; + padding: ${({ theme }) => theme.spacing(5)}; +`; + +const StyledBackDrop = styled(motion.div)<{ + modalVariant: ModalVariants; +}>` + align-items: center; + background: ${({ theme, modalVariant }) => + modalVariant === 'primary' + ? theme.background.overlayPrimary + : theme.background.overlaySecondary}; + display: flex; + height: 100%; + justify-content: center; + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 9999; + user-select: none; +`; + +type ModalHeaderProps = React.PropsWithChildren & { + className?: string; +}; + +const ModalHeader = ({ children, className }: ModalHeaderProps) => ( + {children} +); + +type ModalContentProps = React.PropsWithChildren & { + className?: string; +}; + +const ModalContent = ({ children, className }: ModalContentProps) => ( + {children} +); + +type ModalFooterProps = React.PropsWithChildren & { + className?: string; +}; + +const ModalFooter = ({ children, className }: ModalFooterProps) => ( + {children} +); + +export type ModalSize = 'small' | 'medium' | 'large'; +export type ModalPadding = 'none' | 'small' | 'medium' | 'large'; +export type ModalVariants = 'primary' | 'secondary'; + +export type ModalProps = React.PropsWithChildren & { + size?: ModalSize; + padding?: ModalPadding; + className?: string; hotkeyScope?: ModalHotkeyScope; - onClose?: () => void; onEnter?: () => void; + modalVariant?: ModalVariants; +} & ( + | { isClosable: true; onClose: () => void } + | { isClosable?: false; onClose?: never } + ); + +const modalAnimation = { + hidden: { opacity: 0 }, + visible: { opacity: 1 }, + exit: { opacity: 0 }, }; export const Modal = ({ - isOpen = false, children, - onClose, - hotkeyScope = ModalHotkeyScope.Default, - onEnter, size = 'medium', padding = 'medium', className, + hotkeyScope = ModalHotkeyScope.Default, + onEnter, + isClosable = false, + onClose, + modalVariant = 'primary', }: ModalProps) => { + const isMobile = useIsMobile(); + const modalRef = useRef(null); + const { goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope, } = usePreviousHotkeyScope(); - useScopedHotkeys( - [Key.Escape], - () => { - onClose?.(); - }, + useEffect(() => { + setHotkeyScopeAndMemorizePreviousScope(hotkeyScope); + return () => { + goBackToPreviousHotkeyScope(); + }; + }, [ hotkeyScope, - [onClose], - ); + setHotkeyScopeAndMemorizePreviousScope, + goBackToPreviousHotkeyScope, + ]); useScopedHotkeys( [Key.Enter], @@ -50,41 +187,53 @@ export const Modal = ({ hotkeyScope, ); - useEffect(() => { - if (isOpen) { - setHotkeyScopeAndMemorizePreviousScope(hotkeyScope); - } else { - goBackToPreviousHotkeyScope(); - } - }, [ - goBackToPreviousHotkeyScope, + useScopedHotkeys( + [Key.Escape], + () => { + if (isClosable && onClose !== undefined) { + onClose(); + } + }, hotkeyScope, - isOpen, - setHotkeyScopeAndMemorizePreviousScope, - ]); - - const modalRef = useRef(null); + ); useListenClickOutsideV2({ refs: [modalRef], listenerId: 'MODAL_CLICK_OUTSIDE_LISTENER_ID', - callback: () => onClose?.(), + callback: () => { + if (isClosable && onClose !== undefined) { + onClose(); + } + }, }); - return isOpen ? ( - { + e.stopPropagation(); + }; + + return ( + - {children} - - ) : ( - <> + + {children} + + ); }; -Modal.Header = ModalLayout.Header; -Modal.Content = ModalLayout.Content; -Modal.Footer = ModalLayout.Footer; +Modal.Header = ModalHeader; +Modal.Content = ModalContent; +Modal.Footer = ModalFooter; diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/ModalLayout.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/ModalLayout.tsx deleted file mode 100644 index d11c6be921..0000000000 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/ModalLayout.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import React from 'react'; -import styled from '@emotion/styled'; -import { motion } from 'framer-motion'; - -const StyledModalDiv = styled(motion.div)<{ - size?: ModalSize; - padding?: ModalPadding; -}>` - display: flex; - flex-direction: column; - background: ${({ theme }) => theme.background.primary}; - color: ${({ theme }) => theme.font.color.primary}; - border-radius: ${({ theme }) => theme.border.radius.md}; - overflow: hidden; - max-height: 90vh; - z-index: 10000; // should be higher than Backdrop's z-index - - width: ${({ size, theme }) => { - switch (size) { - case 'small': - return theme.modal.size.sm; - case 'medium': - return theme.modal.size.md; - case 'large': - return theme.modal.size.lg; - default: - return 'auto'; - } - }}; - - padding: ${({ padding, theme }) => { - switch (padding) { - case 'none': - return theme.spacing(0); - case 'small': - return theme.spacing(2); - case 'medium': - return theme.spacing(4); - case 'large': - return theme.spacing(6); - default: - return 'auto'; - } - }}; -`; - -const StyledHeader = styled.div` - align-items: center; - display: flex; - flex-direction: row; - height: 60px; - overflow: hidden; - padding: ${({ theme }) => theme.spacing(5)}; -`; - -const StyledContent = styled.div` - display: flex; - flex: 1; - flex: 1 1 0%; - flex-direction: column; - overflow-y: auto; - padding: ${({ theme }) => theme.spacing(10)}; -`; - -const StyledFooter = styled.div` - align-items: center; - display: flex; - flex-direction: row; - height: 60px; - overflow: hidden; - padding: ${({ theme }) => theme.spacing(5)}; -`; - -const StyledBackDrop = styled(motion.div)` - align-items: center; - background: ${({ theme }) => theme.background.overlay}; - display: flex; - height: 100%; - justify-content: center; - left: 0; - position: fixed; - top: 0; - width: 100%; - z-index: 9999; - user-select: none; -`; - -/** - * Modal components - */ -type ModalLayoutHeaderProps = React.PropsWithChildren & { - className?: string; -}; - -const ModalLayoutHeader = ({ children, className }: ModalLayoutHeaderProps) => ( - {children} -); - -type ModalLayoutContentProps = React.PropsWithChildren & { - className?: string; -}; - -const ModalLayoutContent = ({ - children, - className, -}: ModalLayoutContentProps) => ( - {children} -); - -type ModalLayoutFooterProps = React.PropsWithChildren & { - className?: string; -}; - -const ModalLayoutFooter = ({ children, className }: ModalLayoutFooterProps) => ( - {children} -); - -/** - * Modal - */ -export type ModalSize = 'small' | 'medium' | 'large'; -export type ModalPadding = 'none' | 'small' | 'medium' | 'large'; - -export type ModalLayoutProps = React.PropsWithChildren & { - size?: ModalSize; - padding?: ModalPadding; - className?: string; - modalRef?: React.RefObject; -}; - -const modalVariants = { - hidden: { opacity: 0 }, - visible: { opacity: 1 }, - exit: { opacity: 0 }, -}; - -// This component should be used over Modal when seeking a modal feel without modal state (hotkeyScope etc) -export const ModalLayout = ({ - children, - size = 'medium', - padding = 'medium', - modalRef, - className, -}: ModalLayoutProps) => { - const stopEventPropagation = (e: React.MouseEvent) => { - e.stopPropagation(); - }; - - return ( - - - {children} - - - ); -}; - -ModalLayout.Header = ModalLayoutHeader; -ModalLayout.Content = ModalLayoutContent; -ModalLayout.Footer = ModalLayoutFooter; diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/Modal.stories.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/Modal.stories.tsx index d27d09f2b6..919bf33d47 100644 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/Modal.stories.tsx +++ b/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/Modal.stories.tsx @@ -2,7 +2,6 @@ import { Meta, StoryObj } from '@storybook/react'; import { ComponentDecorator } from 'twenty-ui'; import { Modal } from '../Modal'; -import { ModalHotkeyScope } from '../types/ModalHotkeyScope'; const meta: Meta = { title: 'UI/Layout/Modal/Modal', @@ -14,10 +13,8 @@ type Story = StoryObj; export const Default: Story = { args: { - isOpen: true, size: 'medium', padding: 'medium', - hotkeyScope: ModalHotkeyScope.Default, children: ( <> Stay in touch diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ModalLayout.stories.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ModalLayout.stories.tsx deleted file mode 100644 index 538c7b2992..0000000000 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ModalLayout.stories.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; -import { ComponentDecorator } from 'twenty-ui'; - -import { ModalLayout } from '@/ui/layout/modal/components/ModalLayout'; - -const meta: Meta = { - title: 'UI/Layout/Modal/ModalLayout', - component: ModalLayout, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - size: 'medium', - padding: 'medium', - children: ( - <> - Stay in touch - - This is a dummy newletter form so don't bother trying to test it. Not - that I expect you to, anyways. :) - - - By using Twenty, you're opting for the finest CRM experience you'll - ever encounter. - - - ), - }, - decorators: [ComponentDecorator], - argTypes: { - children: { control: false }, - }, -}; diff --git a/packages/twenty-front/src/modules/ui/layout/page/DefaultLayout.tsx b/packages/twenty-front/src/modules/ui/layout/page/DefaultLayout.tsx index a41e791424..4108f6a5ce 100644 --- a/packages/twenty-front/src/modules/ui/layout/page/DefaultLayout.tsx +++ b/packages/twenty-front/src/modules/ui/layout/page/DefaultLayout.tsx @@ -2,8 +2,6 @@ import { css, Global, useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { AnimatePresence, LayoutGroup, motion } from 'framer-motion'; import { Outlet } from 'react-router-dom'; - -import { AuthModal } from '@/auth/components/Modal'; import { CommandMenu } from '@/command-menu/components/CommandMenu'; import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary'; import { KeyboardShortcutMenu } from '@/keyboard-shortcut-menu/components/KeyboardShortcutMenu'; @@ -16,6 +14,7 @@ import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal'; import { DESKTOP_NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/DesktopNavDrawerWidths'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useScreenSize } from '@/ui/utilities/screen-size/hooks/useScreenSize'; +import { AuthModal } from '@/auth/components/AuthModal'; const StyledLayout = styled.div` background: ${({ theme }) => theme.background.noisy}; diff --git a/packages/twenty-ui/src/theme/constants/BackgroundDark.ts b/packages/twenty-ui/src/theme/constants/BackgroundDark.ts index df00ccf90b..b594cb842b 100644 --- a/packages/twenty-ui/src/theme/constants/BackgroundDark.ts +++ b/packages/twenty-ui/src/theme/constants/BackgroundDark.ts @@ -23,7 +23,8 @@ export const BACKGROUND_DARK = { lighter: RGBA(GRAY_SCALE.gray0, 0.03), danger: RGBA(COLOR.red, 0.08), }, - overlay: RGBA(GRAY_SCALE.gray80, 0.8), + overlayPrimary: RGBA(GRAY_SCALE.gray80, 0.8), + overlaySecondary: RGBA(GRAY_SCALE.gray80, 0.4), radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`, radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`, primaryInverted: GRAY_SCALE.gray20, diff --git a/packages/twenty-ui/src/theme/constants/BackgroundLight.ts b/packages/twenty-ui/src/theme/constants/BackgroundLight.ts index 82f1eccbf7..187ecf7de8 100644 --- a/packages/twenty-ui/src/theme/constants/BackgroundLight.ts +++ b/packages/twenty-ui/src/theme/constants/BackgroundLight.ts @@ -23,7 +23,8 @@ export const BACKGROUND_LIGHT = { lighter: RGBA(GRAY_SCALE.gray100, 0.02), danger: RGBA(COLOR.red, 0.08), }, - overlay: RGBA(GRAY_SCALE.gray80, 0.8), + overlayPrimary: RGBA(GRAY_SCALE.gray80, 0.8), + overlaySecondary: RGBA(GRAY_SCALE.gray80, 0.4), radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`, radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`, primaryInverted: GRAY_SCALE.gray60, diff --git a/packages/twenty-ui/src/theme/constants/Modal.ts b/packages/twenty-ui/src/theme/constants/Modal.ts index 2a53265cc0..f72880127e 100644 --- a/packages/twenty-ui/src/theme/constants/Modal.ts +++ b/packages/twenty-ui/src/theme/constants/Modal.ts @@ -3,5 +3,6 @@ export const MODAL = { sm: '300px', md: '400px', lg: '53%', + fullscreen: `100dvh`, }, };