Skip to content

Commit

Permalink
feat(Group): Add Group.ExpandedContent to ignore group inner paddings (
Browse files Browse the repository at this point in the history
…#7396)

Добавили подкомпонент для игнорирования вертикальных и горизонтальных отступов `Group`.
Можно игнорировать либо вертикальные, либо горизонтальные отступы.

Возможно, что имеет смысл игнорировать сразу все отступы, но это можно сделать отдельным вариантом свойства `direction`.

- перетасовали css переменные в `Group`.
Потребовалось, чтобы упростить понимание реализации `Group.ExpandedContent`.
Так как `Group.ExpandedContent` всегда будет находится внутри `Group` и на него всегда будут влиять внутренние отступы `Group`, будет логично внутренние отступы компенсировать за счёт отрицательных марджинов.
Проще всего взять текущее значение паддинга, умножить на -1 и подставить в `margin` `Group.ExpandedContent`.
Но чтобы это сделать надо где-то хранить текущее значение паддинга.

Так как паддинг по горизонтали и вертикали меняется относительно режима `mode = 'card' | 'plain'` у `Group`, то логично хранить паддинг в двух отдельных css-переменных: `--vkui_internal--Group_padding_inline` и `--vkui_internal--Group_padding_block`.
Можно один раз прописать
```css
padding-block: var(--vkui_internal--Group_padding_block);
padding-inline: var(--vkui_internal--Group_padding_inline);
```
а дальше менять только css-переменные, в зависимости от режима.

К сожалению, не удалось избавиться от сss-переменной `--vkui_internal--Group_padding_size`, которая используется для задания отступов в режиме `card`.
Тем не менее удалось встроить её в схему с основными переменными.
Переменная теперь имеет более специфичное имя: `--vkui_internal--Group_card_mode_padding_size`.
  • Loading branch information
mendrew authored Aug 30, 2024
1 parent 01a75d7 commit 0cf497b
Show file tree
Hide file tree
Showing 18 changed files with 229 additions and 12 deletions.
35 changes: 34 additions & 1 deletion packages/vkui/src/components/Group/Group.e2e-playground.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentPlayground, type ComponentPlaygroundProps } from '@vkui-e2e/playground-helpers';
import { Div } from '../Div/Div';
import { Header } from '../Header/Header';
import { Group } from './Group';
import { Group, type GroupProps } from './Group';

