Skip to content

Commit 6ab3d04

Browse files
author
Juli Ovechkina
authored
fix: add custom height to images in Tabs (#650)
1 parent 4c3ed84 commit 6ab3d04

File tree

10 files changed

+232
-99
lines changed

10 files changed

+232
-99
lines changed

src/blocks/Tabs/Tabs.scss

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ $block: '.#{$ns}tabs-block';
66
#{$block} {
77
$class: &;
88

9-
&__block-title {
9+
&__title {
1010
margin-bottom: $indentSM;
1111

1212
@include centerable-title();
@@ -20,10 +20,6 @@ $block: '.#{$ns}tabs-block';
2020

2121
&__row_reverse {
2222
flex-direction: row-reverse;
23-
24-
#{$class}__content-wrapper {
25-
margin: $indentSM $indentM 0 0;
26-
}
2723
}
2824

2925
&__image {
@@ -45,51 +41,15 @@ $block: '.#{$ns}tabs-block';
4541
color: var(--g-color-text-secondary);
4642
}
4743

48-
&__content {
49-
display: flex;
50-
flex-direction: column;
51-
52-
&_centered {
53-
margin: 0 auto;
54-
}
55-
}
56-
5744
&__col {
5845
&_centered {
5946
margin: 0 auto;
6047
}
6148
}
6249

63-
&__content-wrapper {
64-
&_margin {
65-
margin: $indentSM 0 0 $contentMargin;
66-
}
67-
}
68-
69-
&__content-title {
70-
margin: 0 auto $indentXXS;
71-
72-
@include add-specificity(&) {
73-
& > * {
74-
@include heading4();
75-
}
76-
}
77-
}
78-
7950
@media (max-width: map-get($gridBreakpoints, 'md')) {
80-
&__content-wrapper {
81-
&_margin {
82-
margin: 0 0 $contentMargin 0;
83-
}
84-
}
85-
8651
&__row_reverse {
8752
flex-direction: column-reverse;
88-
89-
#{$class}__content > * {
90-
margin-top: $indentM;
91-
padding-bottom: 0;
92-
}
9353
}
9454
}
9555

src/blocks/Tabs/Tabs.tsx

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {Fragment, useRef, useState} from 'react';
1+
import React, {Fragment, useCallback, useRef, useState} from 'react';
22

33
import {useUniqId} from '@gravity-ui/uikit';
44

@@ -12,9 +12,10 @@ import {getHeight} from '../../components/VideoBlock/VideoBlock';
1212
import {useTheme} from '../../context/theme';
1313
import {Col, GridColumnOrderClasses, Row} from '../../grid';
1414
import {TabsBlockProps} from '../../models';
15-
import {Content} from '../../sub-blocks';
1615
import {block, getThemedValue} from '../../utils';
1716

17+
import TabsTextContent from './TabsTextContent/TabsTextContent';
18+
1819
import './Tabs.scss';
1920

2021
const b = block('tabs-block');
@@ -37,15 +38,32 @@ export const TabsBlock = ({
3738
const isReverse = direction === 'content-media';
3839
const ref = useRef<HTMLDivElement>(null);
3940
const mediaWidth = ref?.current?.offsetWidth;
40-
const mediaHeight = mediaWidth && getHeight(mediaWidth);
4141
const captionId = useUniqId();
42-
42+
const themedMedia = getThemedValue(activeTabData?.media, theme);
43+
const hasNoImage = !themedMedia?.image || !activeTabData?.image;
44+
const mediaVideoHeight = hasNoImage && mediaWidth && getHeight(mediaWidth);
45+
const [minImageHeight, setMinImageHeight] = useState(ref?.current?.offsetHeight);
46+
// TODO remove property support activeTabData?.image. Use only activeTabData?.media?.image
4347
let imageProps;
4448

49+
const handleImageHeight = useCallback(() => {
50+
setMinImageHeight(ref?.current?.offsetHeight);
51+
}, []);
52+
53+
const onSelectTab = (
54+
id: string | null,
55+
e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,
56+
) => {
57+
setActiveTab(id);
58+
handleImageHeight();
59+
e.currentTarget.scrollIntoView({inline: 'center', behavior: 'smooth', block: 'nearest'});
60+
};
61+
4562
if (activeTabData) {
46-
const themedImage = getThemedValue(activeTabData.image, theme);
63+
const themedImage = getThemedValue(activeTabData?.image, theme);
4764

4865
imageProps = themedImage && getMediaImage(themedImage);
66+
4967
if (activeTabData.caption && imageProps) {
5068
Object.assign(imageProps, {
5169
'aria-describedby': captionId,
@@ -57,29 +75,14 @@ export const TabsBlock = ({
5775
const showText = Boolean(activeTabData?.text);
5876

5977
const textContent = activeTabData && showText && (
60-
<Col
61-
sizes={{all: 12, md: showMedia ? 4 : 8}}
62-
className={b('content', {centered: centered})}
63-
>
64-
<div
65-
className={b('content-wrapper', {
66-
margin: Boolean((activeTabData?.media || imageProps) && !isReverse),
67-
})}
68-
>
69-
<Content
70-
title={activeTabData.title}
71-
text={activeTabData.text}
72-
additionalInfo={activeTabData.additionalInfo}
73-
size={contentSize}
74-
links={[
75-
...(activeTabData.link ? [activeTabData.link] : []),
76-
...(activeTabData.links || []),
77-
]}
78-
buttons={activeTabData.buttons}
79-
colSizes={{all: 12}}
80-
/>
81-
</div>
82-
</Col>
78+
<TabsTextContent
79+
showMedia={showMedia}
80+
data={activeTabData}
81+
imageProps={imageProps ? imageProps : undefined}
82+
isReverse={isReverse}
83+
contentSize={contentSize}
84+
centered={centered}
85+
/>
8386
);
8487

8588
const mediaContent = showMedia && (
@@ -91,15 +94,18 @@ export const TabsBlock = ({
9194
}}
9295
className={b('col', {centered: centered})}
9396
>
94-
<div ref={ref}>
97+
<div style={{minHeight: mediaVideoHeight || minImageHeight}}>
9598
{activeTabData?.media && (
96-
<Media
97-
{...getThemedValue(activeTabData.media, theme)}
98-
key={activeTab}
99-
className={b('media')}
100-
playVideo={play}
101-
height={mediaHeight}
102-
/>
99+
<div ref={ref}>
100+
<Media
101+
{...getThemedValue(activeTabData.media, theme)}
102+
key={activeTab}
103+
className={b('media')}
104+
playVideo={play}
105+
height={mediaVideoHeight || undefined}
106+
onImageLoad={handleImageHeight}
107+
/>
108+
</div>
103109
)}
104110
</div>
105111
{imageProps && (
@@ -115,20 +121,12 @@ export const TabsBlock = ({
115121
</Col>
116122
);
117123

118-
const onSelectTab = (
119-
id: string | null,
120-
e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,
121-
) => {
122-
setActiveTab(id);
123-
e.currentTarget.scrollIntoView({inline: 'center', behavior: 'smooth', block: 'nearest'});
124-
};
125-
126124
return (
127125
<AnimateBlock className={b()} onScroll={() => setPlay(true)} animate={animated}>
128126
<Title
129127
title={title}
130128
subtitle={description}
131-
className={b('block-title', {centered: centered})}
129+
className={b('title', {centered: centered})}
132130
/>
133131
<Row>
134132
<Col sizes={tabsColSizes}>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@import '../../../../styles/mixins';
2+
@import '../../../../styles/variables';
3+
4+
$block: '.#{$ns}tabs-block-text-content';
5+
6+
#{$block} {
7+
display: flex;
8+
flex-direction: column;
9+
10+
&_centered {
11+
margin: 0 auto;
12+
}
13+
14+
&__wrapper {
15+
margin: $indentSM 0 0 $contentMargin;
16+
17+
&_reverse {
18+
margin: $indentSM $indentM 0 0;
19+
}
20+
21+
&_no-image {
22+
margin: 0;
23+
}
24+
}
25+
26+
@media (max-width: map-get($gridBreakpoints, 'md')) {
27+
&__wrapper {
28+
margin: 0 0 $contentMargin 0;
29+
30+
&_reverse {
31+
margin-top: $indentM;
32+
padding-bottom: 0;
33+
}
34+
}
35+
}
36+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React from 'react';
2+
3+
import {Col} from '../../../grid';
4+
import {ImageDeviceProps, ImageObjectProps, TabsBlockItem, TabsBlockProps} from '../../../models';
5+
import {Content} from '../../../sub-blocks';
6+
import {block} from '../../../utils';
7+
8+
import './TabsTextContent.scss';
9+
10+
const b = block('tabs-block-text-content');
11+
12+
interface TextContentProps extends Pick<TabsBlockProps, 'centered' | 'contentSize'> {
13+
showMedia: boolean;
14+
isReverse: boolean;
15+
data: TabsBlockItem;
16+
centered?: boolean;
17+
imageProps?: ImageObjectProps | ImageDeviceProps;
18+
}
19+
20+
export const TabsTextContent = ({
21+
centered,
22+
contentSize = 's',
23+
showMedia,
24+
data,
25+
imageProps,
26+
isReverse,
27+
}: TextContentProps) => {
28+
const isImage = data?.media || imageProps;
29+
return (
30+
<Col sizes={{all: 12, md: showMedia ? 4 : 8}} className={b({centered: centered})}>
31+
<div
32+
className={b('wrapper', {
33+
reverse: isReverse,
34+
'no-image': !isImage,
35+
})}
36+
>
37+
<Content
38+
title={data.title}
39+
text={data.text}
40+
additionalInfo={data.additionalInfo}
41+
size={contentSize}
42+
links={[...(data.link ? [data.link] : []), ...(data.links || [])]}
43+
buttons={data.buttons}
44+
colSizes={{all: 12}}
45+
/>
46+
</div>
47+
</Col>
48+
);
49+
};
50+
51+
export default TabsTextContent;

0 commit comments

Comments
 (0)