Skip to content

Commit

Permalink
docs(ComponentDoc): refactor, add sidebar navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Fedyashov committed Sep 13, 2017
1 parent d288f3b commit 4adc6fa
Show file tree
Hide file tree
Showing 45 changed files with 701 additions and 374 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ coverage/
dist/
docs/build/
docs/app/docgenInfo.json
docs/app/menuInfo.json
dll/

.DS_Store
Expand Down
265 changes: 35 additions & 230 deletions docs/app/Components/ComponentDoc/ComponentDoc.js
Original file line number Diff line number Diff line change
@@ -1,252 +1,57 @@
import cx from 'classnames'
import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import React, {Component} from 'react'
import DocumentTitle from 'react-document-title'
import { Link } from 'react-router-dom'
import {Grid} from 'semantic-ui-react'

import { repoURL } from 'docs/app/utils'
import { META } from 'src/lib'
import * as semanticUIReact from 'src'
import docgenInfo from '../../docgenInfo.json'
import ComponentExamples from './ComponentExamples'
import ComponentProps from './ComponentProps'
import ComponentDocHeader from './ComponentDocHeader'
import ComponentDocLinks from './ComponentDocLinks'
import ComponentDocSee from './ComponentDocSee'
import ComponentSidebar from './ComponentSidebar'

const { Divider, Grid, Header, Icon, List } = semanticUIReact

const docgenPaths = _.keys(docgenInfo)

const pathSepRegEx = new RegExp(_.escapeRegExp(__PATH_SEP__), 'g')

const getDocgenPath = componentName => _.find(docgenPaths, path => (
new RegExp(`${__PATH_SEP__}${componentName}.js$`).test(path)
))

// no matter the OS path separator, use '/'
const getPosixPath = componentName => getDocgenPath(componentName).replace(pathSepRegEx, '/')

const getGithubSourceUrl = (componentName) => {
const posixPath = getPosixPath(componentName)
return `${repoURL}/blob/master/${posixPath}`
}

const getGithubEditUrl = (componentName) => {
const posixPath = getPosixPath(componentName)
return `${repoURL}/edit/master/${posixPath}`
}

const getSemanticUIDocsUrl = _meta => (
`https://semantic-ui.com/${_meta.type}s/${_meta.parent || _meta.name}`.toLowerCase()
)

const showPropsStyle = {
display: 'inline-flex',
margin: '1em 0.5em',
marginLeft: 0,
cursor: 'pointer',
}

const subDescriptionStyle = {
fontSize: '1.08em',
color: '#777',
}

const linkListStyle = {
position: 'absolute',
padding: '0.5em',
margin: '0.5em',
top: '0',
right: '0',
boxShadow: '0 0 1em 0.5em #f7f7f7',
background: '#f7f7f7',
}
const topRowStyle = {margin: '1em'}

