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 f40de47cf..0bef31d15 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 d9de117e2..1b69206fd 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 85f58d923..2f09b9f41 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 866ad298e..666af5c1f 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 6958e3275..a7107cb71 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 713b17ff7..58e61ba97 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 d478fc86e..1b21a981b 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 ae84f9d79..a74495da4 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 f0cdc1bb4..54f1a0403 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 fb8f15f5d..2c20ed969 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 90e0a4d22..c8e5d05cb 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 402b94c51..67cb20253 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 d9fd4f181..abd6bb2f0 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 d11c6be92..000000000 --- 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 d27d09f2b..919bf33d4 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 538c7b299..000000000 --- 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 a41e79142..4108f6a5c 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 df00ccf90..b594cb842 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 82f1eccbf..187ecf7de 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 2a53265cc..f72880127 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`, }, };