Skip to content

Commit

Permalink
Refactor Documentation layout components to TS
Browse files Browse the repository at this point in the history
  • Loading branch information
psdcoder committed Apr 3, 2020
1 parent 79185b5 commit 5a8821a
Show file tree
Hide file tree
Showing 14 changed files with 267 additions and 245 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
"@reach/portal": "^0.9.0",
"@reach/router": "^1.3.1",
"@reach/tooltip": "^0.9.1",
"@types/react": "^16.9.27",
"@types/styled-components": "^5.0.1",
"classnames": "^2.2.6",
"color": "^3.1.2",
"compression": "^1.7.4",
Expand Down Expand Up @@ -91,10 +89,14 @@
"@svgr/webpack": "^5.2.0",
"@types/classnames": "^2.2.10",
"@types/isomorphic-fetch": "^0.0.35",
"@types/lodash.includes": "^4.3.6",
"@types/promise-polyfill": "^6.0.3",
"@types/react": "^16.9.27",
"@types/react-collapse": "^5.0.0",
"@types/react-helmet": "^5.0.15",
"@types/react-popover": "^0.5.3",
"@types/react-slick": "^0.23.4",
"@types/styled-components": "^5.0.1",
"@types/vfile-message": "^1.0.1",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"@typescript-eslint/parser": "^2.24.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import React, { useEffect, useState } from 'react'
import Promise from 'promise-polyfill'
import { loadResource } from '../../../../utils/resources'

import { SearchArea, Input, Wrapper } from './styles'
import styles from './styles.module.css'

