Skip to content

Commit

Permalink
refactor: update ModalRoot/ModalPage/ModalCard
Browse files Browse the repository at this point in the history
  • Loading branch information
inomdzhon committed Nov 8, 2024
1 parent d293080 commit 2aeae94
Show file tree
Hide file tree
Showing 69 changed files with 2,682 additions and 3,154 deletions.
2 changes: 1 addition & 1 deletion packages/vkui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"test:e2e-update": "../../scripts/generate_env_docker.sh -u && docker compose --env-file=./.env.docker up --abort-on-container-exit",
"test:e2e:ci": "yarn run -T playwright test --config playwright-ct.config.ts",
"test:e2e-update:ci": "yarn run test:e2e:ci --update-snapshots",
"lint:generated-files": "yarn run -T tsc scripts/generateCSSCustomMedias.mjs --checkJs --module ESNext --moduleResolution node --resolveJsonModule --allowSyntheticDefaultImports --noEmit && yarn run generate:css-custom-medias && git diff --exit-code src/styles/customMedias.generated.css",
"lint:generated-files": "yarn run -T tsc scripts/generateCSSCustomMedias.mjs --checkJs --module ESNext --moduleResolution node --resolveJsonModule --allowSyntheticDefaultImports --jsx react-jsx --noEmit && yarn run generate:css-custom-medias && git diff --exit-code src/styles/customMedias.generated.css",
"storybook": "bash -c 'source .env && yarn run -T cross-env SANDBOX=\\.storybook storybook dev -p ${STORYBOOK_DEV_PORT:=6006}'",
"storybook:build": "yarn run -T cross-env SANDBOX=\\.storybook FROM_STORYBOOK=1 storybook build",
"generate:css-custom-medias": "node scripts/generateCSSCustomMedias.mjs"
Expand Down
12 changes: 3 additions & 9 deletions packages/vkui/src/components/Group/Group.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { render, screen } from '@testing-library/react';
import { classNames, noop } from '@vkontakte/vkjs';
import { ModalContext } from '../../context/ModalContext';
import type { SizeTypeValues } from '../../lib/adaptivity';
import { baselineComponent } from '../../testing/utils';
import { AdaptivityContext } from '../AdaptivityProvider/AdaptivityContext';
Expand All @@ -8,7 +9,6 @@ import {
type AppRootContextInterface,
DEFAULT_APP_ROOT_CONTEXT_VALUE,
} from '../AppRoot/AppRootContext';
import { ModalRootContext } from '../ModalRoot/ModalRootContext';
import { Group, type GroupProps } from './Group';
import styles from './Group.module.css';

Expand Down Expand Up @@ -75,17 +75,11 @@ describe('Group', () => {
}}
>
<AdaptivityContext.Provider value={{ sizeX }}>
<ModalRootContext.Provider
value={{
isInsideModal,
updateModalHeight: noop,
registerModal: noop,
}}
>
<ModalContext.Provider value={isInsideModal ? 'test' : null}>
<Group mode={mode} data-testid="group">
<div />
</Group>
</ModalRootContext.Provider>
</ModalContext.Provider>
</AdaptivityContext.Provider>
</AppRootContext.Provider>,
);
Expand Down
4 changes: 2 additions & 2 deletions packages/vkui/src/components/Group/GroupContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { useModalContext } from '../../context/ModalContext';
import { useAdaptivity } from '../../hooks/useAdaptivity';
import type { SizeTypeValues } from '../../lib/adaptivity';
import { warnOnce } from '../../lib/warnOnce';
import type { HasComponent, HTMLAttributesWithRootRef } from '../../types';
import { AppRootContext } from '../AppRoot/AppRootContext';
import { ModalRootContext } from '../ModalRoot/ModalRootContext';
import { RootComponent } from '../RootComponent/RootComponent';
import styles from './Group.module.css';

