Skip to content

Commit f6195f3

Browse files
author
Juli Ovechkina
authored
feat(Tabs): change tabs to buttons (#63)
* feat(Tabs): change tabs to buttons
1 parent 7e74082 commit f6195f3

File tree

14 files changed

+463
-186
lines changed

14 files changed

+463
-186
lines changed

src/blocks/ContentLayout/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
`properties:` — Content cube properties (optional)
22

3-
- `size?: 's' | 'l'` — Cube size that defines font sizes (defaults to l)
3+
- `size?: 's' | 'l'` — Cube size that defines font sizes ('l' by default)
44
- `background?: BackgroundImage` — Special background properties described in the **Content blocks** section.
55
- `centered?: false | true` — Indicates if text is centered (false by default).
66
- `theme?: 'default' | 'dark' | 'light'` — Cube theme: default, dark, or monochrome light ('default' by default).

src/blocks/Tabs/README.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
11
Tabs block
22

3-
`type: tabs-block` — Title
3+
`type: tabs-block`
44

5-
`title: Title` — Subtitle
5+
`title?: Title | string`
66

7-
`items: TabsBlockItem[]` — Tab description
7+
`description?: string`
88

9-
> `tabName: string` — Tab title.
9+
`animated?: boolean` — Enables/disables animation for the block (enabled by default).
1010

11-
> `image: string` — Image.
11+
`centered?: false | true` - Aligns all content to the center ('false' by default)
1212

13-
> `caption?: string` — Image caption.
13+
`tabsColSizes?: Object` — Width of buttons tabs, the value ranges from 1 to 12 columns. If 12 columns, buttons takes up the entire width of the row.
1414

15-
> `text: string` —Text.
15+
- `all: number` — On all screens.
16+
- `sm: number` — On a screen wider than 577px.
17+
- `md: number` — On a screen wider than 769px.
18+
- `lg: number` — On a screen wider than 1081px.
19+
- `xl: number` — On a screen wider than 1185px.
1620

17-
> `link?: Link` — Link below the text.
21+
`items: TabsBlockItem[]` — Tab description
22+
23+
- `tabName: string` — Tab title.
24+
- `title?: string` — Item's title
25+
- `text?: string` — Item's text (with YFM support)
26+
- `additionalInfo?: string` — Gray text (with YFM support)
27+
- `links?: Link[]` — An array with link objects (see [Content blocks](?path=/story/information--common-types&viewMode=docs))
28+
- `buttons?: Button[]` — An array with button objects (see [Content blocks](?path=/story/information--common-types&viewMode=docs))
29+
- `image?: string | ImageObjectProps` — Image.
30+
- [`media: Media` — Media description](?path=/story/information--common-types&viewMode=docs#media---picvideodatalens)
31+
- `caption?: string` — Image caption.

src/blocks/Tabs/Tabs.scss

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
11
@import '../../../styles/mixins';
22
@import '../../../styles/variables';
33

4-
$block: '.#{$ns}TabsBlock';
4+
$block: '.#{$ns}tabs-block';
55

66
#{$block} {
77
$class: &;
88

99
&__block-title {
10-
margin-bottom: 12px;
10+
margin-bottom: $indentSM;
11+
12+
&_centered {
13+
display: flex;
14+
justify-content: center;
15+
flex-wrap: wrap;
16+
margin-left: auto;
17+
margin-right: auto;
18+
text-align: center;
19+
}
1120
}
1221

1322
&__tabs {
14-
@include add-specificity(&) {
15-
flex-wrap: nowrap;
16-
overflow-x: auto;
17-
margin-bottom: $indentM;
23+
&_centered {
24+
display: flex;
25+
justify-content: center;
26+
flex-wrap: wrap;
27+
}
28+
}
29+
30+
&__row_reverse {
31+
flex-direction: row-reverse;
32+
33+
#{$class}__content-wrapper {
34+
margin: $indentSM $indentM 0 0;
1835
}
1936
}
2037

@@ -40,6 +57,16 @@ $block: '.#{$ns}TabsBlock';
4057
&__content {
4158
display: flex;
4259
flex-direction: column;
60+
61+
&_centered {
62+
margin: 0 auto;
63+
}
64+
}
65+
66+
&__col {
67+
&_centered {
68+
margin: 0 auto;
69+
}
4370
}
4471

4572
&__content-wrapper {
@@ -58,17 +85,41 @@ $block: '.#{$ns}TabsBlock';
5885
}
5986
}
6087

61-
&__tabs,
62-
&__link {
63-
@include text-size(body-2);
64-
}
65-
6688
@media (max-width: map-get($gridBreakpoints, 'md')) {
89+
&__tabs {
90+
display: flex;
91+
flex-wrap: nowrap;
92+
justify-content: flex-start;
93+
overflow: auto;
94+
margin-left: -$indentL;
95+
margin-right: -$indentL;
96+
padding-left: $indentL;
97+
padding-right: $indentL - $indentXXXS;
98+
}
99+
67100
&__content-wrapper {
68101
&_margin {
69102
margin: 0 0 $contentMargin 0;
70103
}
71104
}
105+
106+
&__row_reverse {
107+
flex-direction: column-reverse;
108+
109+
#{$class}__content > * {
110+
margin-top: $indentM;
111+
padding-bottom: 0;
112+
}
113+
}
114+
}
115+
116+
@media (max-width: map-get($gridBreakpoints, 'sm')) {
117+
&__tabs {
118+
margin-left: -$indentSM;
119+
margin-right: -$indentSM;
120+
padding-left: $indentSM;
121+
padding-right: $indentXS;
122+
}
72123
}
73124

