Skip to content

Commit 327b17a

Browse files
Merge pull request #440 from gemini-testing/HERMIONE-161.sticky_header
feat: sticky foldable header
2 parents bf7cea3 + f2aea96 commit 327b17a

File tree

8 files changed

+106
-8
lines changed

8 files changed

+106
-8
lines changed

lib/static/components/gui.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {bindActionCreators} from 'redux';
66

77
import {ROOT} from '../../constants/extension-points';
88
import * as actions from '../modules/actions';
9-
import ControlButtons from './controls/gui-controls';
9+
import StickyHeader from './sticky-header/gui';
1010
import Loading from './loading';
1111
import ModalContainer from '../containers/modal';
1212
import MainTree from './main-tree';
@@ -81,7 +81,7 @@ class Gui extends Component {
8181
<CustomScripts scripts={customScripts}/>
8282
{notificationElem}
8383
<FaviconChanger />
84-
<ControlButtons />
84+
<StickyHeader />
8585
<main className="container">
8686
<MainTree />
8787
</main>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.header {
2+
padding-top: 15px;
23
padding-bottom: 15px;
34
border-bottom: 1px solid #ccc;
45
}

lib/static/components/report.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import {bindActionCreators} from 'redux';
77
import {ROOT} from '../../constants/extension-points';
88
import * as actions from '../modules/actions';
99
import Loading from './loading';
10-
import Header from './header';
11-
import ControlButtons from './controls/report-controls';
10+
import StickyHeader from './sticky-header/report';
1211
import MainTree from './main-tree';
1312
import CustomScripts from './custom-scripts';
1413
import FaviconChanger from './favicon-changer';
@@ -51,8 +50,7 @@ class Report extends Component {
5150
<CustomScripts scripts={this.props.customScripts}/>
5251
{notificationElem}
5352
<FaviconChanger />
54-
<Header/>
55-
<ControlButtons/>
53+
<StickyHeader />
5654
<main className="container">
5755
<MainTree />
5856
</main>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
3+
import StickyHeaderTemplate from '.';
4+
import ControlButtons from '../controls/gui-controls';
5+
6+
const StickyHeader = () => (
7+
<StickyHeaderTemplate>
8+
<ControlButtons />
9+
</StickyHeaderTemplate>
10+
);
11+
12+
export default StickyHeader;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React, {useState, useCallback} from 'react';
2+
import {throttle} from 'lodash';
3+
4+
import './index.styl';
5+
import useEventListener from '../../hooks/useEventListener';
6+
7+
const MAX_SHOW_HEADER = 10;
8+
const MIN_HIDE_HEADER = 30;
9+
10+
const StickyHeader = ({children}) => {
11+
const [scrollHeight, setScrollHeight] = useState(0);
12+
const shouldWrap = scrollHeight > MAX_SHOW_HEADER;
13+
const handleScroll = useCallback(throttle(() => {
14+
const shouldShow = scroll => (scroll < MAX_SHOW_HEADER && window.scrollY > MIN_HIDE_HEADER);
15+
const shouldHide = scroll => (scroll > MIN_HIDE_HEADER && window.scrollY < MAX_SHOW_HEADER);
16+
const shouldUpdate = scroll => shouldShow(scroll) || shouldHide(scroll);
17+
const cb = scroll => shouldUpdate(scroll)
18+
? window.scrollY
19+
: scroll;
20+
21+
setScrollHeight(cb);
22+
}, 100), [setScrollHeight]);
23+
24+
useEventListener('scroll', handleScroll);
25+
26+
return (
27+
<div className={`sticky-header sticky-header_${shouldWrap ? 'wrapped' : 'unwrapped'}`}>
28+
<div className="sticky-header__wrap" />
29+
<div className="sticky-header__content">
30+
{children}
31+
</div>
32+
</div>
33+
);
34+
};
35+
36+
export default StickyHeader;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.sticky-header
2+
display contents
3+
4+
.sticky-header__wrap
5+
position fixed
6+
width 100%
7+
height 40px
8+
z-index 1000
9+
text-align center
10+
background-color white
11+
border-bottom 1px solid #ccc
12+
transition transform 250ms ease-out 500ms
13+
transform-origin top
14+
transform translateY(-100%)
15+
16+
&::before
17+
transform translateY(50%) rotate(180deg)
18+
19+
.sticky-header__content
20+
position sticky
21+
top 0
22+
width 100%
23+
z-index 1100
24+
transform-origin top
25+
transition transform 250ms linear 250ms
26+
background-color white
27+
border-bottom 1px solid #ccc
28+
29+
&.sticky-header_unwrapped .sticky-header__wrap
30+
transition-delay 0ms
31+
32+
&.sticky-header_wrapped:not(:hover)
33+
.sticky-header__wrap
34+
transform translateY(0)
35+
36+
.sticky-header__content
37+
transform translateY(-100%) scaleY(0)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
3+
import StickyHeaderTemplate from '.';
4+
import Header from '../header';
5+
import ControlButtons from '../controls/report-controls';
6+
7+
const StickyHeader = () => (
8+
<StickyHeaderTemplate>
9+
<Header />
10+
<ControlButtons />
11+
</StickyHeaderTemplate>
12+
);
13+
14+
export default StickyHeader;

lib/static/styles.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
.report {
2323
font: 15px YS Text, Helvetica Neue, Arial, sans-serif;
2424
line-height: 20px;
25-
margin-top: 15px;
2625
margin-bottom: 15px;
2726
}
2827

@@ -285,7 +284,8 @@ main.container {
285284
.tests-group__title:before,
286285
.state-title:after,
287286
.details__summary:after,
288-
.error .details__summary:before {
287+
.error .details__summary:before,
288+
.sticky-header__wrap:before {
289289
content: '';
290290
width: 16px;
291291
height: 16px;

0 commit comments

Comments
 (0)