Expand Down Expand Up @@ -90,7 +90,7 @@ export const GroupContainer: React.FC<GroupContainerProps> = ({
tabIndex: tabIndexProp,
...restProps
}: GroupContainerProps) => {
const { isInsideModal } = React.useContext(ModalRootContext);
const isInsideModal = useModalContext().id !== null;
const { sizeX = 'none' } = useAdaptivity();

const mode = useGroupMode(modeProps, sizeX, isInsideModal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import {
import { Button } from '../Button/Button';
import { ButtonGroup } from '../ButtonGroup/ButtonGroup';
import { Image } from '../Image/Image';
import { ModalRoot } from '../ModalRoot/ModalRootAdaptive';
import { Spacing } from '../Spacing/Spacing';
import { Textarea } from '../Textarea/Textarea';
import { UsersStack } from '../UsersStack/UsersStack';
import { ModalCard, type ModalCardProps } from './ModalCard';
import { ModalCard } from './ModalCard';
import type { ModalCardProps } from './types';

const AppWrapper = ({ children, ...restProps }: AppWrapperProps) => (
<AppDefaultWrapper scroll="contain" {...restProps}>
Expand Down Expand Up @@ -127,15 +127,14 @@ export const ModalCardPlayground = (props: ComponentPlaygroundProps) => {
AppWrapper={AppWrapper}
>
{(props: ModalCardProps) => (
<div style={{ height: 500, transform: 'translateZ(0)' }}>
<ModalRoot
activeModal={props.nav}
<div style={{ height: 500, overflow: 'hidden', transform: 'translateZ(0)' }}>
<ModalCard
open
// Note: с включенным фокусом ломаются скриншоты на движке Webkit из-за фокуса сразу
// на несколько окон
noFocusToDialog
>
<ModalCard {...props} />
</ModalRoot>
{...props}
/>
</div>
)}
</ComponentPlayground>
Expand Down
105 changes: 61 additions & 44 deletions packages/vkui/src/components/ModalCard/ModalCard.module.css
Original file line number Diff line number Diff line change
@@ -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: calc(400px + var(--vkui--spacing_size_2xl));
}

/**
* iOS
*/
.hostMaxWidthM {
max-inline-size: calc(414px + var(--vkui--spacing_size_2xl));
}

.ios .in {
max-inline-size: 414px;
.hostMaxWidthL {
max-inline-size: calc(440px + var(--vkui--spacing_size_2xl));
}

/**
* Android + vkcom
*/
/* Mobile */
@media (--viewWidth-smallTabletMinus) {
.host {
--vkui_internal_ModalCard--translateY: 100%;
--vkui_internal_ModalCard--safeAreaInsetBottom: var(--vkui_internal--safe_area_inset_bottom);

.android .in {
max-inline-size: 440px;
}
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--translateY)), 0);
transition: transform var(--vkui--animation_duration_l) var(--vkui--animation_easing_platform);
}

.vkcom .in {
max-inline-size: 400px;
}
.hostStateEnter {
transform: translate3d(0, 100%, 0);
transition-property: none;
}

/**
* Desktop
*/
.hostStateEntering {
transition-property: transform;
transition-delay: 0.2s;
}

.desktop {
align-items: center;
}
.hostStateExiting {
transform: translate3d(0, 100%, 0);
transition-property: transform;
}

.desktop .in {
transform: unset;
opacity: 0;
transition: opacity 340ms var(--vkui--animation_easing_platform);
.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;
}
}
75 changes: 42 additions & 33 deletions packages/vkui/src/components/ModalCard/ModalCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -11,7 +10,8 @@ import { Image } from '../Image/Image';
import { Spacing } from '../Spacing/Spacing';
import { Textarea } from '../Textarea/Textarea';
import { UsersStack } from '../UsersStack/UsersStack';
import { ModalCard, type ModalCardProps } from './ModalCard';
import { ModalCard } from './ModalCard';
import type { ModalCardProps } from './types';

const story: Meta<ModalCardProps> = {
title: 'Modals/ModalCard',
Expand All @@ -23,17 +23,14 @@ export default story;

type Story = StoryObj<ModalCardProps>;

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: () => (
<ModalWrapper modalId={MODAL_CARD_MONEY_SEND}>
render: function Render() {
const [open, setOpen] = React.useState(true);
const handleClose = () => setOpen(false);
return (
<ModalCard
id={MODAL_CARD_MONEY_SEND}
open={open}
onClose={handleClose}
icon={<Icon56MoneyTransferOutline />}
title="Отправляйте деньги друзьям, используя банковскую карту"
description="Номер карты получателя не нужен — он сам решит, куда зачислить средства."
Expand All @@ -43,15 +40,18 @@ export const SimpleCard: Story = {
</Button>
}
/>
</ModalWrapper>
),
);
},
};

export const CardWithAvatar: Story = {
render: () => (
<ModalWrapper modalId={MODAL_CARD_APP_TO_MENU}>
render: function Render() {
const [open, setOpen] = React.useState(true);
const handleClose = () => setOpen(false);
return (
<ModalCard
id={MODAL_CARD_APP_TO_MENU}
open={open}
onClose={handleClose}
icon={<Image borderRadius="l" src={getAvatarUrl('app_zagadki', 200)} size={72} />}
title="Добавить игру «Загадки детства» в меню?"
description="Игра появится под списком разделов на экране меню и будет всегда под рукой."
Expand All @@ -61,15 +61,18 @@ export const CardWithAvatar: Story = {
</Button>
}
/>
</ModalWrapper>
),
);
},
};

export const CardWithTextArea: Story = {
render: () => (
<ModalWrapper modalId={MODAL_CARD_ABOUT}>
render: function Render() {
const [open, setOpen] = React.useState(true);
const handleClose = () => setOpen(false);
return (
<ModalCard
id={MODAL_CARD_ABOUT}
open={open}
onClose={handleClose}
title="Расскажите о себе"
actions={
<Button size="l" mode="primary" stretched>
Expand All @@ -79,15 +82,18 @@ export const CardWithTextArea: Story = {
>
<Textarea defaultValue="В Грузии" />
</ModalCard>
</ModalWrapper>
),
);
},
};

export const CardWithMultipleButtons: Story = {
render: () => (
<ModalWrapper modalId={MODAL_CARD_NOTIFICATIONS}>
render: function Render() {
const [open, setOpen] = React.useState(true);
const handleClose = () => setOpen(false);
return (
<ModalCard
id={MODAL_CARD_NOTIFICATIONS}
open={open}
onClose={handleClose}
icon={<Icon56NotificationOutline />}
title="Приложение запрашивает разрешение на отправку Вам уведомлений"
actions={
Expand All @@ -101,15 +107,18 @@ export const CardWithMultipleButtons: Story = {
</ButtonGroup>
}
/>
</ModalWrapper>
),
);
},
};

export const CardWithComplexContent: Story = {
render: () => (
<ModalWrapper modalId={MODAL_CARD_CHAT_INVITE}>
render: function Render() {
const [open, setOpen] = React.useState(true);
const handleClose = () => setOpen(false);
return (
<ModalCard
id={MODAL_CARD_CHAT_INVITE}
open={open}
onClose={handleClose}
icon={<Avatar src={getAvatarUrl('chat_basketball', 200)} size={72} />}
title="Баскетбол на выходных"
titleComponent="h2"
Expand Down Expand Up @@ -147,6 +156,6 @@ export const CardWithComplexContent: Story = {
<br />и ещё 3 человека
</UsersStack>
</ModalCard>
</ModalWrapper>
),
);
},
};
Loading

0 comments on commit 2aeae94

Please sign in to comment.