1module Container.Header where
5import CSS.Safer (cssSafer)
6import Data.Int (toNumber)
7import Data.Maybe (Maybe(..))
8import Data.Monoid (guard)
9import Data.Newtype (class Newtype)
10import Data.Nullable (Nullable, null)
12import Effect.Class.Console (log)
13import React.Basic.DOM as R
14import React.Basic.Hooks (type (/\), Hook, ReactComponent, Ref, UseLayoutEffect, UseRef, UseState, coerceHook, component, element, readRefMaybe, useLayoutEffect, useRef, useState, (/\))
15import React.Basic.Hooks as React
16import SVG.Icon (trianglelogoIcon)
17import Theme.Styles (makeStyles)
18import Theme.Types (CSSTheme)
19import Typography.Header (HeadingLevel(..), mkH)
21import Web.Event.Event (EventType(..))
22import Web.Event.EventTarget (EventListener, addEventListener, eventListener, removeEventListener)
23import Web.HTML (HTMLElement, window)
24import Web.HTML.HTMLElement (offsetTop)
25import Web.HTML.HTMLElement as HTMLElement
26import Web.HTML.Window (scrollY, toEventTarget)
28mkHeader ∷ Effect (ReactComponent {})
32 makeStyles \(theme ∷ CSSTheme) ->
35 { backgroundColor: theme.backgroundColour
37 , fontFamily: theme.headingFontFamily
40 , alignItems: "center"
41 , justifyContent: "flex-end"
45 , sticky: cssSafer { position: "fixed", top: "0" }
46 , title: cssSafer { paddingRight: "30px"}
54 , fill: theme.textColour
57 component "Header" \{} -> React.do
59 shouldBeSticky /\ nodeRef <- useShouldBeSticky
63 , className: classes.header <> " " <> guard shouldBeSticky classes.sticky
65 [ element h { level: H2, text: "Kleislove", className: Just classes.title }
66 , R.div { children: [ element trianglelogoIcon {} ], className: classes.logo }
70newtype UseShouldBeSticky hooks
71 = UseShouldBeSticky (UseLayoutEffect Unit (UseState Boolean (UseRef (Nullable Node) hooks)))
73derive instance ntUseScrollYPosition ∷ Newtype (UseShouldBeSticky hooks) _
75useShouldBeSticky ∷ Hook UseShouldBeSticky (Boolean /\ Ref (Nullable Node))
78 nodeRef <- useRef null
79 mustBeSticky /\ modifyMustBeSticky <- useState false
80 let setSticky = modifyMustBeSticky <<< const
81 useLayoutEffect unit do
82 maybeNode <- readRefMaybe nodeRef
83 case maybeNode >>= HTMLElement.fromNode of
85 log "Could not register listener because there was no node"
88 listener <- makeListener setSticky element
89 registerListener listener
90 pure (mustBeSticky /\ nodeRef)
92scrollEventType ∷ EventType
93scrollEventType = EventType "scroll"
95registerListener ∷ EventListener -> Effect (Effect Unit)
96registerListener listener = do
97 target <- window <#> toEventTarget
98 addEventListener scrollEventType listener false target
99 pure $ removeEventListener scrollEventType listener false target
101makeListener ∷ (Boolean -> Effect Unit) -> HTMLElement -> Effect EventListener
102makeListener setSticky element = do
103 nodeStartPos <- offsetTop element
104 eventListener $ const do
105 yPos <- window >>= scrollY <#> toNumber
106 setSticky $ nodeStartPos < yPos
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list