export default class ComponentDoc extends Component {
static propTypes = {
_meta: PropTypes.object,
}

componentWillMount() {
this.setState({
showPropsFor: this.props._meta.name,
})
}

componentWillReceiveProps(nextProps) {
this.setState({
showPropsFor: this.state.showPropsFor ? nextProps._meta.name : null,
})
}

toggleProps = (name) => {
this.setState({
showPropsFor: this.state.showPropsFor === name ? null : name,
})
}

renderSee() {
const { _meta } = this.props
const docPath = getDocgenPath(_meta.name)
const docgen = docgenInfo[docPath]
const seeTags = _.filter(docgen.docBlock.tags, ['title', 'see'])

const seeLinks = _.map(seeTags, ({ description }) => {
const seeMeta = _.get(semanticUIReact[description], '_meta')
if (!seeMeta) return

const { type, name } = seeMeta

return (
<List.Item as={Link} key={description} to={`/${type}s/${_.kebabCase(name)}`}>
{description}
</List.Item>
)
})

// still render empty lists to reserve the whitespace
return (
<List link horizontal size='small' style={{ display: 'block' }}>
<List.Item>
<Header size='tiny' color='grey'>
{seeLinks.length > 0 ? 'See:' : ' '}
</Header>
</List.Item>
{seeLinks}
</List>
)
}

renderSemanticDocsLink = () => {
const { _meta } = this.props
state = {}

if (META.isAddon(_meta)) return null

return (
<List.Item>
<List.Icon name='book' />
<List.Content>
<a href={getSemanticUIDocsUrl(_meta)} target='_blank'>
Semantic UI {_meta.parent || _meta.name} Docs
</a>
</List.Content>
</List.Item>
)
}

renderGithubSourceLink() {
const { _meta } = this.props
const docPath = getDocgenPath(_meta.name)
// no matter the OS path separator, use '/' since these link to github
const posixPath = docPath.replace(pathSepRegEx, '/')
return (
<List.Item>
<List.Icon name='github' />
<List.Content>
<code>
<a href={getGithubSourceUrl(_meta.name)} target='_blank'>{posixPath}</a>
</code>
</List.Content>
</List.Item>
)
}

renderProps = () => {
const { _meta } = this.props
const { showPropsFor } = this.state

const itemCX = name => cx(showPropsFor === name && 'active', 'link item')
const selectedDocgen = docgenInfo[getDocgenPath(showPropsFor)]
const toggleIcon = `toggle ${showPropsFor ? 'on' : 'off'}`

const subComponents = _.flatMap(semanticUIReact, SDComponent => _.filter(SDComponent, staticValue => (
_.get(staticValue, '_meta.parent') === _meta.name
)))

const hasSubComponents = !_.isEmpty(subComponents)
const showSubDescription = hasSubComponents && _.get(selectedDocgen, 'docBlock.description')

const subComponentItems = _.map(subComponents, ({ _meta: { name } }) => (
<div key={name} className={itemCX(name)} onClick={() => this.toggleProps(name)}>
{_meta.name}.{name.replace(_meta.name, '')}
</div>
))

return (
<div>
<Header
as='h4'
className='no-anchor'
color={cx(showPropsFor ? 'green' : 'grey')}
style={showPropsStyle}
onClick={() => this.toggleProps(showPropsFor || _meta.name)}
>
<a style={{ color: 'inherit' }}><Icon name={toggleIcon} /> Props{hasSubComponents && ':'}</a>
</Header>
<div className='ui small compact secondary green menu'>
{hasSubComponents && (
<div className={itemCX(_meta.name)} onClick={() => this.toggleProps(_meta.name)}>
{_meta.name}
</div>
)}
{subComponentItems}
</div>
{selectedDocgen && (
<div>
{showSubDescription && (
<div style={subDescriptionStyle}>
{selectedDocgen.docBlock.description}
<Divider />
</div>
)}
<ComponentProps props={selectedDocgen.props} meta={semanticUIReact[showPropsFor]._meta} />
</div>
)}
</div>
)
}

renderHeader = () => {
const { _meta } = this.props
const docgen = docgenInfo[getDocgenPath(_meta.name)]

return (
<Header as='h1' style={{ marginBottom: '0.25em' }}>
{_meta.name}
<Header.Subheader>
{/* TODO: Remove once all components have descriptions */}
{docgen.docBlock.description || (
<span>
<a href={getGithubEditUrl(_meta.name)}>Add a description</a>. Instructions are{' '}
<a href={`${repoURL}/blob/master/.github/CONTRIBUTING.md#components`}>
here.
</a>
{' '}Description is in the SUI Docs, right there <Icon name='pointing right' />
</span>
)}
</Header.Subheader>
</Header>
)
}
handleExamplesRef = examplesRef => this.setState({ examplesRef })

render() {
const { _meta } = this.props
const {_meta} = this.props
const { examplesRef } = this.state

return (
<DocumentTitle title={`${_meta.name} | UI React`}>
<div>
<Grid padded columns='1'>
<DocumentTitle title={`${_meta.name} | Semantic UI React`}>
<Grid>
<Grid.Row columns='equal' style={topRowStyle}>
<Grid.Column>
{this.renderHeader()}
{this.renderSee()}
<List link style={linkListStyle}>
{this.renderGithubSourceLink()}
{this.renderSemanticDocsLink()}
</List>
{this.renderProps()}
<ComponentDocHeader componentName={_meta.name}/>
<ComponentDocSee componentName={_meta.name}/>
<ComponentDocLinks componentName={_meta.parent || _meta.name} type={_meta.type}/>
<ComponentProps componentName={_meta.name}/>
</Grid.Column>
<Grid.Column computer={5} largeScreen={4} widescreen={4}/>
</Grid.Row>

<Grid.Row columns='equal'>
<Grid.Column>
<div ref={this.handleExamplesRef}>
<ComponentExamples componentName={_meta.name}/>
</div>
</Grid.Column>
<Grid.Column computer={5} largeScreen={4} widescreen={4}>
<ComponentSidebar
componentName={_meta.parent || _meta.name}
examplesRef={examplesRef}
/>
</Grid.Column>
</Grid>
<ComponentExamples name={_meta.name} />
</div>
</Grid.Row>
</Grid>
</DocumentTitle>
)
}
Expand Down
21 changes: 21 additions & 0 deletions docs/app/Components/ComponentDoc/ComponentDocHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import PropTypes from 'prop-types'
import React from 'react'
import { Header } from 'semantic-ui-react'

import { pure } from 'docs/app/HOC'
import { getDocDescription } from 'docs/app/utils'

const headerStyle = { marginBottom: '0.25em' }

const ComponentDocHeader = ({ componentName }) => (
<Header as='h1' style={headerStyle}>
{componentName}
<Header.Subheader>{getDocDescription(componentName)}</Header.Subheader>
</Header>
)

ComponentDocHeader.propTypes = {
componentName: PropTypes.string,
}

export default pure(ComponentDocHeader)
47 changes: 47 additions & 0 deletions docs/app/Components/ComponentDoc/ComponentDocLinks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import PropTypes from 'prop-types'
import React from 'react'
import { List } from 'semantic-ui-react'

import { pure } from 'docs/app/HOC'
import { getGithubSourceUrl, getPosixPath, getSemanticUIDocsUrl } from 'docs/app/utils'

const linkListStyle = {
background: '#f7f7f7',
boxShadow: '0 0 1em 0.5em #f7f7f7',
margin: '0.5em',
padding: '0.5em',
position: 'absolute',
right: '0',
top: '0',
}

const ComponentDocLinks = ({ componentName, type }) => {
const ghLink = getGithubSourceUrl(componentName)
const suiLink = getSemanticUIDocsUrl(componentName, type)

return (
<List link style={linkListStyle}>
<List.Item
content={(
<code>
<a href={ghLink} target='_blank'>{getPosixPath(componentName)}</a>
</code>
)}
icon='github'
/>
{suiLink && (
<List.Item
content={<a href={suiLink} target='_blank'>Semantic UI {componentName} Docs</a>}
icon='book'
/>
)}
</List>
)
}

ComponentDocLinks.propTypes = {
componentName: PropTypes.string,
type: PropTypes.string,
}

export default pure(ComponentDocLinks)
Loading

0 comments on commit 4adc6fa

Please sign in to comment.