Skip to content

Commit

Permalink
fix(docz-theme-default): scrolling and overflows performance
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronauck committed Sep 11, 2018
1 parent 07ae769 commit a28ab79
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import get from 'lodash.get'

const Wrapper = styled('div')`
display: flex;
height: 100vh;
max-width: 100vw;
`

interface MainProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ interface ListProps {
}

const List = styled('dl')`
flex: 1;
overflow-y: auto;
visibility: ${(p: ListProps) => (p.opened ? 'visible' : 'hidden')};
max-height: ${(p: ListProps) => (p.opened ? '9999px' : '0px')};
transition: max-height 0.1s;
max-height: ${(p: ListProps) => (p.opened ? 'auto' : '0px')};
`

export const MenuLink = styled('a')`
Expand Down
249 changes: 139 additions & 110 deletions packages/docz-theme-default/src/components/shared/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react'
import { SFC } from 'react'
import { Docs, Entry, DocsRenderProps } from 'docz'
import { Toggle, State } from 'react-powerplug'
import { Component } from 'react'
import { Docs, Entry } from 'docz'
import withSizes from 'react-sizes'
import styled from 'react-emotion'
import match from 'match-sorter'
Expand All @@ -26,22 +25,20 @@ const position = (p: WrapperProps) =>
})

const Wrapper = styled('div')`
display: flex;
flex-direction: column;
position: relative;
width: 280px;
min-width: 280px;
height: 100%;
min-height: 100vh;
background: ${(p: WrapperProps) => p.theme.docz.colors.sidebarBg};
transition: transform 0.2s, background 0.3s;
z-index: 100;
${position};
${p => p.theme.docz.styles.sidebar};
dl {
padding: 0;
margin: 0 0 0 16px;
margin: 0 16px;
}
dl a {
Expand All @@ -53,6 +50,18 @@ const Wrapper = styled('div')`
}
`

const Content = styled('div')`
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
width: 280px;
min-width: 280px;
height: 100%;
max-height: 100vh;
`

const Menus = styled('nav')`
flex: 1;
overflow-y: auto;
Expand Down Expand Up @@ -104,116 +113,136 @@ const FooterLogo = styled(Docz)`
fill: ${p => p.theme.docz.colors.footerText};
`

interface Toggle {
on: boolean
toggle: () => void
interface SidebarState {
docs: Entry[] | null
searching: boolean
lastVal: string
showing: boolean
}

interface State {
setState: (state: any) => void
state: {
docs?: Entry[] | null
searching?: boolean
lastVal: string
}
interface SidebarProps {
isDesktop: boolean
}

type RenderProps = DocsRenderProps & Toggle & State

interface ComposedProps {
children: (renderProps: RenderProps) => React.ReactNode
}
class SidebarBase extends Component<SidebarProps, SidebarState> {
public state = {
docs: null,
lastVal: '',
searching: false,
showing: true,
}

const Composed: SFC<ComposedProps> = ({ children }) => (
<Docs>
{docs => (
<State initial={{ docs: null, searching: false, lastVal: '' }}>
{(state: any) => (
<Toggle initial={true}>
{(toggle: any) => children({ ...docs, ...toggle, ...state })}
</Toggle>
)}
</State>
)}
</Docs>
)
public componentDidUpdate(pProps: SidebarProps, pState: SidebarState): void {
if (pState.showing !== this.state.showing) {
this.addOverlayClass()
}
}

interface SidebarProps {
isDesktop: boolean
}
public componentDidMount(): void {
this.addOverlayClass()
}

const SidebarBase: SFC<SidebarProps> = ({ isDesktop }) => (
<Composed>
{({ menus, docs: initialDocs, toggle, on, state, setState }) => {
const docs = state.docs || initialDocs
const docsWithoutMenu = docs.filter((doc: Entry) => !doc.menu)

const fromMenu = (menu: string) => docs.filter(doc => doc.menu === menu)
const search = (val: string) => {
const change = !val.startsWith(state.lastVal)
setState({ lastVal: val })
if (change) return match(initialDocs, val, { keys: ['name'] })
return match(docs, val, { keys: ['name'] })
}

const handleSearchDocs = (val: string) => {
const isEmpty = val.length === 0

setState({
docs: isEmpty ? initialDocs : search(val),
searching: !isEmpty,
})
}

const handleSidebarToggle = () => {
if (isDesktop) return
toggle && toggle()
}

return (
<React.Fragment>
<Wrapper opened={on}>
<Hamburguer opened={!on} onClick={handleSidebarToggle} />
<Logo showBg={!on} />
<Search onSearch={handleSearchDocs} />
{docs.length < 1 ? (
<Empty>No documents found.</Empty>
) : (
<Menus>
{docsWithoutMenu.map(doc => (
<Link
key={doc.id}
to={doc.route}
onClick={handleSidebarToggle}
doc={doc}
>
{doc.name}
</Link>
))}
{menus.map(menu => (
<Menu
key={menu}
menu={menu}
docs={fromMenu(menu)}
sidebarToggle={handleSidebarToggle}
collapseAll={Boolean(state.searching)}
public render(): React.ReactNode {
const { showing } = this.state

return (
<Docs>
{({ menus, docs: initialDocs }) => {
const docs = this.state.docs || initialDocs
const docsWithoutMenu = docs.filter((doc: Entry) => !doc.menu)

return (
<React.Fragment>
<Wrapper opened={showing}>
<Content>
<Hamburguer
opened={!showing}
onClick={this.handleSidebarToggle}
/>
))}
</Menus>
)}
<Footer>
Built with
<FooterLink href="https://docz.site" target="_blank">
<FooterLogo width={40} />
</FooterLink>
</Footer>
</Wrapper>
<ToggleBackground opened={on} onClick={handleSidebarToggle} />
</React.Fragment>
)
}}
</Composed>
)
<Logo showBg={!showing} />
<Search onSearch={this.handleSearchDocs(initialDocs, docs)} />
{docs.length < 1 ? (
<Empty>No documents found.</Empty>
) : (
<Menus>
{docsWithoutMenu.map(doc => (
<Link
key={doc.id}
to={doc.route}
onClick={this.handleSidebarToggle}
doc={doc}
>
{doc.name}
</Link>
))}
{menus.map(menu => (
<Menu
key={menu}
menu={menu}
docs={this.fromMenu(docs, menu)}
sidebarToggle={this.handleSidebarToggle}
collapseAll={Boolean(this.state.searching)}
/>
))}
</Menus>
)}
<Footer>
Built with
<FooterLink href="https://docz.site" target="_blank">
<FooterLogo width={40} />
</FooterLink>
</Footer>
</Content>
</Wrapper>
<ToggleBackground
opened={showing}
onClick={this.handleSidebarToggle}
/>
</React.Fragment>
)
}}
</Docs>
)
}

private addOverlayClass = () => {
const { isDesktop } = this.props
const { showing } = this.state

if (window && typeof window !== 'undefined' && !isDesktop) {
!showing && document.documentElement.classList.add('with-overlay')
showing && document.documentElement.classList.remove('with-overlay')
}
}

private fromMenu = (docs: Entry[], menu: string) => {
return docs.filter(doc => doc.menu === menu)
}

private search = (initialDocs: Entry[], docs: Entry[], val: string) => {
const change = !val.startsWith(this.state.lastVal)

this.setState({ lastVal: val })
if (change) return match(initialDocs, val, { keys: ['name'] })
return match(docs, val, { keys: ['name'] })
}

private handleSearchDocs = (initialDocs: Entry[], docs: Entry[]) => (
val: string
) => {
const isEmpty = val.length === 0

this.setState({
docs: isEmpty ? initialDocs : this.search(initialDocs, docs, val),
searching: !isEmpty,
})
}

private handleSidebarToggle = () => {
if (this.props.isDesktop) return
this.setState({ showing: !this.state.showing })
}
}

const mapSizesToProps = ({ width }: { width: number }) => ({
isDesktop: width >= breakpoints.desktop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Toggle } from 'react-powerplug'

import { Button as BaseButton } from './Button'

type AnimatedButtonProps = React.ButtonHTMLAttributes<any> & {
export type AnimatedButtonProps = React.ButtonHTMLAttributes<any> & {
as?: React.ComponentType<React.ButtonHTMLAttributes<any>>
swap?: React.ReactNode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const ClipboardAction: SFC<ClipboardActionProps> = ({
}) => (
<ActionButton
{...props}
as={ButtonLink}
as={ButtonLink as any}
title="Copy to clipboard"
onClick={() => copy(content)}
swap={<Check width={17} />}
Expand Down
3 changes: 0 additions & 3 deletions packages/docz-theme-default/src/components/ui/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@ import { GithubLink, Sidebar, Main } from '../shared'

const Wrapper = styled('div')`
flex: 1;
height: 100%;
overflow-y: auto;
color: ${p => p.theme.docz.colors.text};
background: ${p => p.theme.docz.colors.background};
`

export const Container = styled('div')`
position: relative;
margin: 0 auto;
max-width: 100%;
${p => p.theme.docz.mq(p.theme.docz.styles.container)};
`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export class Render extends Component<RenderComponentProps, RenderState> {

return {
minHeight: fullscreen ? 360 : '100%',
minWidth: 320,
minWidth: 260,
maxWidth: '100%',
maxHeight: '100%',
size: {
Expand Down
Loading

0 comments on commit a28ab79

Please sign in to comment.