diff --git a/README.md b/README.md
index 1f44ac2fb888..1c34d800abd9 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,25 @@ storiesOf('Button')
> Have a look at [this example](example/story.js) stories to learn more about the `addWithInfo` API.
+## Use with Docgen
+To add a prop description, we can use a single line or multiple lines comment as below example:
+```js
+Object.assign(Button, {
+ displayName: 'Button',
+ propTypes: {
+ /** Single line comment: This is label description */
+ label: React.PropTypes.string.isRequired,
+ /*
+ * Multiple lines comment: This is style description
+ * Must be in object
+ */
+ style: React.PropTypes.object,
+ disabled: React.PropTypes.bool,
+ onClick: React.PropTypes.func,
+ },
+});
+```
+
## The FAQ
**Components lose their names on static build**
diff --git a/example/Button.js b/example/Button.js
index 68ea5323adea..3a5f4a82f4fe 100644
--- a/example/Button.js
+++ b/example/Button.js
@@ -9,7 +9,12 @@ const Button = ({ disabled, label, style, onClick }) => (
Object.assign(Button, {
displayName: 'Button',
propTypes: {
+ /** Single line comment: This is label description */
label: React.PropTypes.string.isRequired,
+ /*
+ * Multiple lines comment: This is style description
+ * Must be in object
+ */
style: React.PropTypes.object,
disabled: React.PropTypes.bool,
onClick: React.PropTypes.func,
diff --git a/src/components/PropTable.js b/src/components/PropTable.js
index e65c05ce0ef4..b210af148d61 100644
--- a/src/components/PropTable.js
+++ b/src/components/PropTable.js
@@ -1,6 +1,18 @@
import React from 'react';
import PropVal from './PropVal';
+const stylesheet = {
+ propTable: {
+ marginLeft: -10,
+ borderSpacing: '10px 5px',
+ borderCollapse: 'separate',
+ },
+};
+
+function isNotEmpty(obj) {
+ return obj && Object.keys(obj).length > 0;
+}
+
const PropTypesMap = new Map();
for (const typeName in React.PropTypes) {
if (!React.PropTypes.hasOwnProperty(typeName)) {
@@ -11,82 +23,129 @@ for (const typeName in React.PropTypes) {
PropTypesMap.set(type.isRequired, typeName);
}
-const stylesheet = {
- propTable: {
- marginLeft: -10,
- borderSpacing: '10px 5px',
- borderCollapse: 'separate',
- },
-};
+function renderDocgenPropType(propType) {
+ if (!propType) {
+ return 'unknown';
+ }
-export default class PropTable extends React.Component {
- render() {
- const type = this.props.type;
+ const name = propType.name;
- if (!type) {
- return null;
+ switch (name) {
+ case 'arrayOf':
+ return `${propType.value.name}[]`;
+ case 'instanceOf':
+ return propType.value;
+ case 'union':
+ return propType.raw;
+ default:
+ return name;
+ }
+}
+
+function hasDocgen(type) {
+ return isNotEmpty(type.__docgenInfo);
+}
+
+function propsFromDocgen(type) {
+ let props = null;
+
+ const docgenInfo = type.__docgenInfo || {};
+ const docgenInfoProps = docgenInfo.props;
+
+ if (docgenInfoProps) {
+ props = {};
+ for (const propName in docgenInfoProps) {
+ if (!docgenInfoProps.hasOwnProperty(propName)) {
+ continue;
+ }
+ const docgenInfoProp = docgenInfoProps[propName];
+ const defaultValueDesc = docgenInfoProp.defaultValue || {};
+ const propType = docgenInfoProp.flowType || docgenInfoProp.type || 'other';
+
+ props[propName] = {
+ property: propName,
+ propType: renderDocgenPropType(propType),
+ required: docgenInfoProp.required,
+ description: docgenInfoProp.description,
+ defaultValue: defaultValueDesc.value,
+ };
}
+ }
+ return props;
+}
+
+function propsFromPropTypes(type) {
+ let props = null;
- const props = {};
-
- if (type.propTypes) {
- for (const property in type.propTypes) {
- if (!type.propTypes.hasOwnProperty(property)) {
- continue;
- }
- const typeInfo = type.propTypes[property];
- const propType = PropTypesMap.get(typeInfo) || 'other';
- const required = typeInfo.isRequired === undefined ? 'yes' : 'no';
- props[property] = { property, propType, required };
+ if (type.propTypes) {
+ props = {};
+ for (const property in type.propTypes) {
+ if (!type.propTypes.hasOwnProperty(property)) {
+ continue;
}
+ const typeInfo = type.propTypes[property];
+ const propType = PropTypesMap.get(typeInfo) || 'other';
+ const required = typeInfo.isRequired === undefined ? 'yes' : 'no';
+ props[property] = { property, propType, required };
}
+ }
- if (type.defaultProps) {
- for (const property in type.defaultProps) {
- if (!type.defaultProps.hasOwnProperty(property)) {
- continue;
- }
- const value = type.defaultProps[property];
- if (value === undefined) {
- continue;
- }
- if (!props[property]) {
- props[property] = { property };
- }
- props[property].defaultValue = value;
+ if (type.defaultProps) {
+ for (const property in type.defaultProps) {
+ if (!type.defaultProps.hasOwnProperty(property)) {
+ continue;
}
+ const value = type.defaultProps[property];
+ if (value === undefined) {
+ continue;
+ }
+ if (!props[property]) {
+ props[property] = { property };
+ }
+ props[property].defaultValue = value;
}
+ }
+ return props;
+}
- const array = Object.values(props);
- if (!array.length) {
- return No propTypes defined!;
+export default class PropTable extends React.Component {
+ render() {
+ const type = this.props.type;
+
+ if (!type) {
+ return null;
}
- array.sort(function (a, b) {
- return a.property > b.property;
- });
-
- return (
-
-
-
- property |
- propType |
- required |
- default |
-
-
-
- {array.map(row => (
-
- {row.property} |
- {row.propType} |
- {row.required} |
- {row.defaultValue === undefined ? '-' : } |
+
+ const props = hasDocgen(type) ? propsFromDocgen(type) : propsFromPropTypes(type);
+
+ if (isNotEmpty(props)) {
+ return (
+
+
+
+ property |
+ propType |
+ required |
+ default |
+ description |
- ))}
-
-
- );
+
+
+ {Object.values(props).sort((a, b) => a.property > b.property).map(row => (
+
+ {row.property} |
+ {row.propType} |
+ {row.required} |
+ {row.defaultValue === undefined ? '-' : } |
+ {row.description} |
+
+ ))}
+
+
+ );
+ } else {
+ return No propTypes defined!;
+ }
}
}