diff --git a/src/organisms/Modals/Modal/Modal.test.tsx b/src/organisms/Modals/Modal/Modal.test.tsx index 0cc4bb7ee..cdaf95130 100644 --- a/src/organisms/Modals/Modal/Modal.test.tsx +++ b/src/organisms/Modals/Modal/Modal.test.tsx @@ -130,6 +130,24 @@ describe('Modal Component', () => { const modalContent = screen.getByRole('dialog') expect(modalContent).toBeInTheDocument() }) + + it('applies custom size props when provided', () => { + renderWithChakra( + + ) + + const modalContent = screen.getByRole('dialog') + expect(modalContent).toHaveStyle('min-width: 700px') + expect(modalContent).toHaveStyle('max-width: 80vw') + expect(modalContent).toHaveStyle('min-height: 320px') + expect(modalContent).toHaveStyle('max-height: 80vh') + }) }) describe('Responsive Behavior', () => { diff --git a/src/organisms/Modals/Modal/Modal.tsx b/src/organisms/Modals/Modal/Modal.tsx index 212bfcba3..94c4ed4b2 100644 --- a/src/organisms/Modals/Modal/Modal.tsx +++ b/src/organisms/Modals/Modal/Modal.tsx @@ -21,6 +21,10 @@ export const Modal = ({ scrollBehavior = 'outside', fixedButtons = false, autoFocus = false, + minWidth, + maxWidth, + minHeight, + maxHeight, }: IModal): JSX.Element => { const isInside = scrollBehavior === 'inside' || fixedButtons @@ -29,6 +33,10 @@ export const Modal = ({ scrollBehavior, fixedButtons, withoutMargin, + minWidth, + maxWidth, + minHeight, + maxHeight, }) return ( diff --git a/src/organisms/Modals/Modal/ModalSimple.test.tsx b/src/organisms/Modals/Modal/ModalSimple.test.tsx index 7b34209e5..4d6734550 100644 --- a/src/organisms/Modals/Modal/ModalSimple.test.tsx +++ b/src/organisms/Modals/Modal/ModalSimple.test.tsx @@ -4,6 +4,14 @@ import userEvent from '@testing-library/user-event' import { ModalSimple } from './ModalSimple' +jest.mock('@chakra-ui/react', () => { + const originalModule = jest.requireActual('@chakra-ui/react') + return { + ...originalModule, + useMediaQuery: jest.fn(() => [false]), + } +}) + const renderWithChakra = (ui: React.ReactElement): any => { return render({ui}) } @@ -58,4 +66,15 @@ describe('ModalSimple Component', () => { expect(screen.getByTestId('modal-simple-content')).toBeInTheDocument() expect(screen.getByText('Simple content')).toBeInTheDocument() }) + + it('renders in compact mode on mobile when mobileCompact is true', () => { + renderWithChakra( + +
Simple content
+
+ ) + + expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByText('Simple content')).toBeInTheDocument() + }) }) diff --git a/src/organisms/Modals/Modal/ModalSimple.tsx b/src/organisms/Modals/Modal/ModalSimple.tsx index ace6b56da..532104bef 100644 --- a/src/organisms/Modals/Modal/ModalSimple.tsx +++ b/src/organisms/Modals/Modal/ModalSimple.tsx @@ -17,12 +17,14 @@ export const ModalSimple = ({ closeOnOverlayClick = true, closeOnEsc, withoutMargin = false, + mobileCompact = false, }: IModalSimple): JSX.Element => { const modalConfig = useModalConfig({ closeOnOverlayClick, scrollBehavior: 'outside', fixedButtons: false, withoutMargin, + mobileCompact, }) return ( @@ -33,6 +35,7 @@ export const ModalSimple = ({ motionPreset="scale" onClose={onClose} scrollBehavior="outside" + isCentered={mobileCompact} blockScrollOnMount={false} > diff --git a/src/organisms/Modals/Modal/useModalConfig.ts b/src/organisms/Modals/Modal/useModalConfig.ts index 7114eeed9..1592441e9 100644 --- a/src/organisms/Modals/Modal/useModalConfig.ts +++ b/src/organisms/Modals/Modal/useModalConfig.ts @@ -14,6 +14,11 @@ interface UseModalConfigParams { scrollBehavior: 'outside' | 'inside' fixedButtons: boolean withoutMargin: boolean + minWidth?: string | number + maxWidth?: string | number + minHeight?: string | number + maxHeight?: string | number + mobileCompact?: boolean } export const useModalConfig = ({ @@ -21,30 +26,53 @@ export const useModalConfig = ({ scrollBehavior, fixedButtons, withoutMargin, + minWidth, + maxWidth, + minHeight, + maxHeight, + mobileCompact = false, }: UseModalConfigParams): ModalConfig => { const [isDesktop] = useMediaQuery(`(min-width: ${uiKitModalIsDesktop}px)`) // fixedButtons requiere scroll interno const isInsideScroll = scrollBehavior === 'inside' const shouldForceInsideScroll = fixedButtons + const desktopMinWidth = minWidth ?? '690px' + const desktopMaxWidth = maxWidth ?? '690px' + const desktopMinHeight = minHeight ?? '300px' + const insideMaxHeight = maxHeight ?? 'calc(100% - 96px)' + const outsideMaxHeight = maxHeight ?? 'auto' + const compactMobileWidth = maxWidth ?? 'calc(100vw - 32px)' + const compactMobileMaxWidth = maxWidth ?? '375px' + const compactMobileMaxHeight = maxHeight ?? 'calc(100dvh - 32px)' const isInside = isInsideScroll || shouldForceInsideScroll return { closeOnOverlayClick, closeOnEsc: closeOnOverlayClick, scrollBehavior: isInside ? 'inside' : 'outside', contentProps: { - maxH: isInside ? '100dvh' : 'auto', - minH: isDesktop ? '300px' : '100dvh', + maxH: isInside + ? maxHeight ?? '100%' + : mobileCompact && !isDesktop + ? compactMobileMaxHeight + : outsideMaxHeight, + minH: isDesktop ? desktopMinHeight : mobileCompact ? 'auto' : '100%', padding: 0, - width: '100%', + width: isDesktop ? 'fit-content' : mobileCompact ? compactMobileWidth : '100%', animation: 'none', sx: { bgColor: vars('colors-neutral-white'), - borderRadius: isDesktop ? '8px' : 0, - mt: isDesktop ? '48px' : 0, - mb: isDesktop ? '48px' : 0, - marginX: isDesktop ? 'auto' : 0, - maxH: isInside ? 'calc(100dvh - 96px)' : 'auto', - maxWidth: isDesktop ? '690px' : '100%', + borderRadius: isDesktop ? '8px' : mobileCompact ? '10px' : 0, + mt: isDesktop ? '48px' : mobileCompact ? 'auto' : 0, + mb: isDesktop ? '48px' : mobileCompact ? 'auto' : 0, + marginX: isDesktop ? 'auto' : mobileCompact ? 'auto' : 0, + maxH: isInside + ? insideMaxHeight + : mobileCompact && !isDesktop + ? compactMobileMaxHeight + : outsideMaxHeight, + minWidth: isDesktop ? desktopMinWidth : mobileCompact ? 'auto' : undefined, + maxWidth: isDesktop ? desktopMaxWidth : mobileCompact ? compactMobileMaxWidth : '100%', + overflow: mobileCompact && !isDesktop ? 'hidden' : undefined, ...(fixedButtons && { '.uikit-modalContent': { diff --git a/src/organisms/Modals/ModalAlert/useModalAlertConfig.ts b/src/organisms/Modals/ModalAlert/useModalAlertConfig.ts index 50a96e372..c5cceeb90 100644 --- a/src/organisms/Modals/ModalAlert/useModalAlertConfig.ts +++ b/src/organisms/Modals/ModalAlert/useModalAlertConfig.ts @@ -21,7 +21,7 @@ export const useModalAlertConfig = (): ModalConfig => { p: 0, m: '10vh auto 0', sx: { - maxWidth: isDesktop ? '589px' : '343px', + maxWidth: isDesktop ? '589px' : 'calc(100vw - 32px)', }, }, } diff --git a/src/organisms/Modals/ModalMultiple/ModalMultiple.tsx b/src/organisms/Modals/ModalMultiple/ModalMultiple.tsx index 5ff5c41f1..2a08d7f24 100644 --- a/src/organisms/Modals/ModalMultiple/ModalMultiple.tsx +++ b/src/organisms/Modals/ModalMultiple/ModalMultiple.tsx @@ -15,6 +15,10 @@ export interface ModalDefaultProps { withoutMargin?: IModal['withoutMargin'] scrollBehavior?: IModal['scrollBehavior'] fixedButtons?: IModal['fixedButtons'] + minWidth?: IModal['minWidth'] + maxWidth?: IModal['maxWidth'] + minHeight?: IModal['minHeight'] + maxHeight?: IModal['maxHeight'] } type BaseProps = ModalDefaultProps & { @@ -88,6 +92,10 @@ export const ModalMultiple = (props: ModalMultipleProps): JSX.Element => { withoutMargin = false, scrollBehavior = 'outside', fixedButtons = false, + minWidth, + maxWidth, + minHeight, + maxHeight, } = props const modalConfig = useModalMultipleConfig({ @@ -96,6 +104,10 @@ export const ModalMultiple = (props: ModalMultipleProps): JSX.Element => { scrollBehavior, fixedButtons, withoutMargin, + minWidth, + maxWidth, + minHeight, + maxHeight, }) const renderContent = (): JSX.Element | null => { diff --git a/src/organisms/Modals/ModalMultiple/useModalMultipleConfig.ts b/src/organisms/Modals/ModalMultiple/useModalMultipleConfig.ts index 1d5f92cb6..695bce96a 100644 --- a/src/organisms/Modals/ModalMultiple/useModalMultipleConfig.ts +++ b/src/organisms/Modals/ModalMultiple/useModalMultipleConfig.ts @@ -17,6 +17,10 @@ interface UseModalMultipleConfigParams { scrollBehavior: 'outside' | 'inside' fixedButtons: boolean withoutMargin: boolean + minWidth?: string | number + maxWidth?: string | number + minHeight?: string | number + maxHeight?: string | number } export const useModalMultipleConfig = ({ @@ -25,12 +29,20 @@ export const useModalMultipleConfig = ({ scrollBehavior, fixedButtons, withoutMargin, + minWidth, + maxWidth, + minHeight, + maxHeight, }: UseModalMultipleConfigParams): ModalConfig => { const modalConfig = useModalConfig({ closeOnOverlayClick, scrollBehavior, fixedButtons, withoutMargin, + minWidth, + maxWidth, + minHeight, + maxHeight, }) const modalAlertConfig = useModalAlertConfig() diff --git a/src/organisms/Modals/types.d.ts b/src/organisms/Modals/types.d.ts index 70784020f..c87b53862 100644 --- a/src/organisms/Modals/types.d.ts +++ b/src/organisms/Modals/types.d.ts @@ -14,6 +14,10 @@ export interface IModal { /** Si esta activo se fija el footer */ fixedButtons?: boolean autoFocus?: boolean + minWidth?: string | number + maxWidth?: string | number + minHeight?: string | number + maxHeight?: string | number } export interface IModalSimple { @@ -23,6 +27,8 @@ export interface IModalSimple { isOpen: boolean onClose: () => void withoutMargin?: boolean + /** Si está activo en mobile se comporta como una tarjeta compacta centrada */ + mobileCompact?: boolean } export interface IModalCard {