Skip to content

Commit

Permalink
feat: add Modal designed body
Browse files Browse the repository at this point in the history
  • Loading branch information
vadim-kudr committed Nov 15, 2024
1 parent 2428b09 commit a99eaf1
Show file tree
Hide file tree
Showing 30 changed files with 1,449 additions and 94 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion packages/plasma-b2c/src/components/ModalBase/Modal.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ export const config = {
variations: {
view: {
default: css`
${modalTokens.modalOverlayWithBlurColor}: rgba(35, 35, 35, 0.2);
${modalTokens.modalOverlayWithBlurColor}: var(--overlay-blur);
${modalTokens.modalOverlayColor}: var(--overlay-soft);
${modalTokens.modalBodyBackground}: var(--surface-solid-card);
${modalTokens.modalBodyBorderRadius}: 1.25rem;
${modalTokens.modalBodyPadding}: 2rem;
${modalTokens.modalContentPadding}: 0.625rem;
${modalTokens.modalCloseButtonRadius}: 0.375rem;
${modalTokens.modalOutlineFocusColor}: var(--surface-accent);
`,
},
},
Expand Down
143 changes: 141 additions & 2 deletions packages/plasma-b2c/src/components/ModalBase/ModalBase.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback, useRef, useState } from 'react';
import styled, { css } from 'styled-components';
import type { Meta, StoryObj } from '@storybook/react';
import { surfaceSolid02 } from '@salutejs/plasma-tokens-b2c';
import { InSpacingDecorator } from '@salutejs/plasma-sb-utils';
import { disableProps, InSpacingDecorator } from '@salutejs/plasma-sb-utils';

import { SSRProvider } from '../SSRProvider';
import { Button } from '../Button';
Expand All @@ -20,6 +20,24 @@ const meta: Meta<ModalBaseProps> = {
docs: { story: { inline: false, iframeHeight: '30rem' } },
},
argTypes: {
...disableProps([
'onEscKeyDown',
'onOverlayClick',
'initialFocusRef',
'focusAfterRef',
'onClose',
'view',
'isOpen',
'opened',
'offset',
'frame',
'children',
'overlay',
'zIndex',
'popupInfo',
'withAnimation',
'hasBody',
]),
placement: {
options: [
'center',
Expand All @@ -35,6 +53,37 @@ const meta: Meta<ModalBaseProps> = {
control: {
type: 'select',
},
table: { defaultValue: { summary: 'center' } },
},
offsetX: {
control: {
type: 'number',
},
table: { defaultValue: { summary: 0 } },
},
offsetY: {
control: {
type: 'number',
},
table: { defaultValue: { summary: 0 } },
},
closeOnEsc: {
control: {
type: 'boolean',
},
table: { defaultValue: { summary: true } },
},
closeOnOverlayClick: {
control: {
type: 'boolean',
},
table: { defaultValue: { summary: true } },
},
withBlur: {
control: {
type: 'boolean',
},
table: { defaultValue: { summary: false } },
},
},
};
Expand All @@ -48,6 +97,7 @@ type StoryModalBaseProps = {
closeOnEsc: boolean;
closeOnOverlayClick: boolean;
withBlur: boolean;
hasClose?: boolean;
};

const StyledButton = styled(Button)`
Expand Down Expand Up @@ -103,6 +153,89 @@ const StoryModalBaseDemo = ({ placement, offsetX, offsetY, ...rest }: StoryModal
const [isOpenB, setIsOpenB] = useState(false);
const [isOpenC, setIsOpenC] = useState(false);

return (
<SSRProvider>
<StyledWrapper>
<PopupBaseProvider>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<StyledButton text="Открыть A" onClick={() => setIsOpenA(true)} />
</div>
<StyledModal
id="modalA"
withAnimation
onClose={() => setIsOpenA(false)}
opened={isOpenA}
placement={placement}
offset={[offsetX, offsetY]}
hasBody
{...rest}
>
<Button onClick={() => setIsOpenA(false)}>Close</Button>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<StyledButton text="Открыть B" onClick={() => setIsOpenB(true)} />
</div>
<ModalBase
id="modalB"
onClose={() => setIsOpenB(false)}
opened={isOpenB}
placement="left"
offset={[offsetX, offsetY]}
hasBody
{...rest}
>
<Button style={{ marginRight: '1rem' }} onClick={() => setIsOpenB(false)}>
Close
</Button>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<StyledButton text="Открыть C" onClick={() => setIsOpenC(true)} />
</div>
<ModalBase
id="modalC"
onClose={() => setIsOpenC(false)}
opened={isOpenC}
placement="top"
offset={[offsetX, offsetY]}
hasBody
{...rest}
>
<Button style={{ marginRight: '1rem' }} onClick={() => setIsOpenC(false)}>
Close
</Button>
<>Content</>
</ModalBase>
</ModalBase>
</StyledModal>
</PopupBaseProvider>
</StyledWrapper>
</SSRProvider>
);
};

export const Default: StoryObj<StoryModalBaseProps> = {
args: {
placement: 'center',
withBlur: false,
closeOnEsc: true,
closeOnOverlayClick: true,
offsetX: 0,
offsetY: 0,
hasClose: true,
},
argTypes: {
hasClose: {
control: {
type: 'boolean',
},
},
},
render: (args) => <StoryModalBaseDemo {...args} />,
};

const StoryCustomModalBaseDemo = ({ placement, offsetX, offsetY, ...rest }: StoryModalBaseProps) => {
const [isOpenA, setIsOpenA] = useState(false);
const [isOpenB, setIsOpenB] = useState(false);
const [isOpenC, setIsOpenC] = useState(false);

return (
<SSRProvider>
<StyledWrapper>
Expand Down Expand Up @@ -173,7 +306,10 @@ export const ModalBaseDemo: StoryObj<StoryModalBaseProps> = {
offsetX: 0,
offsetY: 0,
},
render: (args) => <StoryModalBaseDemo {...args} />,
argTypes: {
...disableProps(['hasClose']),
},
render: (args) => <StoryCustomModalBaseDemo {...args} />,
};

const StyledModalAnimation = styled(ModalBase)`
Expand Down Expand Up @@ -295,5 +431,8 @@ export const ModalBottomAnimation: StoryObj<StoryModalBaseProps> = {
offsetX: 0,
offsetY: 0,
},
argTypes: {
...disableProps(['hasClose']),
},
render: (args) => <StoryModalAnimationDemo {...args} />,
};
49 changes: 49 additions & 0 deletions packages/plasma-new-hope/src/components/Modal/Modal.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { styled } from '@linaria/react';

