Skip to content

Commit 99122a9

Browse files
author
berdysheva
committed
fix(Header): use react-hook
1 parent 930f041 commit 99122a9

File tree

5 files changed

+117
-163
lines changed

5 files changed

+117
-163
lines changed

src/components/navigation/components/Header/Header.scss

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33

44
.header {
55
$root: &;
6-
$searchHeight: 36px;
7-
$searchWidth: 122px;
8-
$searchButtonWidth: 36px;
9-
$searchBreakpoint: 1120px;
6+
107
position: sticky;
118
z-index: 98;
129
top: 0;
@@ -46,11 +43,11 @@
4643

4744
&__navigation {
4845
position: relative;
46+
margin-right: $normalOffset;
4947

5048
flex: 1 0 0;
5149
justify-content: flex-start;
5250

53-
margin-right: $normalOffset;
5451
@include desktop-only();
5552
}
5653

Lines changed: 83 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import React, {createRef, MouseEvent} from 'react';
1+
import React, {MouseEvent, useCallback, useState} from 'react';
22
import block from 'bem-cn-lite';
3+
4+
import {HeaderData, NavigationLogo} from '../../../../models';
35
import {Col, Grid, Row} from '../../../../grid';
46
import OutsideClick from '../../../OutsideClick/OutsideClick';
57
import Control from '../../../Control/Control';
6-
7-
import Logo from '../Logo/Logo';
8-
9-
import {HeaderData, NavigationLogo} from '../../../../models';
108
import Navigation from '../Navigation/Navigation';
119
import MobileNavigation from '../MobileNavigation/MobileNavigation';
1210
import NavigationItem from '../NavigationItem/NavigationItem';
11+
import Logo from '../Logo/Logo';
1312

1413
import {NavigationClose, NavigationOpen} from '../../../../icons';
1514

@@ -22,136 +21,99 @@ export interface HeaderProps {
2221
data: HeaderData;
2322
}
2423

25-
interface HeaderState {
26-
isSidebarOpened: boolean;
27-
activeItemIndex: number;
28-
}
29-
30-
class Header extends React.Component<HeaderProps, HeaderState> {
31-
ref = createRef();
32-
state = {
33-
isSidebarOpened: false,
34-
activeItemIndex: -1,
35-
};
36-
37-
render() {
38-
return (
39-
<Grid className={b()}>
40-
<Row>
41-
<Col>
42-
<header className={b('wrapper')}>
43-
{this.renderLogo()}
44-
{this.renderLeft()}
45-
{this.renderRight()}
46-
{this.renderMobileNavigation()}
47-
</header>
48-
</Col>
49-
</Row>
50-
</Grid>
51-
);
52-
}
53-
54-
private renderLeft() {
55-
const {activeItemIndex} = this.state;
56-
const {leftItems} = this.props.data;
57-
58-
return (
59-
leftItems && (
60-
<div className={b('navigation-container')}>
61-
<Navigation
62-
className={b('navigation')}
63-
links={leftItems}
64-
activeItemIndex={activeItemIndex}
65-
onActiveItemChange={this.onActiveItemChange}
66-
/>
67-
</div>
68-
)
69-
);
70-
}
71-
72-
private renderLogo() {
73-
const {logo} = this.props;
74-
75-
if (!logo) {
76-
return null;
77-
}
78-
79-
return (
80-
<div className={b('left')}>
81-
<Logo {...logo} className={b('logo')} />
82-
</div>
83-
);
84-
}
85-
86-
private renderRight() {
87-
return (
88-
<div className={b('right')}>
89-
{this.renderMobileMenuButton()}
90-
{this.renderRightItems()}
91-
</div>
92-
);
93-
}
94-
95-
private renderRightItems() {
96-
const {rightItems} = this.props.data;
97-
98-
return (
99-
rightItems && (
100-
<div className={b('buttons')}>
101-
{rightItems.map((button) => (
102-
<NavigationItem key={button.text} data={button} className={b('button')} />
103-
))}
104-
</div>
105-
)
106-
);
107-
}
24+
export const Header: React.FC<HeaderProps> = ({data, logo}) => {
25+
const {leftItems, rightItems} = data;
26+
const [isSidebarOpened, setIsSidebarOpened] = useState(false);
27+
const [activeItemIndex, setActiveItemIndex] = useState(-1);
28+
29+
const onActiveItemChange = useCallback((index) => {
30+
setActiveItemIndex(index);
31+
}, []);
32+
33+
const onSidebarOpenedChange = useCallback((isOpen: boolean) => {
34+
setIsSidebarOpened(isOpen);
35+
}, []);
36+
37+
const hideSidebar = useCallback(() => {
38+
setIsSidebarOpened(false);
39+
}, []);
40+
41+
const renderLogo = (
42+
<div className={b('left')}>
43+
<Logo {...logo} className={b('logo')} />
44+
</div>
45+
);
46+
47+
const renderLeft = (
48+
<div className={b('navigation-container')}>
49+
<Navigation
50+
className={b('navigation')}
51+
links={leftItems}
52+
activeItemIndex={activeItemIndex}
53+
onActiveItemChange={onActiveItemChange}
54+
/>
55+
</div>
56+
);
10857

109-
private renderMobileMenuButton() {
110-
const {isSidebarOpened} = this.state;
58+
const renderMobileMenuButton = () => {
11159
const iconProps = {icon: isSidebarOpened ? NavigationClose : NavigationOpen, iconSize: 36};
11260

11361
return (
11462
<Control
11563
className={b('mobile-menu-button')}
11664
onClick={(e: MouseEvent) => {
11765
e.stopPropagation();
118-
this.onSidebarOpenedChange(!isSidebarOpened);
66+
onSidebarOpenedChange(!isSidebarOpened);
11967
}}
12068
size="l"
12169
{...iconProps}
12270
/>
12371
);
124-
}
125-
126-
private renderMobileNavigation() {
127-
const {leftItems, rightItems} = this.props.data;
128-
const {isSidebarOpened, activeItemIndex} = this.state;
129-
130-
return (
131-
<OutsideClick onOutsideClick={() => this.onSidebarOpenedChange(false)}>
132-
<MobileNavigation
133-
topItems={leftItems}
134-
bottomItems={rightItems}
135-
isOpened={isSidebarOpened}
136-
activeItemIndex={activeItemIndex}
137-
onActiveItemChange={this.onActiveItemChange}
138-
onClose={this.hideSidebar}
139-
/>
140-
</OutsideClick>
141-
);
142-
}
143-
144-
private onActiveItemChange = (index: number) => {
145-
this.setState({activeItemIndex: index});
14672
};
14773

148-
private onSidebarOpenedChange = (isSidebarOpened: boolean) => {
149-
this.setState({isSidebarOpened});
150-
};
151-
152-
private hideSidebar = () => {
153-
this.setState({isSidebarOpened: false});
154-
};
155-
}
74+
const renderRightItems = (
75+
<div className={b('buttons')}>
76+
{rightItems &&
77+
rightItems.map((button) => (
78+
<NavigationItem key={button.text} data={button} className={b('button')} />
79+
))}
80+
</div>
81+
);
82+
83+
const renderRight = (
84+
<div className={b('right')}>
85+
{renderMobileMenuButton()}
86+
{rightItems && renderRightItems}
87+
</div>
88+
);
89+
90+
const renderMobileNavigation = (
91+
<OutsideClick onOutsideClick={() => onSidebarOpenedChange(false)}>
92+
<MobileNavigation
93+
topItems={leftItems}
94+
bottomItems={rightItems}
95+
isOpened={isSidebarOpened}
96+
activeItemIndex={activeItemIndex}
97+
onActiveItemChange={onActiveItemChange}
98+
onClose={hideSidebar}
99+
/>
100+
</OutsideClick>
101+
);
102+
103+
return (
104+
<Grid className={b()}>
105+
<Row>
106+
<Col>
107+
<header className={b('wrapper')}>
108+
{logo && renderLogo}
109+
{leftItems && renderLeft}
110+
{renderRight}
111+
{renderMobileNavigation}
112+
</header>
113+
</Col>
114+
</Row>
115+
</Grid>
116+
);
117+
};
156118

157119
export default Header;

src/components/navigation/components/MobileNavigation/MobileNavigation.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
border-bottom-right-radius: $borderRadius;
1313
border-bottom-left-radius: $borderRadius;
1414
background-color: var(--yc-color-base-background);
15-
box-shadow: 0px 3px 10px var(--yc-color-sfx-shadow);
15+
box-shadow: 0 3px 10px var(--yc-color-sfx-shadow);
16+
1617
@include text-size(body-2);
1718
@include mobile-tablet-only();
1819

src/components/navigation/components/NavigationItem/NavigationItem.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,27 +70,30 @@ const NavigationDropdown: React.FC<NavigationDropdownProps> = ({
7070
type NavigationLinkProps = NavigationItemProps & NavigationLinkItem;
7171

7272
const NavigationLink: React.FC<NavigationLinkProps> = (props) => {
73-
const {hostname} = useContext(LocationContext);
73+
const {hostname, Link} = useContext(LocationContext);
7474
const {url, text, icon, arrow, target, ...rest} = props;
7575
const linkExtraProps = getLinkProps(url, hostname, target);
7676
const iconData = icon && getMediaImage(icon);
77-
7877
const content = (
7978
<Fragment>
8079
<Content text={text} icon={iconData} />
8180
{arrow && <NavigationArrow className={b('arrow')} />}
8281
</Fragment>
8382
);
8483

85-
return linkExtraProps?.target ? (
86-
<a href={url} title={text} {...rest} {...linkExtraProps}>
87-
{content}
88-
</a>
89-
) : (
90-
<RouterLink href={url} passHref>
91-
<a {...rest}>{content}</a>
92-
</RouterLink>
93-
);
84+
if (linkExtraProps?.target || !Link) {
85+
return (
86+
<a href={url} title={text} {...rest} {...linkExtraProps}>
87+
{content}
88+
</a>
89+
);
90+
} else {
91+
return (
92+
<RouterLink href={url} passHref>
93+
<a {...rest}>{content}</a>
94+
</RouterLink>
95+
);
96+
}
9497
};
9598

9699
const NavigationButton: React.FC<ButtonProps> = (props) => {

src/containers/PageConstructor/__stories__/data.json

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,14 @@
126126
}
127127
},
128128
"navigation": {
129+
"logo": {
130+
"icon": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/icon_1_light.svg",
131+
"text": "Logo"
132+
},
129133
"header": {
130134
"leftItems": [
131135
{
132-
"text": "Lorem",
136+
"text": "Dropdown 1",
133137
"type": "dropdown",
134138
"items": [
135139
{
@@ -151,7 +155,7 @@
151155
]
152156
},
153157
{
154-
"text": "Ipsum",
158+
"text": "Dropdown 2",
155159
"type": "dropdown",
156160
"items": [
157161
{
@@ -173,37 +177,24 @@
173177
]
174178
},
175179
{
176-
"text": "Dolor",
177-
"type": "dropdown",
178-
"items": [
179-
{
180-
"text": "Lorem ipsum ",
181-
"url": "https://example.com"
182-
},
183-
{
184-
"text": "Dolor sit amet",
185-
"url": "https://example.com"
186-
},
187-
{
188-
"text": "Consectetur adipiscing",
189-
"url": "https://example.com"
190-
},
191-
{
192-
"text": "Ut enim ad minim ",
193-
"url": "https://example.com"
194-
}
195-
]
180+
"text": "Link 1",
181+
"url": "http://localhost:7009/downloads",
182+
"icon": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/icon_3_light.svg"
183+
},
184+
{
185+
"text": "Link 2",
186+
"url": "/../en/downloads"
196187
}
197188
],
198189
"rightItems": [
199190
{
200-
"text": "Lorem",
191+
"text": "Link",
201192
"url": "https://example.com",
202-
"icon": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/icon_1_light.svg"
193+
"icon": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/icon_2_light.svg"
203194
},
204195
{
205196
"type": "button",
206-
"text": "Ipsum",
197+
"text": "Button",
207198
"url": "https://example.com",
208199
"theme": "pseudo"
209200
}

0 commit comments

Comments
 (0)