export const GroupPlayground = (props: ComponentPlaygroundProps) => {
return (
Expand All @@ -24,3 +24,36 @@ export const GroupPlayground = (props: ComponentPlaygroundProps) => {
</ComponentPlayground>
);
};

export const GroupWithExpandedContentPlayground = (props: ComponentPlaygroundProps) => {
return (
<ComponentPlayground
{...props}
propSets={[
{
mode: ['plain', 'card'],
padding: ['s', 'm'],
$adaptivity: 'x',
children: [
<Group.ExpandedContent key="expanded-inline" direction="inline">
<Div style={{ background: 'var(--vkui--color_background_accent_tint)' }}>
Expanded Inline
</Div>
</Group.ExpandedContent>,
<Group.ExpandedContent key="expanded-block" direction="block">
<Div style={{ background: 'var(--vkui--color_background_accent_tint)' }}>
Expanded Block
</Div>
</Group.ExpandedContent>,
],
},
]}
>
{(props: GroupProps) => (
<Div style={{ background: 'var(--vkui--color_background_warning)' }}>
<Group {...props} />
</Div>
)}
</ComponentPlayground>
);
};
11 changes: 10 additions & 1 deletion packages/vkui/src/components/Group/Group.e2e.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { test } from '@vkui-e2e/test';
import { GroupPlayground } from './Group.e2e-playground';
import { GroupPlayground, GroupWithExpandedContentPlayground } from './Group.e2e-playground';

test('Group', async ({ mount, expectScreenshotClippedToContent, componentPlaygroundProps }) => {
await mount(<GroupPlayground {...componentPlaygroundProps} />);
await expectScreenshotClippedToContent();
});

test('Group.ExpandedContent', async ({
mount,
expectScreenshotClippedToContent,
componentPlaygroundProps,
}) => {
await mount(<GroupWithExpandedContentPlayground {...componentPlaygroundProps} />);
await expectScreenshotClippedToContent();
});
52 changes: 42 additions & 10 deletions packages/vkui/src/components/Group/Group.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,55 @@
* - sizeX="regular" (desktop) -> mode="card"
*/
.Group {
--vkui_internal--Group_padding_size: 0;
--vkui_internal--Group_padding_inline: 0;
--vkui_internal--Group_padding_block: var(--vkui--spacing_size_m);
--vkui_internal--Group_card_mode_padding_size: 0;

color: var(--vkui--color_text_primary);
padding-block: var(--vkui--spacing_size_m);
padding-block: var(--vkui_internal--Group_padding_block);
padding-inline: var(--vkui_internal--Group_padding_inline);
}

.Group--padding-s {
--vkui_internal--Group_padding_size: var(--vkui--spacing_size_xs);
--vkui_internal--Group_card_mode_padding_size: var(--vkui--spacing_size_xs);
}

.Group--padding-m {
--vkui_internal--Group_padding_size: var(--vkui--spacing_size_m);
--vkui_internal--Group_card_mode_padding_size: var(--vkui--spacing_size_m);
}

/* разделитель при mode="card" */
.Group--mode-card,
.Group--sizeX-regular.Group--mode-none {
padding: var(--vkui_internal--Group_padding_size);
--vkui_internal--Group_padding_inline: var(--vkui_internal--Group_card_mode_padding_size);
--vkui_internal--Group_padding_block: var(--vkui_internal--Group_card_mode_padding_size);

position: relative;
background: var(--vkui--color_background_content);
border-radius: var(--vkui--size_border_radius_paper--regular);
}

@media (--sizeX-regular) {
.Group--sizeX-none.Group--mode-none {
padding: var(--vkui_internal--Group_padding_size);
--vkui_internal--Group_padding_inline: var(--vkui_internal--Group_card_mode_padding_size);
--vkui_internal--Group_padding_block: var(--vkui_internal--Group_card_mode_padding_size);

position: relative;
background: var(--vkui--color_background_content);
border-radius: var(--vkui--size_border_radius_paper--regular);
}
}

.Group--sizeX-compact.Group--mode-card {
padding-inline: 0;
--vkui_internal--Group_padding_inline: 0;

border-radius: var(--vkui--size_border_radius_promo--regular);
}

@media (--sizeX-compact) {
.Group--sizeX-none.Group--mode-card {
padding-inline: 0;
--vkui_internal--Group_padding_inline: 0;

border-radius: var(--vkui--size_border_radius_promo--regular);
}
}
Expand Down Expand Up @@ -231,7 +240,8 @@
*/
@media (--sizeX-regular) {
.Group--mode-plain-inside-modal {
padding: var(--vkui--spacing_size_m);
--vkui_internal--Group_padding_inline: var(--vkui--spacing_size_m);
--vkui_internal--Group_padding_block: var(--vkui--spacing_size_m);
}

.Group--mode-plain-inside-modal + .Group__separator-sibling {
Expand All @@ -245,7 +255,7 @@
* Group вложенный в Group
*/
.Group .Group {
padding-inline: 0;
--vkui_internal--Group_padding_inline: 0;
}

.Group .Group + .Group__separator-sibling {
Expand All @@ -260,6 +270,28 @@
padding-block-end: 0;
}

/*
* Group.ExpandedContent
* компенсирующий отступы Group в зависимости
* от режима: inline / block
*/

.Group__expanded-content--inline {
margin-inline: calc(-1 * var(--vkui_internal--Group_padding_inline));
}

.Group__expanded-content--block {
margin-block: calc(-1 * var(--vkui_internal--Group_padding_block));
}

.Group .Group:first-of-type .Group__expanded-content--block {
margin-inline-start: 0;
}

.Group .Group:last-of-type .Group__expanded-content--block {
margin-inline-start: 0;
}

/*
* CMP:
* PanelHeader
Expand Down
18 changes: 18 additions & 0 deletions packages/vkui/src/components/Group/Group.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ export const Example: Story = {
<CellButton onClick={noop}>Добавить домашний адрес</CellButton>
<CellButton onClick={noop}>Добавить рабочий адрес</CellButton>
</Group>
<Group.Container>
<Group.Header>
<Header>Подкомпонентный подход: Адреса</Header>
</Group.Header>
<CellButton onClick={noop}>Добавить домашний адрес</CellButton>
<CellButton onClick={noop}>Добавить рабочий адрес</CellButton>
<Group.Description>
Для использования в мини-приложениях, Delivery Club, VK Taxi и других сервисах
ВКонтакте. Эти адреса видны только Вам.
</Group.Description>
</Group.Container>
<Group>
<Header>Контент игнорирует боковые отступы Group</Header>
<Group.ExpandedContent>
<CellButton onClick={noop}>Добавить домашний адрес</CellButton>
<CellButton onClick={noop}>Добавить рабочий адрес</CellButton>
</Group.ExpandedContent>
</Group>
</>
),
withSinglePanel,
Expand Down
4 changes: 4 additions & 0 deletions packages/vkui/src/components/Group/Group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { hasReactNode } from '@vkontakte/vkjs';
import { GroupContainer, type GroupContainerProps } from './GroupContainer';
import { GroupDescription } from './GroupDescription';
import { GroupExpandedContent } from './GroupExpandedContent';
import { GroupHeader } from './GroupHeader';

export interface GroupProps extends GroupContainerProps {
Expand All @@ -16,6 +17,7 @@ export const Group: React.FC<GroupProps> & {
Container: typeof GroupContainer;
Header: typeof GroupHeader;
Description: typeof GroupDescription;
ExpandedContent: typeof GroupExpandedContent;
} = ({ header, description, children, ...restProps }: GroupProps): React.ReactNode => {
return (
<GroupContainer {...restProps}>
Expand All @@ -33,3 +35,5 @@ Group.Header = GroupHeader;
Group.Header.displayName = 'Group.Header';
Group.Description = GroupDescription;
Group.Description.displayName = 'Group.Description';
Group.ExpandedContent = GroupExpandedContent;
Group.ExpandedContent.displayName = 'Group.ExpandedContent';
26 changes: 26 additions & 0 deletions packages/vkui/src/components/Group/GroupExpandedContent.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { render, screen } from '@testing-library/react';
import { GroupExpandedContent, type GroupExpandedContentProps } from './GroupExpandedContent';
import styles from './Group.module.css';

describe('GroupExpandedContent', () => {
it.each<{ direction: GroupExpandedContentProps['direction']; className: string }>([
{
direction: undefined,
className: styles['Group__expanded-content--inline'],
},
{
direction: 'inline',
className: styles['Group__expanded-content--inline'],
},
{
direction: 'block',
className: styles['Group__expanded-content--block'],
},
])(
'should have className "$className" with direction "$direction"',
async ({ direction, className }) => {
render(<GroupExpandedContent direction={direction}>Content</GroupExpandedContent>);
expect(screen.getByText('Content')).toHaveClass(className);
},
);
});
27 changes: 27 additions & 0 deletions packages/vkui/src/components/Group/GroupExpandedContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import type { HasComponent, HTMLAttributesWithRootRef } from '../../types';
import { RootComponent } from '../RootComponent/RootComponent';
import styles from './Group.module.css';

const stylesDirection = {
inline: styles['Group__expanded-content--inline'],
block: styles['Group__expanded-content--block'],
};

export type GroupExpandedContentProps = HTMLAttributesWithRootRef<HTMLElement> &
HasComponent & {
direction?: 'inline' | 'block';
};
export const GroupExpandedContent: React.FC<GroupExpandedContentProps> = ({
direction = 'inline',
...restProps
}: GroupExpandedContentProps) => {
return (
<RootComponent
Component="div"
{...restProps}
baseClassName={classNames(styles['Group__expanded-content'], stylesDirection[direction])}
/>
);
};
38 changes: 38 additions & 0 deletions packages/vkui/src/components/Group/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,41 @@ const SharedContent = () => {
</Group.Description>
</Group.Container>
```

<br />

## <Group.ExpandedContent>

Компенсирует внутренние отступы `Group` по горизонтали `direction="inline"` или по вертикали `direction="block"`.
Позволяет вложить внутрь `Group` контент, игнорируя внутренние отступы `Group`.

```jsx
const recentFriends = getRandomUsers(20);

<Group header={<Header mode="secondary">Недавние</Header>}>
<Header mode="primary">HorizontalScroll не учитывает отступы Group по горизонтали</Header>

<Group.ExpandedContent direction="inline">
<HorizontalScroll showArrows inline>
{recentFriends.map((item) => {
return (
<HorizontalCell onClick={() => {}} key={item.id} header={item.first_name}>
<Avatar size={56} src={item.photo_200} />
</HorizontalCell>
);
})}
</HorizontalScroll>
</Group.ExpandedContent>

<Header mode="primary">Здесь контент учитывает отступы Group по горизонтали</Header>
<HorizontalScroll showArrows inline>
{recentFriends.map((item) => {
return (
<HorizontalCell onClick={() => {}} key={item.id} header={item.first_name}>
<Avatar size={56} src={item.photo_200} />
</HorizontalCell>
);
})}
</HorizontalScroll>
</Group>;
```
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.
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.

0 comments on commit 0cf497b

Please sign in to comment.