import { addFocus } from '../../mixins';

import { tokens } from './Modal.tokens';

export const ModalBody = styled.div`
border-radius: var(${tokens.modalBodyBorderRadius});
padding: var(${tokens.modalBodyPadding});
background: var(${tokens.modalBodyBackground});
box-shadow: var(--shadow-down-soft-l);
`;

export const ModalContent = styled.div`
position: relative;
padding: var(${tokens.modalContentPadding});
`;

export const CloseButton = styled.button`
top: 0;
right: 0;
width: 1.5rem;
height: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
border: none;
border-radius: var(${tokens.modalCloseButtonRadius});
padding: 0;
margin: 0;
outline: none;
cursor: pointer;
background: transparent;
${addFocus({
outlineSize: '0.063rem',
outlineOffset: '-0.125rem',
outlineColor: `var(${tokens.modalOutlineFocusColor})`,
outlineRadius: `calc(var(${tokens.modalCloseButtonRadius}) + 0.063rem)`,
})};
position: absolute;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,53 @@ export function App() {
}
```

## Использование стилизованной обертки

Для использования стилизованного мобального окна с отступами и крестиком для закрытия, добавьте свойство `hasBody`.
```tsx live
import React, { useState } from 'react';
import { SSRProvider, Button, Modal, PopupProvider } from '@salutejs/{{ package }}';

export function App() {
const [isOpenA, setIsOpenA] = useState(false);
const [isOpenB, setIsOpenB] = useState(false);

return (
<SSRProvider>
<PopupProvider>
<div style=\{{ height: "300px" }}>
<div style=\{{ display: 'flex', flexDirection: 'column' }}>
<Button text="Открыть A" onClick={() => setIsOpenA(true)} />
</div>
<Modal
id="modalA"
onClose={() => setIsOpenA(false)}
opened={isOpenA}
placement="center"
offset={[0, 0]}
hasBody
>
<Button onClick={() => setIsOpenA(false)}>Close</Button>
<Button text="Открыть B" onClick={() => setIsOpenB(true)} />
Content
<Modal
id="modalB"
onClose={() => setIsOpenB(false)}
opened={isOpenB}
placement="right"
offset={[0, 0]}
>
<Button onClick={() => setIsOpenB(false)}>Close</Button>
Content
</Modal>
</Modal>
</div>
</PopupProvider>
</SSRProvider>
);
}
```

## Подключение анимации
Подключение анимации аналогично тому, как это происходит в `Popup` - через свойство `withAnimation`(управление через `popupClasses`, `modalClasses`).
Для добавления анимации в оверлей необходимо использовать класс `.modal-overlay` через переменную `modalClasses.overlay` из пакета.
Expand Down
6 changes: 6 additions & 0 deletions packages/plasma-new-hope/src/components/Modal/Modal.tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ export const classes = {
export const tokens = {
modalOverlayWithBlurColor: '--plasma-modal-overlay-with-blur-color',
modalOverlayColor: '--plasma-modal-overlay-color',
modalBodyBackground: '--plasma-modal-body-background',
modalBodyBorderRadius: '--plasma-modal-body-border-radius',
modalBodyPadding: '--plasma-modal-body-padding',
modalContentPadding: '--plasma-modal-content-padding',
modalOutlineFocusColor: '--plasma-modal-outline-focus-color',
modalCloseButtonRadius: '--plasma-modal-close-button-radius',
};
Loading

0 comments on commit a99eaf1

Please sign in to comment.