74125
@include animate(#{$class}__media);

src/blocks/Tabs/Tabs.tsx

Lines changed: 87 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,123 @@
11
import React, {Fragment, useContext, useState} from 'react';
2-
import {Tabs} from '@gravity-ui/uikit';
32

43
import {block, getThemedValue} from '../../utils';
54
import {Row, Col, GridColumnOrderClasses} from '../../grid';
6-
import YFMWrapper from '../../components/YFMWrapper/YFMWrapper';
75
import {TabsBlockProps} from '../../models';
86
import AnimateBlock from '../../components/AnimateBlock/AnimateBlock';
97
import BlockHeader from '../../components/BlockHeader/BlockHeader';
108
import FullScreenImage from '../../components/FullscreenImage/FullscreenImage';
119
import Media from '../../components/Media/Media';
12-
import Links from '../../components/Link/Links';
1310
import {ThemeValueContext} from '../../context/theme/ThemeValueContext';
1411
import {getMediaImage} from '../../components/Media/Image/utils';
12+
import ButtonTabs, {ButtonTabsItemProps} from '../../components/ButtonTabs/ButtonTabs';
13+
import {Content} from '../../sub-blocks';
1514

1615
import './Tabs.scss';
1716

18-
const b = block('TabsBlock');
17+
const b = block('tabs-block');
1918

20-
export const TabsBlock = ({items, title, description, animated}: TabsBlockProps) => {
19+
export const TabsBlock = ({
20+
items,
21+
title,
22+
description,
23+
animated,
24+
tabsColSizes,
25+
centered,
26+
direction = 'media-content',
27+
}: TabsBlockProps) => {
2128
const [activeTab, setActiveTab] = useState(items[0].tabName);
2229
const [play, setPlay] = useState<boolean>(false);
2330
const {themeValue: theme} = useContext(ThemeValueContext);
24-
const tabs = items.map(({tabName}) => ({title: tabName, id: tabName}));
31+
const tabs: ButtonTabsItemProps[] = items.map(({tabName}) => ({title: tabName, id: tabName}));
2532
const activeTabData = items.find(({tabName}) => tabName === activeTab);
33+
const isReverse = direction === 'content-media';
2634

2735
let imageProps;
2836

2937
if (activeTabData) {
3038
const themedImage = getThemedValue(activeTabData.image, theme);
39+
3140
imageProps = themedImage && getMediaImage(themedImage);
3241
}
3342

3443
const showMedia = Boolean(activeTabData?.media || imageProps);
44+
const showText = Boolean(activeTabData?.text);
45+
46+
const textContent = activeTabData && showText && (
47+
<Col
48+
sizes={{all: 12, md: showMedia ? 4 : 8}}
49+
className={b('content', {centered: centered})}
50+
>
51+
<div
52+
className={b('content-wrapper', {
53+
margin: Boolean((activeTabData?.media || imageProps) && !isReverse),
54+
})}
55+
>
56+
<Content
57+
title={activeTabData.title}
58+
text={activeTabData.text}
59+
additionalInfo={activeTabData.additionalInfo}
60+
size="s"
61+
links={[
62+
...(activeTabData.link ? [activeTabData.link] : []),
63+
...(activeTabData.links || []),
64+
]}
65+
buttons={activeTabData.buttons}
66+
colSizes={{all: 12}}
67+
/>
68+
</div>
69+
</Col>
70+
);
71+
72+
const mediaContent = showMedia && (
73+
<Col
74+
sizes={{all: 12, md: 8}}
75+
orders={{
76+
all: GridColumnOrderClasses.Last,
77+
md: GridColumnOrderClasses.First,
78+
}}
79+
className={b('col', {centered: centered})}
80+
>
81+
{activeTabData?.media && (
82+
<Media
83+
{...getThemedValue(activeTabData.media, theme)}
84+
key={activeTab}
85+
className={b('media')}
86+
playVideo={play}
87+
/>
88+
)}
89+
{imageProps && (
90+
<Fragment>
91+
<FullScreenImage {...imageProps} imageClassName={b('image')} />
92+
{activeTabData?.caption && (
93+
<p className={b('caption')}>{activeTabData.caption}</p>
94+
)}
95+
</Fragment>
96+
)}
97+
</Col>
98+
);
3599

36100
return (
37101
<AnimateBlock className={b()} onScroll={() => setPlay(true)} animate={animated}>
38-
<BlockHeader title={title} description={description} className={b('block-title')} />
39-
<Tabs
40-
className={b('tabs')}
41-
items={tabs}
42-
activeTab={activeTab}
43-
onSelectTab={setActiveTab}
44-
size="l"
102+
<BlockHeader
103+
title={title}
104+
description={description}
105+
className={b('block-title', {centered: centered})}
45106
/>
107+
<Row>
108+
<Col sizes={tabsColSizes}>
109+
<ButtonTabs
110+
items={tabs}
111+
onSelectTab={setActiveTab}
112+
activeTab={activeTab}
113+
className={b('tabs', {centered: centered})}
114+
/>
115+
</Col>
116+
</Row>
46117
{activeTabData && (
47-
<Row>
48-
{showMedia && (
49-
<Col
50-
sizes={{all: 12, md: 8}}
51-
orders={{
52-
all: GridColumnOrderClasses.Last,
53-
md: GridColumnOrderClasses.First,
54-
}}
55-
>
56-
{activeTabData?.media && (
57-
<Media
58-
{...getThemedValue(activeTabData.media, theme)}
59-
key={activeTab}
60-
className={b('media')}
61-
playVideo={play}
62-
/>
63-
)}
64-
{imageProps && (
65-
<Fragment>
66-
<FullScreenImage {...imageProps} imageClassName={b('image')} />
67-
{activeTabData && (
68-
<p className={b('caption')}>{activeTabData.caption}</p>
69-
)}
70-
</Fragment>
71-
)}
72-
</Col>
73-
)}
74-
<Col sizes={{all: 12, md: showMedia ? 4 : 8}} className={b('content')}>
75-
<div
76-
className={b('content-wrapper', {
77-
margin: Boolean(activeTabData?.media || imageProps),
78-
})}
79-
>
80-
<h4 className={b('content-title')}>
81-
<YFMWrapper
82-
content={activeTabData.title}
83-
modifiers={{constructor: true}}
84-
/>
85-
</h4>
86-
<YFMWrapper
87-
content={activeTabData.text}
88-
modifiers={{constructor: true}}
89-
/>
90-
<Links
91-
links={[
92-
...(activeTabData.link ? [activeTabData.link] : []),
93-
...(activeTabData.links || []),
94-
]}
95-
className={b('link')}
96-
/>
97-
</div>
98-
</Col>
118+
<Row className={b('row', {reverse: isReverse})}>
119+
{mediaContent}
120+
{textContent}
99121
</Row>
100122
)}
101123
</AnimateBlock>

0 commit comments

Comments
 (0)