diff --git a/.storybook/main.js b/.storybook/main.js
index 3210ecc50..bbbd0804f 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -29,7 +29,8 @@ const config = {
storyStoreV7: false
},
docs: {
- autodocs: "tag"
+ autodocs: "tag",
+ defaultName: 'Documentation',
},
webpackFinal: async (config) => {
return {
diff --git a/client/src/components/ActionMenu/tests/ActionMenu-story.js b/client/src/components/ActionMenu/tests/ActionMenu-story.js
index 90e50e186..23f9ff8a9 100644
--- a/client/src/components/ActionMenu/tests/ActionMenu-story.js
+++ b/client/src/components/ActionMenu/tests/ActionMenu-story.js
@@ -4,6 +4,22 @@ import { DropdownItem } from 'reactstrap';
export default {
title: 'Admin/ActionMenu',
+ component: ActionMenu,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'ActionMenu Component description.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {}
};
export const Single = () => (
diff --git a/client/src/components/Badge/tests/Badge-story.js b/client/src/components/Badge/tests/Badge-story.js
index cee0e317d..394766c10 100644
--- a/client/src/components/Badge/tests/Badge-story.js
+++ b/client/src/components/Badge/tests/Badge-story.js
@@ -3,30 +3,60 @@ import { jsxDecorator } from 'storybook-addon-jsx';
import Badge, { statuses } from 'components/Badge/Badge';
export default {
- title: 'Admin/Badges',
+ title: 'Admin/Badges/Badge',
component: Badge,
decorators: [
- jsxDecorator,
- (Story) =>
-
-
+
+
;
+_FormAlert.args = {
+ type: 'success',
+ value: "This is a 'success'/'good' alert"
+};
+
+
export const Types = () => (
diff --git a/client/src/components/GridFieldActions/tests/GridFIeldActions-story.js b/client/src/components/GridFieldActions/tests/GridFIeldActions-story.js
index 6ef817480..bab8aad0e 100644
--- a/client/src/components/GridFieldActions/tests/GridFIeldActions-story.js
+++ b/client/src/components/GridFieldActions/tests/GridFIeldActions-story.js
@@ -3,25 +3,29 @@ import GridFieldActions from 'components/GridFieldActions/GridFieldActions';
export default {
title: 'Admin/GridFieldActions',
+ component: GridFieldActions,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'GridFieldActions description.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {}
};
-export const Single = () => {
- const schema = [
- {
- type: 'link',
- title: 'Link Type Action',
- url: '#edit',
- group: 'General',
- data: {
- extraClass: 'edit-link',
- },
- },
- ];
- return
;
-};
+const Template = args =>
;
-export const Multiple = () => {
- const schema = [
+export const Multiple = Template.bind({});
+Multiple.args = {
+ schema: [
{
type: 'link',
title: 'Link Type Action',
@@ -42,12 +46,12 @@ export const Multiple = () => {
'data-url': 'admin/pages/edit/EditForm/8/field/Companies',
},
},
- ];
- return
;
+ ]
};
-export const Grouped = () => {
- const schema = [
+export const Grouped = Template.bind({});
+Grouped.args = {
+ schema: [
{
type: 'link',
title: 'Action 1',
@@ -84,12 +88,12 @@ export const Grouped = () => {
extraClass: 'edit-link',
},
},
- ];
- return
;
+ ]
};
-export const Complex = () => {
- const schema = [
+export const Complex = Template.bind({});
+Complex.args = {
+ schema: [
{
type: 'link',
title: 'Link Type Action',
@@ -210,6 +214,19 @@ export const Complex = () => {
'data-url': 'admin/pages/edit/EditForm/8/field/Companies',
},
},
- ];
- return
;
+ ]
+};
+export const _GridFieldActions = Template.bind({});
+_GridFieldActions.args = {
+ schema: [
+ {
+ type: 'link',
+ title: 'Link Type Action',
+ url: '#edit',
+ group: 'General',
+ data: {
+ extraClass: 'edit-link',
+ },
+ },
+ ]
};
diff --git a/client/src/components/HeaderField/tests/HeaderField-story.js b/client/src/components/HeaderField/tests/HeaderField-story.js
index b66f0b20d..173a7ad50 100644
--- a/client/src/components/HeaderField/tests/HeaderField-story.js
+++ b/client/src/components/HeaderField/tests/HeaderField-story.js
@@ -7,17 +7,48 @@ export default {
decorators: [
jsxDecorator
],
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'Generates a header field for displaying as a title.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
extraClass: {
- control: 'text'
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
},
data: {
- title: {
- control: 'text'
+ description: `Extra data that helps define this field uniquely.
+ * headingLevel (number): The level depth for heading.
+ * title (string) (required): Title to display.`,
+ control: 'object',
+ type: {
+ required: true
},
- headingLevel: {
- control: 'select',
- options: [1, 2, 3, 4, 5]
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: '{}' },
}
}
}
@@ -25,6 +56,7 @@ export default {
export const Heading = {
args: {
+ id: 'my-hidden',
extraClass: 'my-extra-class',
data: {
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
diff --git a/client/src/components/HiddenField/tests/HiddenField-story.js b/client/src/components/HiddenField/tests/HiddenField-story.js
index 0f8f567c7..c1475dafa 100644
--- a/client/src/components/HiddenField/tests/HiddenField-story.js
+++ b/client/src/components/HiddenField/tests/HiddenField-story.js
@@ -1,14 +1,66 @@
import React from 'react';
import HiddenField from 'components/HiddenField/HiddenField';
-const props = {
- extraClass: 'my-extra-class',
- name: 'MyName',
- value: 'MyValue',
-};
-
export default {
title: 'Admin/HiddenField',
+ component: HiddenField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a hidden input type field.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ },
+ type: {
+ required: true
+ }
+ },
+ value: {
+ description: 'The value the input should hold.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ },
+ }
+ }
};
-export const Default = () =>
;
+export const _HiddenField = (args) =>
;
+_HiddenField.args = {
+ extraClass: 'my-extra-class',
+ name: 'MyName',
+ value: 'MyValue',
+};
diff --git a/client/src/components/HtmlReadonlyField/tests/HtmlReadonlyField-story.js b/client/src/components/HtmlReadonlyField/tests/HtmlReadonlyField-story.js
index d62a39379..bacedbae0 100644
--- a/client/src/components/HtmlReadonlyField/tests/HtmlReadonlyField-story.js
+++ b/client/src/components/HtmlReadonlyField/tests/HtmlReadonlyField-story.js
@@ -8,12 +8,68 @@ const htmlValue = `
Some
HTML
export default {
title: 'Admin/HtmlReadonlyField',
+ component: HtmlReadonlyField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a block of raw HTML content inside a Readonly styled box.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ value: {
+ description: 'The raw HTML content to generate.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ }
+ }
};
-export const Default = () => (
-
-);
+const Template = args =>
;
-export const HtmlValue = () => (
-
-);
+export const _HtmlReadonlyField = Template.bind({});
+_HtmlReadonlyField.args = {
+ name: 'default',
+ value: 'This is readonly'
+};
+
+export const HtmlValue = Template.bind({});
+HtmlValue.args = {
+ name: 'default',
+ value: htmlValue
+};
diff --git a/client/src/components/IframeDialog/tests/IframeDialog-story.js b/client/src/components/IframeDialog/tests/IframeDialog-story.js
index be65ffef0..f9dfa588e 100644
--- a/client/src/components/IframeDialog/tests/IframeDialog-story.js
+++ b/client/src/components/IframeDialog/tests/IframeDialog-story.js
@@ -3,8 +3,27 @@ import IframeDialog from 'components/IframeDialog/IframeDialog';
export default {
title: 'Admin/IframeDialog',
+ component: IframeDialog,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'IframeDialog Component Description. To show iFrame dialog switch `isOpen` to true.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {},
+};
+export const _IframeDialog = {
+ args: {
+ url: 'https://silverstripe.org',
+ isOpen: false,
+ title: 'iFrame Dialog'
+ }
};
-
-export const Dialog = () => (
-
-);
diff --git a/client/src/components/ListGroup/tests/ListGroupItem-story.js b/client/src/components/ListGroup/tests/ListGroupItem-story.js
index 1ae12260f..e3bf95504 100644
--- a/client/src/components/ListGroup/tests/ListGroupItem-story.js
+++ b/client/src/components/ListGroup/tests/ListGroupItem-story.js
@@ -3,12 +3,30 @@ import ListGroupItem from 'components/ListGroup/ListGroupItem';
export default {
title: 'Admin/ListGroupItem',
+ component: ListGroupItem,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'ListGroupItem Component Description.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
};
-export const Items = () => (
+export const Items = (args) => (
Item one
- Item two (active)
+ Item two (active)
Item three
);
+Items.args = {
+ className: 'active'
+};
diff --git a/client/src/components/LiteralField/tests/LiteralField-story.js b/client/src/components/LiteralField/tests/LiteralField-story.js
index fc0e612c9..81863b85c 100644
--- a/client/src/components/LiteralField/tests/LiteralField-story.js
+++ b/client/src/components/LiteralField/tests/LiteralField-story.js
@@ -1,16 +1,68 @@
import React from 'react';
import LiteralField from 'components/LiteralField/LiteralField';
-const props = {
+export default {
+ title: 'Admin/LiteralField',
+ component: LiteralField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'LiteralField Component Description.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ className: {
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ value: {
+ control: 'text',
+ table: {
+ type: { summary: 'any' },
+ defaultValue: { summary: '' },
+ }
+ },
+ }
+};
+
+export const _LiteralField = (args) =>
;
+_LiteralField.args = {
id: 'my-id',
name: 'MyName',
className: 'my-classname',
extraClass: 'my-extra-class',
value: '
My literal heading My literal content
',
};
-
-export default {
- title: 'Admin/LiteralField',
-};
-
-export const Default = () =>
;
diff --git a/client/src/components/Loading/tests/Loading-story.js b/client/src/components/Loading/tests/Loading-story.js
index 20c66297e..6c998159a 100644
--- a/client/src/components/Loading/tests/Loading-story.js
+++ b/client/src/components/Loading/tests/Loading-story.js
@@ -3,6 +3,33 @@ import Loading from 'components/Loading/Loading';
export default {
title: 'Admin/Loading',
+ component: Loading,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'Provides a simple SilverStripe loading indicator component.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ containerClass: {
+ description: "HTML classes to be added to the indicator's container div. If empty, no container will be rendered. Default: `flexbox-area-grow`",
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: 'flexbox-area-grow' },
+ }
+ }
+ }
};
-export const _Loading = () =>
;
+export const _Loading = () =>
;
+_Loading.args = {
+ containerClass: '',
+};
diff --git a/client/src/components/LookupField/tests/LookupField-story.js b/client/src/components/LookupField/tests/LookupField-story.js
index f5b56be8f..20ccfd376 100644
--- a/client/src/components/LookupField/tests/LookupField-story.js
+++ b/client/src/components/LookupField/tests/LookupField-story.js
@@ -1,8 +1,71 @@
import React from 'react';
import LookupField from 'components/LookupField/LookupField';
-import ValueTracker from 'stories/ValueTracker';
-const props = {
+export default {
+ title: 'Admin/LookupField',
+ component: LookupField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a CSV list of values inside a Readonly styled box.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ type: {
+ required: true
+ },
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ value: {
+ description: 'The values to look up in the source.',
+ table: {
+ type: { summary: 'string|array' },
+ defaultValue: { summary: '' },
+ }
+ },
+ source: {
+ description: `Array of items to appear in the list with the following properties.
+ * value (string|number): The value for item.
+ * title (any): The displayed value for item.`,
+ control: 'object',
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: '' },
+ }
+ }
+ }
+};
+
+export const _LookupField = (args) =>
;
+_LookupField.args = {
name: 'plaintext',
value: 2,
source: [
@@ -20,11 +83,3 @@ const props = {
},
],
};
-
-export default {
- title: 'Admin/LookupField',
-
- decorators: [(storyFn) =>
{storyFn()} ],
-};
-
-export const Lookup = () =>
;
diff --git a/client/src/components/NumberField/tests/NumberField-story.js b/client/src/components/NumberField/tests/NumberField-story.js
index 880f3ee19..0d5b1679c 100644
--- a/client/src/components/NumberField/tests/NumberField-story.js
+++ b/client/src/components/NumberField/tests/NumberField-story.js
@@ -9,33 +9,75 @@ const tagActions = actionListMaker('onClick', 'onChange');
export default {
title: 'Admin/NumberField',
component: NumberField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'NumberField Component description.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
decorators: [
jsxDecorator,
- (Story) =>
],
argTypes: {
title: {
- control: 'text'
+ description: '',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
},
value: {
- control: 'number'
+ control: 'number',
+ table: {
+ type: { summary: 'number' },
+ defaultValue: { summary: '' },
+ }
},
placeholder: {
- control: 'text'
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
},
description: {
- control: 'text'
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
},
disabled: {
- control: 'boolean'
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
},
message: {
- type: {
- control: 'select',
- options: ['', 'error']
- },
- value: {
- control: 'text'
+ control: 'object',
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: "{ value: '', type: '' }" },
+ }
+ },
+ onClick: {
+ table: {
+ type: { summary: 'function' },
+ }
+ },
+ onChange: {
+ table: {
+ type: { summary: 'function' },
}
}
}
diff --git a/client/src/components/OptionsetField/tests/OptionField-story.js b/client/src/components/OptionsetField/tests/OptionField-story.js
new file mode 100644
index 000000000..67443977d
--- /dev/null
+++ b/client/src/components/OptionsetField/tests/OptionField-story.js
@@ -0,0 +1,126 @@
+import React from 'react';
+import OptionField from 'components/OptionsetField/OptionField';
+
+export default {
+ title: 'Admin/OptionField/OptionField',
+ component: OptionField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a radio button group, behaves the similarly to 'SingleSelectField'.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ control: 'text',
+ type: {
+ required: true,
+ },
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ type: {
+ description: 'The type of option component will be: `checkbox` or `radio`',
+ control: 'select',
+ options: ['checkbox', 'radio'],
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: 'radio' },
+ }
+ },
+ leftTitle: {
+ description: 'Title to display to the left (if inline) or above the field, check below NOTE about handling raw html.',
+ control: 'text',
+ table: {
+ type: { summary: 'any' },
+ defaultValue: { summary: '' },
+ }
+ },
+ title: {
+ description: 'Title to display if leftTitle is not defined, check below NOTE about handling raw html.',
+ control: 'text',
+ table: {
+ type: { summary: 'any' },
+ defaultValue: { summary: '' },
+ }
+ },
+ value: {
+ description: 'Whether this is checked or not, *this does not hold an explicit value*!',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ source: {
+ description: `Array of items to appear in the list with the following properties.
+ * value (string|number): The value for item.
+ * title (any): The displayed value for item.
+ * disabled (boolean): Tells if item is disabled from selecting.`,
+ control: 'object',
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: '' },
+ }
+ },
+ disabled: {
+ description: 'Whether this field is disabled.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ readOnly: {
+ description: 'Whether this field is read only.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ onChange: {
+ description: 'Event handler for when the component changes.',
+ table: {
+ type: { summary: 'function' },
+ defaultValue: { summary: false },
+ }
+ }
+ }
+};
+
+export const _OptionField = (args) =>
;
+_OptionField.args = {
+ id: 'set',
+ title: '',
+ name: 'set',
+ value: '2'
+};
diff --git a/client/src/components/OptionsetField/tests/OptionsetField-story.js b/client/src/components/OptionsetField/tests/OptionsetField-story.js
index 0a442cd91..5e0301d40 100644
--- a/client/src/components/OptionsetField/tests/OptionsetField-story.js
+++ b/client/src/components/OptionsetField/tests/OptionsetField-story.js
@@ -1,8 +1,106 @@
import React from 'react';
import OptionsetField from 'components/OptionsetField/OptionsetField';
-import ValueTracker from 'stories/ValueTracker';
-const props = {
+export default {
+ title: 'Admin/OptionField/OptionsetField',
+ component: OptionsetField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a radio button group, behaves the similarly to 'SingleSelectField'.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ itemClass: {
+ description: 'Classes applicable to each item in the group.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ control: 'text',
+ type: {
+ required: true,
+ },
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ value: {
+ description: 'The value that matches one of the source items value.',
+ table: {
+ type: { summary: 'string|number' },
+ defaultValue: { summary: '' },
+ }
+ },
+ source: {
+ description: `Array of items to appear in the list with the following properties.
+ * value (string|number): The value for item.
+ * title (any): The displayed value for item.
+ * disabled (boolean): Tells if item is disabled from selecting.`,
+ control: 'object',
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: '' },
+ }
+ },
+ disabled: {
+ description: 'Whether this field is disabled.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ readOnly: {
+ description: 'Whether this field is read only.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ onChange: {
+ description: 'Event handler for when the component changes.',
+ table: {
+ type: { summary: 'function' },
+ defaultValue: { summary: false },
+ }
+ }
+ }
+};
+
+export const _OptionsetField = (args) =>
;
+_OptionsetField.args = {
id: 'set',
title: '',
name: 'set',
@@ -14,11 +112,3 @@ const props = {
{ value: '4', title: 'four' },
],
};
-
-export default {
- title: 'Admin/OptionsetField',
-
- decorators: [(storyFn) =>
{storyFn()} ],
-};
-
-export const Optionset = () =>
;
diff --git a/client/src/components/PopoverField/tests/PopoverField-story.js b/client/src/components/PopoverField/tests/PopoverField-story.js
index 6e6f30ac9..f7b17da79 100644
--- a/client/src/components/PopoverField/tests/PopoverField-story.js
+++ b/client/src/components/PopoverField/tests/PopoverField-story.js
@@ -8,7 +8,23 @@ const centerStyles = {
};
export default {
- title: 'Admin/PopoverField',
+ title: 'Admin/PopoverField/PopoverField',
+ component: PopoverField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Creates a popup box that may contain other nested fields. The activator for this popup
+ is represented by a button.`
+ },
+ canvas: {
+ sourceState: 'hide',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
};
export const Default = () => (
@@ -21,7 +37,7 @@ export const Default = () => (
buttonTooltip: 'Button tooltip',
}}
>
-
This is some info in the popover
+
This is some info in the popover
(
popoverTitle: 'Default ellipsis button',
}}
>
- An ellipsis icon is used if no title is provided.
+ An ellipsis icon is used if no title is provided.
set.filter(
export default {
- title: 'Admin/PopoverOptionSet',
+ title: 'Admin/PopoverField/PopoverOptionSet',
component: PopoverOptionSetToggle,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a popover filled with buttons that can be filtered with a search.
+ This component can be viewed in the bundled pattern library.
+ Additionally a toggle component is provided as a basic implementation or example to get started.`
+ },
+ canvas: {
+ sourceState: 'hide',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
decorators: [
jsxDecorator,
- (Story) =>
],
argTypes: {
buttons: {
@@ -83,12 +98,12 @@ WithIcons.args = {
};
export const ComplexContent = (args) => (
- <>
-
- Note that supplying JSX as content will mean that search will have to be disabled or you must implement a custom search function
-
-
- >
+ <>
+
+ Note that supplying JSX as content will mean that search will have to be disabled or you must implement a custom search function
+
+
+ >
);
ComplexContent.args = {
...SimpleExample.args,
@@ -96,12 +111,12 @@ ComplexContent.args = {
};
export const CustomSearch = (args) => (
- <>
-
- This custom search function will ignore the Button prefix on each button
-
-
- >
+ <>
+
+ This custom search function will ignore the Button prefix on each button
+
+
+ >
);
CustomSearch.args = {
...SimpleExample.args,
diff --git a/client/src/components/Search/Search.js b/client/src/components/Search/Search.js
index 0bae041de..d28688d97 100644
--- a/client/src/components/Search/Search.js
+++ b/client/src/components/Search/Search.js
@@ -86,8 +86,8 @@ class Search extends Component {
*/
setOverrides(props) {
if (props && (
- !hasFilters(props.filters) || this.props.formSchemaUrl !== props.formSchemaUrl
- )) {
+ !hasFilters(props.filters) || this.props.formSchemaUrl !== props.formSchemaUrl
+ )) {
// clear any overrides that may be in place
const schemaUrl = (props && props.formSchemaUrl) || this.props.formSchemaUrl;
if (schemaUrl) {
@@ -424,7 +424,7 @@ class Search extends Component {
if (displayBehavior === BEHAVIOR.TOGGLABLE) {
return ( );
}
- return (
);
+ return (
);
}
// Display the SearchBox
diff --git a/client/src/components/Search/tests/Search-story.js b/client/src/components/Search/tests/Search-story.js
index 9612e3a1f..484e8131c 100644
--- a/client/src/components/Search/tests/Search-story.js
+++ b/client/src/components/Search/tests/Search-story.js
@@ -1,7 +1,6 @@
import React from 'react';
import Search from '../Search';
import SearchToggle from '../SearchToggle';
-import ValueTracker from 'stories/ValueTracker';
import { createStore, combineReducers } from 'redux';
import { reducer as ReduxFormReducer } from 'redux-form';
import SchemaReducer from 'state/schema/SchemaReducer';
@@ -11,80 +10,97 @@ const FormReducer = combineReducers({
formSchemas: SchemaReducer,
});
-const props = {
+export default {
+ title: 'Admin/Search',
+ component: Search,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'Allows users to search by term or filter results with a sub form.'
+ },
+ canvas: {
+ sourceState: 'hide',
+ },
+ controls: {
+ sort: 'alpha',
+ exclude: ['store'],
+ },
+ story: {
+ height: '200px'
+ }
+ }
+ },
+};
+
+export const _Search = args => ;
+_Search.args = {
name: 'MyField',
title: 'Field title',
onSearch: () => {},
store: createStore(combineReducers({ form: FormReducer })),
};
-export default {
- title: 'Admin/Search',
- decorators: [(Story) => ],
+export const SimpleVanilla = {
+ args: {
+ ..._Search.args,
+ id: 'SimpleVanillaSearch',
+ display: 'VISIBLE',
+ displayBehavior: 'NONE'
+ }
};
-export const SimpleVanilla = () => (
-
-);
-
-export const WithFilters = () => (
-
-);
+export const WithFilters = {
+ args: {
+ ..._Search.args,
+ id: 'SmallNotExpanded',
+ display: 'VISIBLE',
+ formSchemaUrl: '',
+ filters: {},
+ formData: {},
+ placeholder: "Search 'Pages'",
+ displayBehavior: 'NONE',
+ forceFilters: true
+ }
+};
-export const Hideable = () => (
-
-);
+export const Hideable = {
+ args: {
+ ..._Search.args,
+ id: 'Large Hideable',
+ display: 'VISIBLE',
+ formSchemaUrl: '',
+ forceFilters: true,
+ filters: {},
+ formData: {},
+ placeholder: 'Search me',
+ displayBehavior: 'HIDEABLE',
+ }
+};
-export const Toggeable = () => (
-
-);
+export const Toggeable = {
+ args: {
+ ..._Search.args,
+ id: 'TOGGEABLE',
+ display: 'NONE',
+ displayBehavior: 'TOGGLABLE',
+ formSchemaUrl: '',
+ formData: {},
+ forceFilters: true
+ }
+};
-export const Wide = () => (
-
-
-
-);
+export const Wide = {
+ args: {
+ ..._Search.args,
+ id: 'WIDE',
+ display: 'VISIBLE',
+ displayBehavior: 'TOGGLABLE',
+ formSchemaUrl: '',
+ formData: {},
+ forceFilters: true
+ }
+};
export const ToggleButton = () => (
diff --git a/client/src/components/SingleSelectField/tests/SingleSelectField-story.js b/client/src/components/SingleSelectField/tests/SingleSelectField-story.js
index 2b35305f9..f21a871d6 100644
--- a/client/src/components/SingleSelectField/tests/SingleSelectField-story.js
+++ b/client/src/components/SingleSelectField/tests/SingleSelectField-story.js
@@ -1,7 +1,110 @@
import React from 'react';
import SingleSelectField from 'components/SingleSelectField/SingleSelectField';
-const props = {
+export default {
+ title: 'Admin/SingleSelectField',
+ component: SingleSelectField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a select/dropdown field.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ exclude: ['store'],
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ control: 'text',
+ type: {
+ required: true
+ },
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ readOnly: {
+ description: 'Whether this field is read only.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ onChange: {
+ description: 'Event handler for when the component changes.',
+ table: {
+ type: { summary: 'function' },
+ defaultValue: { summary: false },
+ }
+ },
+ value: {
+ description: 'The value that matches one of the source items value.',
+ table: {
+ type: { summary: 'string|number' },
+ defaultValue: { summary: '' },
+ }
+ },
+ source: {
+ description: `Array of items to appear in the list with the following properties excepted.
+ * value (string|number): The value for item.
+ * title (string|number): The displayed value for item.
+ * disabled (boolean): Tells if item is disabled from selecting.`,
+ control: 'object',
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: '' },
+ }
+ },
+ disabled: {
+ description: 'Whether this field is disabled.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ data: {
+ description: `Extra data that helps define this field uniquely.
+ * hasEmptyDefault (boolean): Defines if this has a "blank" option.
+ * emptyString (string): The title for the "blank" option.`,
+ control: 'object',
+ table: {
+ type: { summary: 'object' },
+ defaultValue: { summary: '' },
+ }
+ }
+ }
+};
+
+export const EmptyDefault = (args) =>
;
+
+EmptyDefault.args = {
name: 'options',
source: [
{
@@ -26,22 +129,16 @@ const props = {
description: 'Four is the fourth number',
},
],
+ data: {
+ hasEmptyDefault: true,
+ emptyString: 'Choose an option',
+ }
};
-export default {
- title: 'Admin/SingleSelectField',
+export const Readonly = {
+ args: {
+ ...EmptyDefault.args,
+ readOnly: true,
+ value: 'One'
+ }
};
-
-export const EmptyDefault = () => (
-
-);
-
-export const Readonly = () => (
-
-);
diff --git a/client/src/components/Tabs/tests/Tabs-story.js b/client/src/components/Tabs/tests/Tabs-story.js
index 6cdfda87d..b59e4348c 100644
--- a/client/src/components/Tabs/tests/Tabs-story.js
+++ b/client/src/components/Tabs/tests/Tabs-story.js
@@ -3,6 +3,29 @@ import { jsxDecorator } from 'storybook-addon-jsx';
import { Component as StatelessTabs } from 'components/Tabs/Tabs';
import TabItem from 'components/Tabs/TabItem';
+export default {
+ title: 'Admin/Tabs',
+ decorators: [jsxDecorator],
+ component: TabItem,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `For separating content into tabs without the need for separate pages.
+ This extends from 'reactstrap' with similar expected behaviours, only difference is that when
+ there is only one tab (or none) in the Tabset, then only the content will show without the
+ clickable tab.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+};
+
const Tabs = (props) => {
const [activeTab, activateTab] = useState();
return (
@@ -14,29 +37,25 @@ const Tabs = (props) => {
);
};
-export default {
- title: 'Admin/Tabs',
- decorators: [jsxDecorator],
-};
export const Basic = () => (
-
-
- My first tab content
-
-
- My settings tab here
-
-
- My settings tab here
-
-
+
+
+ My first tab content
+
+
+ My settings tab here
+
+
+ My settings tab here
+
+
);
export const SingleTabInstance = () => (
-
-
- Tab content for the only tab in tabset
-
-
+
+
+ Tab content for the only tab in tabset
+
+
);
diff --git a/client/src/components/Tag/tests/Tag-story.js b/client/src/components/Tag/tests/Tag-story.js
index 7f94be69c..0787811f0 100644
--- a/client/src/components/Tag/tests/Tag-story.js
+++ b/client/src/components/Tag/tests/Tag-story.js
@@ -29,20 +29,22 @@ const compactTagListActions = actionListMaker('onSummary');
export default {
title: 'Admin/Tag',
- decorators: [
- jsxDecorator,
- (Story) =>
- ],
-};
-
-export const _Tag = (args) => (
);
-_Tag.args = {
- dataKey: 'HelloWorld',
- label: '',
- value: '',
- deletable: false,
- focusable: true,
- ...tagActions
+ component: Tag,
+ decorators: [jsxDecorator],
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: '`
` can be used to visually associate a record with related topics. Tags can be used individually or as part of a `
`'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
};
export const _TagList = (args) => (
);
@@ -62,3 +64,13 @@ _CompactTagList.args = {
...tagListActions,
...compactTagListActions
};
+
+export const _Tag = (args) => (
);
+_Tag.args = {
+ dataKey: 'HelloWorld',
+ label: '',
+ value: '',
+ deletable: false,
+ focusable: true,
+ ...tagActions
+};
diff --git a/client/src/components/TextField/tests/TextField-story.js b/client/src/components/TextField/tests/TextField-story.js
index 384fe7b3f..4eb0563f5 100644
--- a/client/src/components/TextField/tests/TextField-story.js
+++ b/client/src/components/TextField/tests/TextField-story.js
@@ -1,54 +1,133 @@
import React from 'react';
import { jsxDecorator } from 'storybook-addon-jsx';
-
import TextField from 'components/TextField/TextField';
-import ValueTracker from 'stories/ValueTracker';
-const props = {
+export default {
+ title: 'Admin/TextField',
+ component: TextField,
+ decorators: [jsxDecorator],
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates an editable text field.
+ _NOTE:_ For other properties, please refer to the [reactstrap Input](https://reactstrap.github.io/components/form/) documentation.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'The ID for the component.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ extraClass: {
+ description: 'Extra classes the component should have.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ name: {
+ description: 'The name for the component.',
+ control: 'text',
+ type: {
+ required: true
+ },
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ readOnly: {
+ description: 'Whether this field is read only.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ onChange: {
+ description: 'Event handler for when the component changes.',
+ table: {
+ type: { summary: 'function' },
+ defaultValue: { summary: false },
+ }
+ },
+ value: {
+ description: 'The value to display for the field, can use `defaultValue` for uncontrollable component.',
+ table: {
+ type: { summary: 'string|number' },
+ defaultValue: { summary: '' },
+ }
+ },
+ disabled: {
+ description: 'Whether this field is disabled.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ defaultValue: { summary: false },
+ }
+ },
+ type: {
+ description: 'Defines the type this component will have, e.g. `email`, `tel`.',
+ control: 'select',
+ options: ['email', 'tel'],
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ }
+};
+
+export const DefaultTextField = args =>
;
+DefaultTextField.args = {
name: 'MyField',
id: 'MyField',
title: 'Field title',
placeholder: 'Placeholder text',
};
-export default {
- title: 'Admin/TextField',
- decorators: [
- jsxDecorator,
- (Story) =>
,
- ]
+export const Textarea = {
+ args: {
+ ...DefaultTextField.args,
+ data: { rows: 4, columns: 40 }
+ }
};
-export const Textbox = () =>
;
-
-export const Textarea = () => (
-
-);
-
-export const AllTitles = () => (
-
-);
+ }
+ }
+};
-export const ValidationFailed = () => (
-
-);
+ type: 'error',
+ }
+ }
+};
diff --git a/client/src/components/Tip/tests/Tip-story.js b/client/src/components/Tip/tests/Tip-story.js
index 03fc2dcda..bed441a25 100644
--- a/client/src/components/Tip/tests/Tip-story.js
+++ b/client/src/components/Tip/tests/Tip-story.js
@@ -1,8 +1,6 @@
import React from 'react';
import { jsxDecorator } from 'storybook-addon-jsx';
-
import Tip, { TIP_IMPORTANCE_LEVELS, TIP_TYPES } from 'components/Tip/Tip';
-import ValueTracker from 'stories/ValueTracker';
import { FormGroup, Input, InputGroup, InputGroupAddon } from 'reactstrap';
const inputProps = {
@@ -22,37 +20,95 @@ const importanceLevels = Object.keys(TIP_IMPORTANCE_LEVELS).reduce(
export default {
title: 'Admin/Tip',
- decorators: [
- jsxDecorator,
- (Story) => (
-
-
),
- ]
+ component: Tip,
+ decorators: [jsxDecorator],
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `The Tip UI allows you to provide extra context on the purpose of a field. It is designed to be applied to an InputGroup.
+ You can use it with an \`InputField\` by passing the relevant configuration in the \`tip\` prop.
+ See the \`addTip\` method in \`TextField.php\` for an explanation on how to add Tips from the backend.
+ **Note:** The Tip UI will visually conflict with prefix / suffix rendering, as they use the same input-grou
+ functionality and this can't be stacked.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ }
+ }
+ },
+ argTypes: {
+ id: {
+ description: 'A unique identifier for this instance of the tip.',
+ control: 'text',
+ table: {
+ type: { summary: 'string|number' },
+ defaultValue: { summary: '' },
+ }
+ },
+ content: {
+ description: 'The text to render in the popover. Should be plaintext - HTML will not be parsed.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: '' },
+ }
+ },
+ icon: {
+ description: 'An icon from the icon font to use. See the Icon reference in the Pattern Library UI. Defaults to `lamp`.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: 'lamp' },
+ }
+ },
+ importance: {
+ description: `Should be specified as \`'normal'\` or \`'high'\` (defaults to \`'normal'\`). Designates the colour used for
+ the icon, and the accessible label of the toggle. Allowed values are defined in the exported \`TIP_IMPORTANCE_LEVELS\`
+ constant in \`Tip.js\`.`,
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: 'lamp' },
+ }
+ },
+ fieldTitle: {
+ description: 'A title for the field it relates to, which will be read aloud for screenreaders.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: 'lamp' },
+ }
+ },
+ }
};
export const _TitleTip = () => (
-
- {inputProps.title}
-
-
-
-
-
+
+ {inputProps.title}
+
+
+
+
+
);
export const _InputGroupTip = (args) => (
-
-
-
-
-
-
+
+
+
+
+
+
);
_InputGroupTip.args = {
diff --git a/client/src/components/Toasts/tests/Toasts-story.js b/client/src/components/Toasts/tests/Toasts-story.js
index fc61c2238..aa6b7869f 100644
--- a/client/src/components/Toasts/tests/Toasts-story.js
+++ b/client/src/components/Toasts/tests/Toasts-story.js
@@ -40,34 +40,55 @@ const toasts = [
export default {
title: 'Admin/Toasts',
- decorators: [
- jsxDecorator,
- (Story) =>
,
- ]
-};
-
-export const Single = (args) => (
-
-);
-
-Single.argsType = {
- text: {
- control: 'text'
- },
- type: {
- control: 'select',
- options: ['info', 'success', 'warning', 'error']
- },
- dismissed: {
- control: 'boolean'
+ component: Toast,
+ decorators: [jsxDecorator],
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Toast notifications should be used to notify the user that their action has altered the state of the application.
+ They are rendered as temporary messages in the top right corner of the Admin UI. A toast notification may have 1 or 2 _actions_ attached to it.
+ Use the provided toast Redux actions to push a new toast notification into the Redux store.
+ Alternatively, you can use the \`jQuery.noticeAdd\` to display a toast notification in legacy Entwine-based contexts.
+ By default, toast notifications are ephemeral. They should occur in response to a user action and communicate short, non-critical messages, such as confirming the success of an operation.
+ Do not use them to display critical information that requires immediate action from the user, such as validation errors. Consider using form alerts or modal alerts instead.
+ For notifications with a moderate importance (e.g.: warning and non-critical errors), consider disabling the toast notification timeout by setting the \`stay\` attribute to \`true\`.
+ If you attach actions to a toast notification, those should be shortcuts to a natural next step and an alternative
+ way of performing that task should be available. e.g.: A toast confirming the publication of a page could offer an action to "View live page". `
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ },
+ story: {
+ height: '300px'
+ }
+ },
},
- onDismiss,
- actions: {
- control: 'select',
- options: [0, 1, 2]
+ argsType: {
+ text: {
+ control: 'text'
+ },
+ type: {
+ control: 'select',
+ options: ['info', 'success', 'warning', 'error']
+ },
+ dismissed: {
+ control: 'boolean'
+ },
+ onDismiss,
+ actions: {
+ control: 'select',
+ options: [0, 1, 2]
+ }
}
};
+export const Single = (args) => (
+
+);
Single.args = {
text: 'The quick brown fox jumps over the lazy dog',
type: 'info',
@@ -75,11 +96,12 @@ Single.args = {
onDismiss
};
-export const List = (() => (
-
-));
+export const List = (args) => (
+
+);
+List.args = {
+ toasts,
+ onDismiss,
+ onPause,
+ onResume,
+};
diff --git a/client/src/components/Toolbar/tests/Toolbar-story.js b/client/src/components/Toolbar/tests/Toolbar-story.js
index 869bb2d61..995395cfc 100644
--- a/client/src/components/Toolbar/tests/Toolbar-story.js
+++ b/client/src/components/Toolbar/tests/Toolbar-story.js
@@ -9,12 +9,46 @@ const noop = () => {};
export default {
title: 'Admin/Toolbar',
+ component: Toolbar,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'The main header for sections in the CMS.'
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ },
+ },
+ },
+ argTypes: {
+ handleBackButtonClick: {
+ description: 'Provides custom handling of back button clicks.',
+ table: {
+ type: { summary: 'function' },
+ }
+ },
+ showBackButton: {
+ description: 'If `true` a back button is displayed. This prop is `false` by default.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ }
+ },
+ }
};
-export const NoBackButton = () => (
-
-);
+export const NoBackButton = args =>
;
+NoBackButton.args = {
+ showBackButton: false,
+};
-export const BackButton = () => (
-
-);
+export const BackButton = {
+ args: {
+ ...NoBackButton.args,
+ showBackButton: true,
+ }
+};
diff --git a/client/src/components/TreeDropdownField/tests/TreeDropdownField-story.js b/client/src/components/TreeDropdownField/tests/TreeDropdownField-story.js
index 4e5ce4e79..893139ea5 100644
--- a/client/src/components/TreeDropdownField/tests/TreeDropdownField-story.js
+++ b/client/src/components/TreeDropdownField/tests/TreeDropdownField-story.js
@@ -17,17 +17,33 @@ const store = createStore(
const fetchMock = () =>
Promise.resolve({ json: () => Promise.resolve(mockTree) });
-const props = {
- id: 'MyField',
- name: 'MyField',
- data: {
- urlTree: '',
- },
- fetch: fetchMock,
-};
-
export default {
title: 'Admin/TreeDropdownField',
+ component: TreeDropdownField,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `A complex select field that binds to an API to allow progressive fetching of nested items. \`TreeDropdownField\` was
+ originally developed for use with \`SiteTree\` and \`Folder\` objects, but can be used with any \`DataObject\` that has the
+ \`Hierarchy\` extension applied.
+ This React component also powers the PHP API's \`TreeMultiselectField\`, allowing multiple items to be selected, by
+ setting \`multi: true\`.
+ A Redux store with \`TreeDropdownFieldReducer\` installed must be provided as context if the component is used outside
+ the CMS. This is used to store the API responses and general state of each \`TreeDropdownField\` instance. You can open
+ the Redux Devtools panel to observe the actions and state used by the component.`
+ },
+ canvas: {
+ sourceState: 'hide',
+ },
+ controls: {
+ sort: 'alpha',
+ },
+ story: {
+ height: '200px'
+ }
+ },
+ },
decorators: [
(storyFn) => (
@@ -40,6 +56,13 @@ export default {
],
};
-export const Standard = () => (
-
-);
+export const Standard = args =>
;
+Standard.args = {
+ id: 'MyField',
+ name: 'MyField',
+ data: {
+ urlTree: '',
+ },
+ fetch: fetchMock,
+};
+
diff --git a/client/src/components/UsedOnTable/UsedOnTable.js b/client/src/components/UsedOnTable/UsedOnTable.js
index 8a750d0b3..b0888810b 100644
--- a/client/src/components/UsedOnTable/UsedOnTable.js
+++ b/client/src/components/UsedOnTable/UsedOnTable.js
@@ -61,7 +61,9 @@ class UsedOnTable extends PureComponent {
renderRow(data, index) {
const { id, type } = data;
- const rowData = [data].concat(data.ancestors).reverse();
+ const rowData = data.ancestors
+ ? [data].concat(data.ancestors).reverse()
+ : [data].reverse();
let cellLink = '#';
let isFirst = true;
const titleLinks = rowData.map((arr, i) => {
diff --git a/client/src/components/UsedOnTable/tests/UsedOnTable-story.js b/client/src/components/UsedOnTable/tests/UsedOnTable-story.js
index 4beabd0f3..fc46592cf 100644
--- a/client/src/components/UsedOnTable/tests/UsedOnTable-story.js
+++ b/client/src/components/UsedOnTable/tests/UsedOnTable-story.js
@@ -3,15 +3,56 @@ import { Component as UsedOnTable } from 'components/UsedOnTable/UsedOnTable';
export default {
title: 'Admin/UsedOnTable',
+ component: UsedOnTable,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `Generates a generic table for loading a DataObject's ownership details.
+ Relies on the \`SilverStripe\Admin\Forms\UsedOnTable\` FormField class on the PHP side, can be used independently if desired.`
+ },
+ canvas: {
+ sourceState: 'shown',
+ },
+ controls: {
+ sort: 'alpha',
+ },
+ story: {
+ height: '300px'
+ }
+ },
+ },
+ argTypes: {
+ loading: {
+ description: 'Shows loadding icon.',
+ control: 'boolean',
+ table: {
+ type: { summary: 'boolean' },
+ }
+ },
+ usedOn: {
+ control: 'object',
+ table: {
+ type: { summary: 'array' },
+ }
+ },
+ }
};
-export const LoadingState = () =>
;
+export const LoadingState = (args) =>
;
+LoadingState.args = {
+ loading: true,
+};
-export const NoOwners = () =>
;
+export const NoOwners = {
+ args: {
+ usedOn: []
+ }
+};
-export const WithOwners = () => (
-
(
state: 'draft',
link: 'http://www.google.co.nz',
},
- ]}
- />
-);
+ ]
+ }
+};
diff --git a/client/src/components/VersionedBadge/tests/VersionedBadge-story.js b/client/src/components/VersionedBadge/tests/VersionedBadge-story.js
index 6e23912c8..de148aa98 100644
--- a/client/src/components/VersionedBadge/tests/VersionedBadge-story.js
+++ b/client/src/components/VersionedBadge/tests/VersionedBadge-story.js
@@ -2,15 +2,37 @@ import React from 'react';
import VersionedBadge from 'components/VersionedBadge/VersionedBadge';
export default {
- title: 'Admin/Badges',
+ title: 'Admin/Badges/VersionedBadge',
component: VersionedBadge,
decorators: [
(Story) => ,
],
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: 'Badge component for displaying versioning states in a Bootstrap "badge" based style.'
+ },
+ canvas: {
+ sourceState: 'hide',
+ },
+ }
+ },
argTypes: {
status: {
+ description: 'The status for the badge, takes versioning states e.g. `draft`, `modified`, `live`, `archived`',
options: ['draft', 'modified', 'live', 'archived'],
- control: 'inline-radio'
+ control: 'inline-radio',
+ table: {
+ type: { summary: 'string' },
+ }
+ },
+ className: {
+ description: 'Any extra classes to apply for the badge.',
+ control: 'text',
+ table: {
+ type: { summary: 'string' },
+ }
}
}
};