Skip to content

Commit

Permalink
feat(Tabs): add layoutFillMode prop (#6114)
Browse files Browse the repository at this point in the history
* feat(Tabs): add itemsFlexMode prop

* feat: Rename prop to gorgeous layoutFillMode

* chore: update screens

* chore: remove useless sreens
  • Loading branch information
BlackySoul authored Nov 24, 2023
1 parent ec3a56d commit 6793e79
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 4 deletions.
28 changes: 27 additions & 1 deletion packages/vkui/src/components/Tabs/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Group>
<Tabs mode={mode} withScrollToSelectedTab scrollBehaviorToSelectedTab="center">
<Tabs
mode={mode}
layoutFillMode={layoutFillMode}
withScrollToSelectedTab
scrollBehaviorToSelectedTab="center"
>
<HorizontalScroll arrowSize="m">
<TabsItem
selected={selected === 'groups'}
Expand Down Expand Up @@ -210,6 +216,26 @@ const Scrollable = () => {
onChange={(event) => setMode(event.target.value)}
/>
</FormItem>
<FormItem top="layoutFillMode">
<CustomSelect
value={layoutFillMode}
options={[
{
label: 'auto',
value: 'auto',
},
{
label: 'stretched',
value: 'stretched',
},
{
label: 'shrinked',
value: 'shrinked',
},
]}
onChange={(event) => setLayoutFillMode(event.target.value)}
/>
</FormItem>
<Checkbox onChange={() => setDisabled((prev) => !prev)}>disabled</Checkbox>
</Group>
);
Expand Down
28 changes: 28 additions & 0 deletions packages/vkui/src/components/Tabs/Tabs.e2e-playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,31 @@ export const TabsPlayground = (props: ComponentPlaygroundProps) => {
</ComponentPlayground>
);
};

export const TabsItemsFlexModePlayground = (props: ComponentPlaygroundProps) => {
return (
<ComponentPlayground
{...props}
propSets={[
{
mode: ['default', 'accent', 'secondary'],
children: [
<>
<TabsItem>Unscrollable</TabsItem>
<TabsItem selected>Unscrollable</TabsItem>
</>,
<HorizontalScroll key="scrolled" arrowSize="m">
<TabsItem key="groups">Scrollable</TabsItem>
<TabsItem key="news" selected>
Scrollable
</TabsItem>
</HorizontalScroll>,
],
layoutFillMode: ['auto', 'shrinked', 'stretched'],
},
]}
>
{(props: TabsProps) => <Tabs {...props} />}
</ComponentPlayground>
);
};
17 changes: 16 additions & 1 deletion packages/vkui/src/components/Tabs/Tabs.e2e.tsx
Original file line number Diff line number Diff line change
@@ -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(<TabsPlayground {...componentPlaygroundProps} />);
await expectScreenshotClippedToContent();
});

test.describe('Tabs', () => {
test.use({
onlyForAppearances: [Appearance.LIGHT],
});
test('layout fill mode', async ({
mount,
expectScreenshotClippedToContent,
componentPlaygroundProps,
}) => {
await mount(<TabsItemsFlexModePlayground {...componentPlaygroundProps} />);
await expectScreenshotClippedToContent();
});
});
12 changes: 12 additions & 0 deletions packages/vkui/src/components/Tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,28 @@ export interface TabsProps extends HTMLAttributesWithRootRef<HTMLDivElement> {
* @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<TabsProps['layoutFillMode']>;
withScrollToSelectedTab: TabsProps['withScrollToSelectedTab'];
scrollBehaviorToSelectedTab: Required<TabsProps['scrollBehaviorToSelectedTab']>;
}

export const TabsModeContext = React.createContext<TabsContextProps>({
mode: 'default',
withGaps: false,
layoutFillMode: 'auto',
withScrollToSelectedTab: false,
scrollBehaviorToSelectedTab: 'nearest',
});
Expand All @@ -47,6 +57,7 @@ export const Tabs = ({
role = 'tablist',
withScrollToSelectedTab,
scrollBehaviorToSelectedTab = 'nearest',
layoutFillMode = 'auto',
...restProps
}: TabsProps) => {
const platform = usePlatform();
Expand Down Expand Up @@ -167,6 +178,7 @@ export const Tabs = ({
value={{
mode,
withGaps,
layoutFillMode,
withScrollToSelectedTab,
scrollBehaviorToSelectedTab,
}}
Expand Down
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.
9 changes: 9 additions & 0 deletions packages/vkui/src/components/TabsItem/TabsItem.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
15 changes: 13 additions & 2 deletions packages/vkui/src/components/TabsItem/TabsItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<HTMLElement> {
/**
* Добавляет иконку слева.
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -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']}
Expand Down

0 comments on commit 6793e79

Please sign in to comment.