diff --git a/packages/vkui/src/components/Tabs/Readme.md b/packages/vkui/src/components/Tabs/Readme.md
index e01e600d63..f7ca4d2187 100644
--- a/packages/vkui/src/components/Tabs/Readme.md
+++ b/packages/vkui/src/components/Tabs/Readme.md
@@ -131,12 +131,18 @@ const DefaultInPanel = ({ menuOpened, onMenuClick, selected, setSelected }) => {
const Scrollable = () => {
const [mode, setMode] = React.useState('default');
+ const [layoutFillMode, setLayoutFillMode] = React.useState('auto');
const [selected, setSelected] = React.useState('news');
const [disabled, setDisabled] = React.useState(false);
return (
-
+
{
onChange={(event) => setMode(event.target.value)}
/>
+
+ setLayoutFillMode(event.target.value)}
+ />
+
setDisabled((prev) => !prev)}>disabled
);
diff --git a/packages/vkui/src/components/Tabs/Tabs.e2e-playground.tsx b/packages/vkui/src/components/Tabs/Tabs.e2e-playground.tsx
index 5c45c7f19a..fccee103f0 100644
--- a/packages/vkui/src/components/Tabs/Tabs.e2e-playground.tsx
+++ b/packages/vkui/src/components/Tabs/Tabs.e2e-playground.tsx
@@ -125,3 +125,31 @@ export const TabsPlayground = (props: ComponentPlaygroundProps) => {
);
};
+
+export const TabsItemsFlexModePlayground = (props: ComponentPlaygroundProps) => {
+ return (
+
+ Unscrollable
+ Unscrollable
+ >,
+
+ Scrollable
+
+ Scrollable
+
+ ,
+ ],
+ layoutFillMode: ['auto', 'shrinked', 'stretched'],
+ },
+ ]}
+ >
+ {(props: TabsProps) => }
+
+ );
+};
diff --git a/packages/vkui/src/components/Tabs/Tabs.e2e.tsx b/packages/vkui/src/components/Tabs/Tabs.e2e.tsx
index 37e27d10db..8eabbbe168 100644
--- a/packages/vkui/src/components/Tabs/Tabs.e2e.tsx
+++ b/packages/vkui/src/components/Tabs/Tabs.e2e.tsx
@@ -1,8 +1,23 @@
import * as React from 'react';
import { test } from '@vkui-e2e/test';
-import { TabsPlayground } from './Tabs.e2e-playground';
+import { Appearance } from '../../helpers/appearance';
+import { TabsItemsFlexModePlayground, TabsPlayground } from './Tabs.e2e-playground';
test('Tabs', async ({ mount, expectScreenshotClippedToContent, componentPlaygroundProps }) => {
await mount();
await expectScreenshotClippedToContent();
});
+
+test.describe('Tabs', () => {
+ test.use({
+ onlyForAppearances: [Appearance.LIGHT],
+ });
+ test('layout fill mode', async ({
+ mount,
+ expectScreenshotClippedToContent,
+ componentPlaygroundProps,
+ }) => {
+ await mount();
+ await expectScreenshotClippedToContent();
+ });
+});
diff --git a/packages/vkui/src/components/Tabs/Tabs.tsx b/packages/vkui/src/components/Tabs/Tabs.tsx
index babf30a3e2..3c2d656e9a 100644
--- a/packages/vkui/src/components/Tabs/Tabs.tsx
+++ b/packages/vkui/src/components/Tabs/Tabs.tsx
@@ -22,11 +22,20 @@ export interface TabsProps extends HTMLAttributesWithRootRef {
* @since 5.10.0
*/
scrollBehaviorToSelectedTab?: ScrollIntoViewOptions['inline'];
+ /**
+ * При `auto` ширина вкладок определяется контекстом:
+ * - равномерно занимают всю доступную ширину при вложении в `HorizontalScroll`
+ * - равномерно занимают всю доступную ширину при `mode=default` и platform !== 'VKCOM'
+ * При `stretched` и `shrinked` вкладки либо равномерно занимают всю ширину,
+ * либо выравниваются по контенту соответственно
+ */
+ layoutFillMode?: 'auto' | 'stretched' | 'shrinked';
}
export interface TabsContextProps {
mode: TabsProps['mode'];
withGaps: boolean;
+ layoutFillMode: NonNullable;
withScrollToSelectedTab: TabsProps['withScrollToSelectedTab'];
scrollBehaviorToSelectedTab: Required;
}
@@ -34,6 +43,7 @@ export interface TabsContextProps {
export const TabsModeContext = React.createContext({
mode: 'default',
withGaps: false,
+ layoutFillMode: 'auto',
withScrollToSelectedTab: false,
scrollBehaviorToSelectedTab: 'nearest',
});
@@ -47,6 +57,7 @@ export const Tabs = ({
role = 'tablist',
withScrollToSelectedTab,
scrollBehaviorToSelectedTab = 'nearest',
+ layoutFillMode = 'auto',
...restProps
}: TabsProps) => {
const platform = usePlatform();
@@ -167,6 +178,7 @@ export const Tabs = ({
value={{
mode,
withGaps,
+ layoutFillMode,
withScrollToSelectedTab,
scrollBehaviorToSelectedTab,
}}
diff --git a/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-android-chromium-light-1-snap.png b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-android-chromium-light-1-snap.png
new file mode 100644
index 0000000000..2c93c09cf7
--- /dev/null
+++ b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-android-chromium-light-1-snap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:21341ab6228655178b06c597f564a53743840a627c83a657a1788ebd6b6fdbcc
+size 139892
diff --git a/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-ios-webkit-light-1-snap.png b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-ios-webkit-light-1-snap.png
new file mode 100644
index 0000000000..6c93384723
--- /dev/null
+++ b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-ios-webkit-light-1-snap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d907ae7a04f25a0fbeb5c7aa3f13ba5c60535c296e5356159862856f97425da8
+size 129027
diff --git a/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-chromium-light-1-snap.png b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-chromium-light-1-snap.png
new file mode 100644
index 0000000000..f160d3217c
--- /dev/null
+++ b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-chromium-light-1-snap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aad87d00a33b748cb6611ba2469d9c12ef1c6eff45fb6d5a0f01704cf8ba4253
+size 130264
diff --git a/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-firefox-light-1-snap.png b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-firefox-light-1-snap.png
new file mode 100644
index 0000000000..40d5c85b29
--- /dev/null
+++ b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-firefox-light-1-snap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c5e59121b9e2301c2c5d1c07c434c644923627fabc9212afae600cddf8ffeb36
+size 158093
diff --git a/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-webkit-light-1-snap.png b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-webkit-light-1-snap.png
new file mode 100644
index 0000000000..1651a8e0d9
--- /dev/null
+++ b/packages/vkui/src/components/Tabs/__image_snapshots__/tabs-layout-fill-mode-vkcom-webkit-light-1-snap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:175b28c7ed96f957b897e9078a4f139d9c04a94abb7a88d51752a8d5b8d4fc1e
+size 119808
diff --git a/packages/vkui/src/components/TabsItem/TabsItem.module.css b/packages/vkui/src/components/TabsItem/TabsItem.module.css
index 02a10deb45..9065717663 100644
--- a/packages/vkui/src/components/TabsItem/TabsItem.module.css
+++ b/packages/vkui/src/components/TabsItem/TabsItem.module.css
@@ -217,3 +217,12 @@
flex-grow: 1;
flex-shrink: 0;
}
+
+.TabsItem.TabsItem--stretched {
+ flex-grow: 1;
+}
+
+.TabsItem.TabsItem--shrinked {
+ flex-grow: 0;
+ min-width: auto;
+}
diff --git a/packages/vkui/src/components/TabsItem/TabsItem.tsx b/packages/vkui/src/components/TabsItem/TabsItem.tsx
index 3244bb0986..e271f7fd80 100644
--- a/packages/vkui/src/components/TabsItem/TabsItem.tsx
+++ b/packages/vkui/src/components/TabsItem/TabsItem.tsx
@@ -25,6 +25,11 @@ const stylesMode = {
secondary: styles['TabsItem--mode-secondary'],
};
+const fillModeClassNames = {
+ stretched: styles['TabsItem--stretched'],
+ shrinked: styles['TabsItem--shrinked'],
+};
+
export interface TabsItemProps extends HTMLAttributesWithRootRef {
/**
* Добавляет иконку слева.
@@ -69,8 +74,13 @@ export const TabsItem = ({
...restProps
}: TabsItemProps) => {
const { sizeY = 'none' } = useAdaptivity();
- const { mode, withGaps, scrollBehaviorToSelectedTab, withScrollToSelectedTab }: TabsContextProps =
- React.useContext(TabsModeContext);
+ const {
+ mode,
+ withGaps,
+ layoutFillMode,
+ scrollBehaviorToSelectedTab,
+ withScrollToSelectedTab,
+ }: TabsContextProps = React.useContext(TabsModeContext);
let statusComponent = null;
const isTabFlow = role === 'tab';
@@ -160,6 +170,7 @@ export const TabsItem = ({
selected && styles['TabsItem--selected'],
sizeY !== SizeType.REGULAR && sizeYClassNames[sizeY],
withGaps && styles['TabsItem--withGaps'],
+ layoutFillMode !== 'auto' && fillModeClassNames[layoutFillMode],
className,
)}
hoverMode={styles['TabsItem--hover']}