mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-08 07:56:12 +02:00
feat: create sticky version of components involved
Notices problems are - Links in content area are higher (in terms of z value) than the sticky header. - The sidebar header for table of contents seems to be positioned higher than it should. - Text size of breadcrumb and title are too big. - Flickering problem on pages that are short (less content/one page content).
This commit is contained in:
committed by
Jean-Philippe Sirois
parent
5ba1e86672
commit
8a5970107f
@@ -17,7 +17,7 @@ interface IBoxedTitleProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HeaderBareboneState = {
|
type HeaderBareboneState = {
|
||||||
scrollY: Number
|
scrollY: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const BoxedTitle: React.FC<IBoxedTitleProps> = (props) => {
|
const BoxedTitle: React.FC<IBoxedTitleProps> = (props) => {
|
||||||
@@ -39,6 +39,29 @@ const BoxedTitle: React.FC<IBoxedTitleProps> = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StickyBoxedTitle: React.FC<IBoxedTitleProps> = (props) => {
|
||||||
|
return (
|
||||||
|
<SC.StickyBox>
|
||||||
|
{props.above}
|
||||||
|
|
||||||
|
<SC.Title
|
||||||
|
className={cx({
|
||||||
|
"has-content-above": props.above,
|
||||||
|
"has-content-below": props.content,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</SC.Title>
|
||||||
|
|
||||||
|
{props.content}
|
||||||
|
</SC.StickyBox>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const StickyContainer: React.FC = ({ children, ...restProps }) => {
|
||||||
|
return <SC.StickyContainerWrapper {...restProps}>{children}</SC.StickyContainerWrapper>
|
||||||
|
}
|
||||||
|
|
||||||
const debounce = (fn) => {
|
const debounce = (fn) => {
|
||||||
let frame
|
let frame
|
||||||
return (...params) => {
|
return (...params) => {
|
||||||
@@ -52,11 +75,15 @@ const debounce = (fn) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class HeaderBarebone extends Component<IHeaderBareboneProps, HeaderBareboneState> {
|
export class HeaderBarebone extends Component<IHeaderBareboneProps, HeaderBareboneState> {
|
||||||
|
controller: AbortController
|
||||||
|
state: HeaderBareboneState = {
|
||||||
|
scrollY: 0
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.tick = this.tick.bind(this)
|
this.tick = this.tick.bind(this)
|
||||||
this.state = { scrollY: 0 }
|
this.controller = new AbortController()
|
||||||
}
|
}
|
||||||
|
|
||||||
tick() {
|
tick() {
|
||||||
@@ -67,32 +94,51 @@ export class HeaderBarebone extends Component<IHeaderBareboneProps, HeaderBarebo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentDidMount() {
|
||||||
|
document.addEventListener('scroll', debounce(this.tick), { passive: true, signal: this.controller.signal })
|
||||||
this.tick()
|
this.tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentWillUnmount() {
|
||||||
document.addEventListener('scroll', debounce(this.tick), { passive: true })
|
this.controller.abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
const isBoxed = props.above || props.content
|
const isBoxed = props.above || props.content
|
||||||
|
|
||||||
return (
|
if (this.state.scrollY <= 250) {
|
||||||
|
return (
|
||||||
<SC.HeaderWrapper className={props.className}>
|
<SC.HeaderWrapper className={props.className}>
|
||||||
<SC.Background />
|
<SC.Background />
|
||||||
|
|
||||||
<Container>
|
<Container>
|
||||||
{(isBoxed && this.state.scrollY < 30) && (
|
{isBoxed && (
|
||||||
<BoxedTitle above={props.above} content={props.content}>
|
<BoxedTitle above={props.above} content={props.content}>
|
||||||
{props.title}
|
{props.title}
|
||||||
</BoxedTitle>
|
</BoxedTitle>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isBoxed && <SC.SingleTitle>{props.title}</SC.SingleTitle>}
|
{!isBoxed && <SC.SingleTitle>{props.title}</SC.SingleTitle>}
|
||||||
</Container>
|
</Container>
|
||||||
</SC.HeaderWrapper>
|
</SC.HeaderWrapper>
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<SC.HeaderWrapperSticky className={props.className}>
|
||||||
|
<SC.Background />
|
||||||
|
|
||||||
|
<StickyContainer>
|
||||||
|
{isBoxed && (
|
||||||
|
<StickyBoxedTitle above={props.above}>
|
||||||
|
{props.title}
|
||||||
|
</StickyBoxedTitle>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!isBoxed && <SC.SingleTitle>{props.title}</SC.SingleTitle>}
|
||||||
|
</StickyContainer>
|
||||||
|
</SC.HeaderWrapperSticky>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ import HeaderMobile from "../../images/header-mobile-375x300.png"
|
|||||||
const spaceAbove = 67
|
const spaceAbove = 67
|
||||||
const height = 300 - spaceAbove
|
const height = 300 - spaceAbove
|
||||||
|
|
||||||
|
export const StickyContainerWrapper = styled.div`
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
`
|
||||||
|
|
||||||
export const HeaderWrapper = styled.div`
|
export const HeaderWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -34,6 +39,31 @@ export const HeaderWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const HeaderWrapperSticky = styled.div`
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 7px;
|
||||||
|
padding-top: ${spaceAbove}px;
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
&.shifted {
|
||||||
|
width: calc(100% - 305px);
|
||||||
|
padding-right: 305px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
width: 100% !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
height: auto;
|
||||||
|
min-height: ${height}px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
export const Background = styled.div`
|
export const Background = styled.div`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -99,6 +129,39 @@ export const Box = styled.div`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const StickyBox = styled.div`
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
background: ${(props) => transparentize(0.3, props.theme.main.background)};
|
||||||
|
padding: 16px;
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
max-width: 100%;
|
||||||
|
left: 32px;
|
||||||
|
right: 32px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
position: static;
|
||||||
|
bottom: auto;
|
||||||
|
top: auto;
|
||||||
|
margin: 32px 0;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
@-moz-document url-prefix() {
|
||||||
|
& {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const title = css`
|
const title = css`
|
||||||
font-family: ${fontFamily.header};
|
font-family: ${fontFamily.header};
|
||||||
font-size: 34px;
|
font-size: 34px;
|
||||||
|
|||||||
Reference in New Issue
Block a user