export default function SearchForm(props) {
declare global {
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
interface Window {
define?: { amd: boolean }
docsearch?: (opts: object) => void
}
}

const SearchForm: React.SFC = props => {
const [isLoaded, setLoaded] = useState(false)

useEffect(() => {
Expand Down Expand Up @@ -41,15 +49,18 @@ export default function SearchForm(props) {
}

return (
<SearchArea>
<Wrapper novalidate>
<Input
<div className={styles.searchArea}>
<div className={styles.container}>
<input
className={styles.input}
type="text"
id="doc-search"
placeholder={`Search docs`}
placeholder="Search docs"
{...props}
/>
</Wrapper>
</SearchArea>
</div>
</div>
)
}

export default SearchForm
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import styled from 'styled-components'

import { media } from '../../../../styles'

export const SearchArea = styled.div`
.searchArea {
box-sizing: border-box;
height: 60px;
padding-top: 10px;
Expand All @@ -17,38 +13,37 @@ export const SearchArea = styled.div`
position: sticky;
top: var(--layout-header-height-collapsed);

${media.phablet`
@media (--xs-scr) {
position: relative;
padding: 10px 20px 0;
top: 0;
`};
}

form {
input {
height: 40px;
}
`
}

export const Wrapper = styled.form`
.container {
width: 100%;
height: 100%;
display: flex;
`
}

export const Input = styled.input`
.input {
box-sizing: border-box;
display: flex;
flex: 1;
width: 240px;
height: 100%;
border-radius: 200px;
background-color: #ffffff;
border: solid 1px #dbe4ea;
padding-left: 48px;
padding-right: 24px;
border: solid 1px var(--color-lighter-blue);
border-radius: 200px;
background-color: #fff;
background-image: url('/img/search.svg');
background-repeat: no-repeat;
background-position: 15px center;
font-size: 16px;
font-weight: 500;
width: 240px;
box-sizing: border-box;
display: block;
`
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import React, { useEffect, useRef, useState } from 'react'
import cn from 'classnames'
import { Collapse } from 'react-collapse'
import PerfectScrollbar from 'perfect-scrollbar'
import PropTypes from 'prop-types'
import includes from 'lodash.includes'

import 'perfect-scrollbar/css/perfect-scrollbar.css'

import ShowOnly from '../../../ShowOnly'
import DownloadButton from '../../../DownloadButton'
import Link from '../../../Link'

import {
structure,
getParentsListFromPath,
getPathWithSoruce
} from '../../../../utils/sidebar'

import { OnlyDesktop } from '../../../../styles'

import { Menu, SectionLink, SectionLinks, Sections, SideFooter } from './styles'
import 'perfect-scrollbar/css/perfect-scrollbar.css'
import styles from './styles.module.css'

interface ISidebarMenuItemProps {
children?: Array<{ label: string; path: string; source: boolean | string }>
label: string
path: string
source: boolean | string
onClick: (e: React.MouseEvent) => void
activePaths?: Array<string>
}

function SidebarMenuItem({ children, label, path, activePaths, onClick }) {
const SidebarMenuItem: React.SFC<ISidebarMenuItemProps> = ({
children,
label,
path,
activePaths,
onClick
}) => {
const isActive = activePaths && includes(activePaths, path)
const isRootParent =
activePaths && activePaths.length > 1 && activePaths[0] === path
Expand All @@ -27,16 +41,18 @@ function SidebarMenuItem({ children, label, path, activePaths, onClick }) {
<>
<Link
href={getPathWithSoruce(path)}
as={SectionLink}
id={path}
isActive={isActive}
className={cn(
styles.sectionLink,
isActive && styles.active,
isRootParent && 'docSearch-lvl0'
)}
onClick={onClick}
className={isRootParent ? 'docSearch-lvl0' : ''}
>
{label}
</Link>
{children && (
<Collapse isOpened={isActive}>
<Collapse isOpened={!!isActive}>
{children.map(item => (
<SidebarMenuItem
key={item.path}
Expand All @@ -51,37 +67,34 @@ function SidebarMenuItem({ children, label, path, activePaths, onClick }) {
)
}

SidebarMenuItem.propTypes = {
children: PropTypes.arrayOf(PropTypes.object),
label: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
source: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]).isRequired,
onClick: PropTypes.func,
activePaths: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string),
PropTypes.bool
]).isRequired
interface ISidebarMenuProps {
currentPath: string
onClick: (e: React.MouseEvent) => void
}

export default function SidebarMenu({ id, sidebar, currentPath, onClick }) {
const psRef = useRef()
const SidebarMenu: React.SFC<ISidebarMenuProps> = ({
currentPath,
onClick
}) => {
const rootRef = useRef<HTMLDivElement>(null)
const psRef = useRef<PerfectScrollbar | undefined>(undefined)
const [isScrollHidden, setIsScrollHidden] = useState(false)
const activePaths = currentPath && getParentsListFromPath(currentPath)

useEffect(() => {
if (!psRef.current) {
psRef.current = new PerfectScrollbar(`#${id}`, {
if (!psRef.current && rootRef.current) {
psRef.current = new PerfectScrollbar(rootRef.current, {
wheelPropagation: true
})
}

const node = document.getElementById(currentPath)
const parent = document.getElementById(id)
const node = document.getElementById(currentPath.replace(/\/$/, ''))
const parent = rootRef.current

setIsScrollHidden(true)

const timeout = setTimeout(() => {
psRef.current.update()
psRef.current?.update()

if (node && parent) {
const parentHeight = parent.clientHeight
Expand All @@ -103,37 +116,37 @@ export default function SidebarMenu({ id, sidebar, currentPath, onClick }) {

return () => {
clearTimeout(timeout)
psRef.current.destroy()
psRef.current = null
psRef.current?.destroy()
psRef.current = undefined
}
}, [currentPath])
}, [])

return (
<Menu id={id} isScrollHidden={isScrollHidden}>
<Sections>
<SectionLinks>
{sidebar.map(item => (
<div
className={cn(styles.menu, isScrollHidden && styles.isScrollHidden)}
ref={rootRef}
>
<div className={styles.sections}>
<div className={styles.sectionLinks}>
{structure.map(item => (
<SidebarMenuItem
key={item.path}
activePaths={includes(activePaths, item.path) && activePaths}
activePaths={
includes(activePaths, item.path) ? activePaths : undefined
}
onClick={onClick}
{...item}
/>
))}
</SectionLinks>
</Sections>
<OnlyDesktop>
<SideFooter>
</div>
</div>
<ShowOnly on="desktop">
<div className={styles.footer}>
<DownloadButton openTop />
</SideFooter>
</OnlyDesktop>
</Menu>
</div>
</ShowOnly>
</div>
)
}

SidebarMenu.propTypes = {
id: PropTypes.string.isRequired,
sidebar: PropTypes.arrayOf(PropTypes.object).isRequired,
currentPath: PropTypes.string,
onClick: PropTypes.func
}
export default SidebarMenu
Loading

0 comments on commit 5a8821a

Please sign in to comment.