From e800405db183f19a256cca533f4699c263c0f9eb Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Tue, 24 Jan 2017 19:32:19 +0200 Subject: [PATCH] Add basic Styleguide --- src/components/Hello/Hello.example.js | 13 ++ src/components/Hello/Hello.js | 9 ++ src/components/examples.js | 4 + .../StyleguidePage/StyleguidePage.css | 6 + .../StyleguidePage/StyleguidePage.js | 114 ++++++++++++++++++ src/containers/index.js | 4 +- src/routesConfiguration.js | 25 ++++ 7 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/components/Hello/Hello.example.js create mode 100644 src/components/Hello/Hello.js create mode 100644 src/components/examples.js create mode 100644 src/containers/StyleguidePage/StyleguidePage.css create mode 100644 src/containers/StyleguidePage/StyleguidePage.js diff --git a/src/components/Hello/Hello.example.js b/src/components/Hello/Hello.example.js new file mode 100644 index 00000000..b109e6af --- /dev/null +++ b/src/components/Hello/Hello.example.js @@ -0,0 +1,13 @@ +import Hello from './Hello'; + +export const HelloWorld = { + component: Hello, + description: 'Hello to world', + props: { name: 'world' }, +}; + +export const HelloMars = { + component: Hello, + description: 'Hello to mars', + props: { name: 'mars' }, +}; diff --git a/src/components/Hello/Hello.js b/src/components/Hello/Hello.js new file mode 100644 index 00000000..3cb026de --- /dev/null +++ b/src/components/Hello/Hello.js @@ -0,0 +1,9 @@ +import React, { PropTypes } from 'react'; + +const Hello = ({ name }) =>

hello, {name}!

; + +const { string } = PropTypes; + +Hello.propTypes = { name: string.isRequired }; + +export default Hello; diff --git a/src/components/examples.js b/src/components/examples.js new file mode 100644 index 00000000..0d0b9135 --- /dev/null +++ b/src/components/examples.js @@ -0,0 +1,4 @@ +/* eslint-disable import/prefer-default-export*/ +import * as Hello from './Hello/Hello.example'; + +export { Hello }; diff --git a/src/containers/StyleguidePage/StyleguidePage.css b/src/containers/StyleguidePage/StyleguidePage.css new file mode 100644 index 00000000..b5367cc9 --- /dev/null +++ b/src/containers/StyleguidePage/StyleguidePage.css @@ -0,0 +1,6 @@ +.root { + & ul { + list-style: none; + padding: 0; + } +} diff --git a/src/containers/StyleguidePage/StyleguidePage.js b/src/containers/StyleguidePage/StyleguidePage.js new file mode 100644 index 00000000..131c291f --- /dev/null +++ b/src/containers/StyleguidePage/StyleguidePage.js @@ -0,0 +1,114 @@ +import React, { PropTypes } from 'react'; +import { Link } from 'react-router'; +import { map, size } from 'lodash'; +import * as allExamples from '../../components/examples'; + +import css from './StyleguidePage.css'; + +const ALL = '*'; + +const Example = props => { + const { + componentName, + exampleName, + component: ExampleComponent, + description, + props: exampleProps, + } = props; + const desc = description ?

Description: {description}

: null; + return ( +
  • +

    + {componentName}/ + {exampleName} +

    + raw + {desc} +
    + +
    +
  • + ); +}; + +const { string, oneOfType, func, node, object, objectOf, shape } = PropTypes; + +Example.defaultProps = { description: null, props: {} }; + +Example.propTypes = { + componentName: string.isRequired, + exampleName: string.isRequired, + component: oneOfType([ func, node ]).isRequired, + description: string, + props: object, +}; + +const Examples = props => { + const { examples } = props; + const toExamples = (exmpls, name) => ( +
  • + +
  • + ); + return ( + + ); +}; + +Examples.propTypes = { examples: objectOf(objectOf(object)).isRequired }; + +const examplesFor = (examples, componentName, exampleName) => { + // All components, all examples + if (componentName === ALL) { + return examples; + } + + // Specific component, all examples + const component = examples[componentName]; + if (exampleName === ALL) { + return component ? { [componentName]: component } : {}; + } + + // Specific component, specific example + const example = component ? component[exampleName] : null; + return example ? { [componentName]: { [exampleName]: example } } : {}; +}; + +const StyleguidePage = props => { + const { params } = props; + const component = params.component || ALL; + const example = params.example || ALL; + const raw = params.type === 'raw'; + const examples = examplesFor(allExamples, component, example); + + // Raw examples are rendered without any wrapper + if (raw && examples[component] && examples[component][example]) { + const { component: ExampleComponent, props: exampleProps } = examples[component][example]; + return ; + } else if (raw) { + return

    No example with filter {component}/{example}/raw

    ; + } + + const html = size(examples) > 0 + ? + :

    No examples with filter: {component}/{example}

    ; + + return ( +
    +

    Styleguide

    + {html} +
    + ); +}; + +StyleguidePage.propTypes = { params: shape({ component: string, example: string }).isRequired }; + +export default StyleguidePage; diff --git a/src/containers/index.js b/src/containers/index.js index 77df1a0a..c2a99d14 100644 --- a/src/containers/index.js +++ b/src/containers/index.js @@ -6,6 +6,7 @@ import InboxPage from './InboxPage/InboxPage'; import LandingPage from './LandingPage/LandingPage'; import ListingPage from './ListingPage/ListingPage'; import ManageListingsPage from './ManageListingsPage/ManageListingsPage'; +import NotFoundPage from './NotFoundPage/NotFoundPage'; import OrderPage from './OrderPage/OrderPage'; import PasswordChangePage from './PasswordChangePage/PasswordChangePage'; import PasswordForgottenPage from './PasswordForgottenPage/PasswordForgottenPage'; @@ -14,7 +15,7 @@ import ProfilePage from './ProfilePage/ProfilePage'; import SalesConversationPage from './SalesConversationPage/SalesConversationPage'; import SearchPage from './SearchPage/SearchPage'; import SecurityPage from './SecurityPage/SecurityPage'; -import NotFoundPage from './NotFoundPage/NotFoundPage'; +import StyleguidePage from './StyleguidePage/StyleguidePage'; import Topbar from './Topbar/Topbar'; export { @@ -35,5 +36,6 @@ export { SalesConversationPage, SearchPage, SecurityPage, + StyleguidePage, Topbar, }; diff --git a/src/routesConfiguration.js b/src/routesConfiguration.js index 21e6057b..0a8ae658 100644 --- a/src/routesConfiguration.js +++ b/src/routesConfiguration.js @@ -19,6 +19,7 @@ import { SalesConversationPage, SearchPage, SecurityPage, + StyleguidePage, } from './containers'; // This is only used for testing that redirects work correct in the @@ -196,6 +197,30 @@ const routesConfiguration = [ }, ], }, + { + pattern: '/styleguide', + exactly: true, + name: 'Styleguide', + component: StyleguidePage, + }, + { + pattern: '/styleguide/:component', + exactly: true, + name: 'StyleguideComponent', + component: StyleguidePage, + }, + { + pattern: '/styleguide/:component/:example', + exactly: true, + name: 'StyleguideComponentExample', + component: StyleguidePage, + }, + { + pattern: '/styleguide/:component/:example/:type', + exactly: true, + name: 'StyleguideComponentExampleRaw', + component: StyleguidePage, + }, ]; const flattenRoutes = routesArray =>