diff --git a/packages/vkui/src/components/AppRoot/ScrollContext.tsx b/packages/vkui/src/components/AppRoot/ScrollContext.tsx index 48e9c103450..3e148463661 100644 --- a/packages/vkui/src/components/AppRoot/ScrollContext.tsx +++ b/packages/vkui/src/components/AppRoot/ScrollContext.tsx @@ -13,6 +13,7 @@ const clearDisableScrollStyle = (node: HTMLElement) => { top: '', left: '', right: '', + overscrollBehavior: '', overflowY: '', overflowX: '', }); @@ -117,11 +118,13 @@ export const GlobalScrollController = ({ children }: ScrollControllerProps): Rea const overflowY = window!.innerWidth > document!.documentElement.clientWidth ? 'scroll' : ''; const overflowX = window!.innerHeight > document!.documentElement.clientHeight ? 'scroll' : ''; + document!.documentElement.style.setProperty('overscroll-behavior', 'none'); Object.assign(document!.body.style, { position: 'fixed', top: `-${scrollY}px`, left: `-${scrollX}px`, right: '0', + overscrollBehavior: 'none', overflowY, overflowX, }); @@ -131,6 +134,7 @@ export const GlobalScrollController = ({ children }: ScrollControllerProps): Rea const scrollY = document!.body.style.top; const scrollX = document!.body.style.left; + document!.documentElement.style.removeProperty('overscroll-behavior'); clearDisableScrollStyle(document!.body); window!.scrollTo(-parseInt(scrollX || '0'), -parseInt(scrollY || '0')); }, [document, window]); diff --git a/packages/vkui/src/components/ModalCard/ModalCard.e2e-playground.tsx b/packages/vkui/src/components/ModalCard/ModalCard.e2e-playground.tsx index 00b576a1487..7fb8bd9b637 100644 --- a/packages/vkui/src/components/ModalCard/ModalCard.e2e-playground.tsx +++ b/packages/vkui/src/components/ModalCard/ModalCard.e2e-playground.tsx @@ -9,7 +9,7 @@ import { import { Button } from '../Button/Button'; import { ButtonGroup } from '../ButtonGroup/ButtonGroup'; import { Image } from '../Image/Image'; -import { ModalRoot } from '../ModalRoot/ModalRootAdaptive'; +import { ModalRoot } from '../ModalRoot/ModalRoot'; import { Spacing } from '../Spacing/Spacing'; import { Textarea } from '../Textarea/Textarea'; import { UsersStack } from '../UsersStack/UsersStack'; diff --git a/packages/vkui/src/components/ModalCard/ModalCard.module.css b/packages/vkui/src/components/ModalCard/ModalCard.module.css index a421a005080..ce0c5b046f5 100644 --- a/packages/vkui/src/components/ModalCard/ModalCard.module.css +++ b/packages/vkui/src/components/ModalCard/ModalCard.module.css @@ -1,65 +1,82 @@ .host { - box-sizing: border-box; - position: absolute; - inset-block-start: 0; - padding: 8px; - inset-inline-start: 0; + padding: var(--vkui--spacing_size_m); + margin-inline: auto; inline-size: 100%; - block-size: 100%; - display: flex; - align-items: flex-end; + box-sizing: border-box; } .host:focus { outline: none; } -.in { - inline-size: 100%; - margin-inline: auto; - transform: translateY(calc(100% + 16px)); - transition: transform 340ms var(--vkui--animation_easing_platform); +.hostMaxWidthS { + max-inline-size: 400px; } -/** - * iOS - */ - -.ios .in { +.hostMaxWidthM { max-inline-size: 414px; } -/** - * Android + vkcom - */ - -.android .in { +.hostMaxWidthL { max-inline-size: 440px; } -.vkcom .in { - max-inline-size: 400px; -} +/* Mobile */ +@media (--viewWidth-smallTabletMinus) { + .host { + --vkui_internal_ModalCard--snapPoint: 100%; + --vkui_internal_ModalCard--safeAreaInsetBottom: var(--vkui_internal--safe_area_inset_bottom); -/** - * Desktop - */ + position: absolute; + inset-inline: 0; + inset-block-end: 0; + margin-block-end: var(--vkui_internal_ModalCard--safeAreaInsetBottom); + transform: translate3d(0, calc(100% - var(--vkui_internal_ModalCard--snapPoint)), 0); + transition: transform var(--vkui--animation_duration_l) var(--vkui--animation_easing_platform); + } -.desktop { - align-items: center; -} + .hostStateEnter { + transform: translate3d(0, 100%, 0); + transition-property: none; + } + + .hostStateEntering { + transition-property: transform; + transition-delay: 0.2s; + } -.desktop .in { - transform: unset; - opacity: 0; - transition: opacity 340ms var(--vkui--animation_easing_platform); + .hostStateExiting { + transform: translate3d(0, 100%, 0); + transition-property: transform; + } + + .hostStateExited { + transform: translate3d(0, 100%, 0); + transition-property: transform; + } } +/* Desktop */ +@media (--viewWidth-smallTabletPlus) { + .host { + margin-block: auto; + opacity: 1; + transition: opacity 340ms var(--vkui--animation_easing_platform); + } + + .hostStateEnter { + opacity: 0; + transition-property: none; + } + + .hostStateEntering { + opacity: 1; + } + + .hostStateExiting { + opacity: 0; + } -/** - * CMP: - * ModalRoot - */ -/* stylelint-disable-next-line selector-pseudo-class-disallowed-list */ -:global(.vkuiInternalModalRoot--touched) .in { - transition: none; + .hostStateExited { + opacity: 0; + } } diff --git a/packages/vkui/src/components/ModalCard/ModalCard.stories.tsx b/packages/vkui/src/components/ModalCard/ModalCard.stories.tsx index f5af257b3b5..9e6c75371bd 100644 --- a/packages/vkui/src/components/ModalCard/ModalCard.stories.tsx +++ b/packages/vkui/src/components/ModalCard/ModalCard.stories.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Icon56MoneyTransferOutline, Icon56NotificationOutline } from '@vkontakte/icons'; -import { ModalWrapper } from '../../storybook/ModalWrapper'; import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; import { getAvatarUrl } from '../../testing/mock'; import { Avatar } from '../Avatar/Avatar'; @@ -23,17 +22,14 @@ export default story; type Story = StoryObj; -const MODAL_CARD_MONEY_SEND = 'money-send'; -const MODAL_CARD_APP_TO_MENU = 'app-to-menu'; -const MODAL_CARD_ABOUT = 'say-about'; -const MODAL_CARD_NOTIFICATIONS = 'notifications'; -const MODAL_CARD_CHAT_INVITE = 'chat-invite'; - export const SimpleCard: Story = { - render: () => ( - + render: function Render() { + const [open, setOpen] = React.useState(true); + const handleClose = () => setOpen(false); + return ( } title="Отправляйте деньги друзьям, используя банковскую карту" description="Номер карты получателя не нужен — он сам решит, куда зачислить средства." @@ -43,15 +39,18 @@ export const SimpleCard: Story = { } /> - - ), + ); + }, }; export const CardWithAvatar: Story = { - render: () => ( - + render: function Render() { + const [open, setOpen] = React.useState(true); + const handleClose = () => setOpen(false); + return ( } title="Добавить игру «Загадки детства» в меню?" description="Игра появится под списком разделов на экране меню и будет всегда под рукой." @@ -61,15 +60,18 @@ export const CardWithAvatar: Story = { } /> - - ), + ); + }, }; export const CardWithTextArea: Story = { - render: () => ( - + render: function Render() { + const [open, setOpen] = React.useState(true); + const handleClose = () => setOpen(false); + return ( @@ -79,15 +81,18 @@ export const CardWithTextArea: Story = { >