Skip to content

Commit

Permalink
tech(Flex): add support flex with gap (#8212)
Browse files Browse the repository at this point in the history
* tech(Flex): add support flex with gap

* fix(Flex): fix logic with calc childrens count

* fix(Flex): revert Flex childrens count calculation

* fix(Flex): add TODO and @support (inset: 0)

* fix(Flex): fix style

* doc: add info about fallback

* doc(Flex): add example with Fragment

* doc(Flex): fix formatting

* fix: fix documentation

* fix(Flex): fix documenatation

* fix(Flex): improve documentation
  • Loading branch information
EldarMuhamethanov authored Feb 3, 2025
1 parent d0fb8bd commit 5e4a670
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 19 deletions.
38 changes: 25 additions & 13 deletions packages/vkui/src/components/Flex/Flex.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,31 @@
margin-block: var(--vkui--size_base_padding_vertical--regular);
}

.withGaps {
margin-block-start: calc(
-1 * var(--vkui_internal--row_gap) + var(--vkui_internal--flex_original_margin_block)
);
margin-inline-start: calc(
-1 * var(--vkui_internal--column_gap) + var(--vkui_internal--flex_original_margin_inline)
);
/*TODO [>=8]: Проверить браузерную поддержку gap*/
/*Данная проверка позволяет максимально близко определить поддерживается ли gap + flex*/
/*см. https://github.com/w3c/csswg-drafts/issues/3559#issuecomment-1758459996*/
/*Поддержка inset https://developer.mozilla.org/en-US/docs/Web/CSS/inset#browser_compatibility*/
/*Поддержка gap https://developer.mozilla.org/en-US/docs/Web/CSS/gap#browser_compatibility*/
@supports (inset: 0) {
.host {
gap: var(--vkui_internal--row_gap) var(--vkui_internal--column_gap);
}
}
@supports not (inset: 0) {
.withGaps {
margin-block-start: calc(
-1 * var(--vkui_internal--row_gap) + var(--vkui_internal--flex_original_margin_block)
);
margin-inline-start: calc(
-1 * var(--vkui_internal--column_gap) + var(--vkui_internal--flex_original_margin_inline)
);
}

/* stylelint-disable-next-line @project-tools/stylelint-atomic, selector-max-universal */
.withGaps.withGaps > * {
margin-block-start: var(--vkui_internal--row_gap);
margin-inline-start: var(--vkui_internal--column_gap);
}
}

.host > .marginAuto {
Expand Down Expand Up @@ -90,9 +108,3 @@
.alignBaseline {
align-items: baseline;
}

/* stylelint-disable-next-line @project-tools/stylelint-atomic, selector-max-universal */
.withGaps.withGaps > * {
margin-block-start: var(--vkui_internal--row_gap);
margin-inline-start: var(--vkui_internal--column_gap);
}
40 changes: 35 additions & 5 deletions packages/vkui/src/components/Flex/Flex.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,54 @@ import { Button } from '../Button/Button';
import { Image } from '../Image/Image';
import { Flex, type FlexProps } from './Flex';

const story: Meta<FlexProps> = {
type StoryProps = FlexProps & {
/**
* Отступ между строками
*/
rowGap?: number;
/**
* Отступ между столбцами
*/
columnGap?: number;
/**
* Количество элементов
*/
itemsCount?: number;
};

const story: Meta<StoryProps> = {
title: 'Layout/Flex',
component: Flex,
parameters: { ...CanvasFullLayout, ...DisableCartesianParam },
argTypes: {
rowGap: {
control: 'number',
},
columnGap: {
control: 'number',
},
itemsCount: {
control: 'number',
},
},
};

export default story;

type Story = StoryObj<FlexProps>;
type Story = StoryObj<StoryProps>;

export const Playground: Story = {
args: {
gap: 'm',
itemsCount: 2,
style: { height: '100%' },
},
render: (args) => (
<Flex {...args}>
{Array.from({ length: 2 }, (_, index) => {
render: ({ itemsCount = 2, rowGap, columnGap, gap, ...args }) => (
<Flex
gap={rowGap !== undefined || columnGap !== undefined ? [rowGap || 0, columnGap || 0] : gap}
{...args}
>
{Array.from({ length: itemsCount }, (_, index) => {
return (
<Banner
key={index}
Expand Down
2 changes: 1 addition & 1 deletion packages/vkui/src/components/Flex/Flex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const Flex: React.FC<FlexProps> & {
...props
}: FlexProps) => {
const withGaps = Children.count(children) > 1 && gap;
const [rowGap, columnGap] = calculateGap(withGaps ? gap : undefined);
const [rowGap, columnGap] = calculateGap(gap);

return (
<RootComponent
Expand Down
38 changes: 38 additions & 0 deletions packages/vkui/src/components/Flex/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,41 @@ const Example = () => {

<Example />;
```

> **⚠️ Важное замечание о поддержке браузеров:**
>
> Современные браузеры (версии от):
>
> - Chrome 87+
> - Edge 87+
> - Safari 14.1+
> - Firefox 66+
> - Opera 73+
>
> используют нативное `CSS` свойство `gap`. Для более старых версий браузеров автоматически применяется альтернативное решение с использованием `margin`.
>
> Рекомендации по использованию:
>
> При работе со старыми браузерами, где `gap` на flex-контейнерах не поддерживается, важно соблюдать следующее правило:
>
> ❌ Не используйте `React.Fragment `как обертку для дочерних элементов:
>
> ```jsx static
> <Flex gap="m">
> <React.Fragment>
> <div>1</div>
> <div>2</div>
> </React.Fragment>
> </Flex>
> ```
>
> ✅ Правильный вариант - размещайте элементы напрямую внутри `Flex`:
>
> ```jsx static
> <Flex gap="m">
> <div>1</div>
> <div>2</div>
> </Flex>
> ```
>
> Это обеспечит корректную работу отступов между элементами во всех поддерживаемых браузерах.

0 comments on commit 5e4a670

Please sign in to comment.