diff --git a/docs/app/Examples/modules/Accordion/Types/index.js b/docs/app/Examples/modules/Accordion/Types/index.js
index 27e4cd1550..c1db7b86ab 100644
--- a/docs/app/Examples/modules/Accordion/Types/index.js
+++ b/docs/app/Examples/modules/Accordion/Types/index.js
@@ -12,8 +12,7 @@ const AccordionTypesExamples = () => (
examplePath='modules/Accordion/Types/AccordionExampleStandard'
/>
An Accordion can be defined using the panels
prop.}
examplePath='modules/Accordion/Types/AccordionExamplePanelsProp'
>
@@ -21,17 +20,6 @@ const AccordionTypesExamples = () => (
{' '}They can also define an onClick
key to be applied to the Accordion.Title
.
-
-
- An active
prop on an
- {' '}<Accordion.Title>
or <Accordion.Content>
- {' '}will override the <Accordion>
<activeIndex>
prop.
-
-
({
+ key: `panel-${i}`,
+ title: ,
+ content: (
+
+ ),
+}))
+
+const AccordionExamplePanelsPropWithCustomTitleAndContent = () => (
+
+)
+
+export default AccordionExamplePanelsPropWithCustomTitleAndContent
diff --git a/docs/app/Examples/modules/Accordion/Usage/index.js b/docs/app/Examples/modules/Accordion/Usage/index.js
new file mode 100644
index 0000000000..d937e4317d
--- /dev/null
+++ b/docs/app/Examples/modules/Accordion/Usage/index.js
@@ -0,0 +1,28 @@
+import React from 'react'
+
+import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
+import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'
+
+import { Message } from 'semantic-ui-react'
+
+const AccordionUsageExamples = () => (
+
+
+
+ An active
prop on an
+ {' '}<Accordion.Title>
or <Accordion.Content>
+ {' '}will override the <Accordion>
<activeIndex>
prop.
+
+
+
+
+)
+
+export default AccordionUsageExamples
diff --git a/docs/app/Examples/modules/Accordion/index.js b/docs/app/Examples/modules/Accordion/index.js
index a452332fa4..5b5da95be1 100644
--- a/docs/app/Examples/modules/Accordion/index.js
+++ b/docs/app/Examples/modules/Accordion/index.js
@@ -1,11 +1,13 @@
import React from 'react'
import Types from './Types'
import Variations from './Variations'
+import Usage from './Usage'
const AccordionExamples = () => (
+
)
diff --git a/src/modules/Accordion/Accordion.js b/src/modules/Accordion/Accordion.js
index a11d541c6c..42523aed49 100644
--- a/src/modules/Accordion/Accordion.js
+++ b/src/modules/Accordion/Accordion.js
@@ -1,5 +1,5 @@
-import cx from 'classnames'
import _ from 'lodash'
+import cx from 'classnames'
import React, { Children, cloneElement, PropTypes } from 'react'
import {
@@ -9,7 +9,7 @@ import {
META,
useKeyOnly,
} from '../../lib'
-import Icon from '../../elements/Icon'
+
import AccordionContent from './AccordionContent'
import AccordionTitle from './AccordionTitle'
@@ -54,14 +54,16 @@ export default class Accordion extends Component {
/**
* Create simple accordion panels from an array of { text: , content: } objects.
* Object can optionally define an `active` key to open/close the panel.
+ * Object can opitonally define a `key` key used for title and content nodes' keys.
* Mutually exclusive with children.
* TODO: AccordionPanel should be a sub-component
*/
panels: customPropTypes.every([
customPropTypes.disallow(['children']),
PropTypes.arrayOf(PropTypes.shape({
+ key: PropTypes.string,
active: PropTypes.bool,
- title: PropTypes.string,
+ title: customPropTypes.contentShorthand,
content: customPropTypes.contentShorthand,
onClick: PropTypes.func,
})),
@@ -158,17 +160,14 @@ export default class Accordion extends Component {
if (panel.onClick) panel.onClick(e, i)
}
- children.push(
-
-
- {panel.title}
-
- )
- children.push(
-
- {panel.content}
-
- )
+ // implement all methods of creating a key that are supported in factories
+ const key = panel.key
+ || _.isFunction(panel.childKey) && panel.childKey(panel)
+ || panel.childKey && panel.childKey
+ || panel.title
+
+ children.push(AccordionTitle.create({ active: isActive, onClick, key: `${key}-title`, content: panel.title }))
+ children.push(AccordionContent.create({ active: isActive, key: `${key}-content`, content: panel.content }))
})
return children
diff --git a/src/modules/Accordion/AccordionContent.js b/src/modules/Accordion/AccordionContent.js
index 2a5e509953..1865cc5692 100644
--- a/src/modules/Accordion/AccordionContent.js
+++ b/src/modules/Accordion/AccordionContent.js
@@ -1,5 +1,6 @@
-import cx from 'classnames'
+import _ from 'lodash'
import React, { PropTypes } from 'react'
+import cx from 'classnames'
import {
customPropTypes,
@@ -7,13 +8,14 @@ import {
getUnhandledProps,
META,
useKeyOnly,
+ createShorthandFactory,
} from '../../lib'
/**
* A content sub-component for Accordion component.
*/
function AccordionContent(props) {
- const { active, children, className } = props
+ const { active, children, className, content } = props
const classes = cx(
'content',
useKeyOnly(active, 'active'),
@@ -22,7 +24,11 @@ function AccordionContent(props) {
const rest = getUnhandledProps(AccordionContent, props)
const ElementType = getElementType(AccordionContent, props)
- return {children}
+ return (
+
+ {_.isNil(children) ? content : children}
+
+ )
}
AccordionContent.propTypes = {
@@ -37,6 +43,9 @@ AccordionContent.propTypes = {
/** Additional classes. */
className: PropTypes.string,
+
+ /** Shorthand for primary content. */
+ content: customPropTypes.contentShorthand,
}
AccordionContent._meta = {
@@ -45,4 +54,6 @@ AccordionContent._meta = {
parent: 'Accordion',
}
+AccordionContent.create = createShorthandFactory(AccordionContent, content => ({ content }))
+
export default AccordionContent
diff --git a/src/modules/Accordion/AccordionTitle.js b/src/modules/Accordion/AccordionTitle.js
index 6762f7f99d..823f8be064 100644
--- a/src/modules/Accordion/AccordionTitle.js
+++ b/src/modules/Accordion/AccordionTitle.js
@@ -1,3 +1,4 @@
+import _ from 'lodash'
import cx from 'classnames'
import React, { Component, PropTypes } from 'react'
@@ -7,8 +8,11 @@ import {
getUnhandledProps,
META,
useKeyOnly,
+ createShorthandFactory,
} from '../../lib'
+import Icon from '../../elements/Icon'
+
/**
* A title sub-component for Accordion component.
*/
@@ -26,6 +30,9 @@ export default class AccordionTitle extends Component {
/** Additional classes. */
className: PropTypes.string,
+ /** Shorthand for primary content. */
+ content: customPropTypes.contentShorthand,
+
/**
* Called on click.
*
@@ -52,6 +59,7 @@ export default class AccordionTitle extends Component {
active,
children,
className,
+ content,
} = this.props
const classes = cx(
@@ -62,6 +70,21 @@ export default class AccordionTitle extends Component {
const rest = getUnhandledProps(AccordionTitle, this.props)
const ElementType = getElementType(AccordionTitle, this.props)
- return {children}
+ if (_.isNil(content)) {
+ return (
+
+ {children}
+
+ )
+ }
+
+ return (
+
+
+ {content}
+
+ )
}
}
+
+AccordionTitle.create = createShorthandFactory(AccordionTitle, content => ({ content }))
diff --git a/src/modules/Accordion/index.d.ts b/src/modules/Accordion/index.d.ts
index fbbc3457e0..13e65b9a16 100644
--- a/src/modules/Accordion/index.d.ts
+++ b/src/modules/Accordion/index.d.ts
@@ -31,8 +31,9 @@ interface AccordionProps {
onTitleClick?: (event: React.MouseEvent, index: number | number[]) => void;
/**
- * Create simple accordion panels from an array of { text: , content: } objects.
+ * Create simple accordion panels from an array of { text: , content: } objects.
* Object can optionally define an `active` key to open/close the panel.
+ * Object can opitonally define a `key` key used for title and content nodes' keys.
* Mutually exclusive with children.
*/
panels?: Array;
diff --git a/test/specs/modules/Accordion/Accordion-test.js b/test/specs/modules/Accordion/Accordion-test.js
index 510f1ce110..c3a9b5ec05 100644
--- a/test/specs/modules/Accordion/Accordion-test.js
+++ b/test/specs/modules/Accordion/Accordion-test.js
@@ -242,9 +242,9 @@ describe('Accordion', () => {
.should.not.have.descendants('#do-not-find-me')
})
- it('adds text and content sibling children', () => {
+ it('adds text title and text content sibling children', () => {
const panels = [{
- text: faker.lorem.sentence(),
+ title: faker.lorem.sentence(),
content: faker.lorem.paragraph(),
}]
const wrapper = mount()
@@ -254,22 +254,40 @@ describe('Accordion', () => {
.should.have.className('title')
.and.contain.text(panels[0].title)
+ expect(wrapper.childAt(0).key()).to.equal(`${panels[0].title}-title`)
+
wrapper
.childAt(1)
.should.have.className('content')
.and.contain.text(panels[0].content)
+
+ expect(wrapper.childAt(1).key()).to.equal(`${panels[0].title}-content`)
})
- it('allows setting the active prop', () => {
+ it('adds custom element title and custom element content sibling children', () => {
const panels = [{
- active: true,
- title: faker.lorem.sentence(),
- content: faker.lorem.paragraph(),
- }, {
- active: false,
- title: faker.lorem.sentence(),
- content: faker.lorem.paragraph(),
+ key: 'panel-1',
+ title: ({faker.lorem.sentence()}
),
+ content: ({faker.lorem.paragraph()}
),
}]
+ const wrapper = mount()
+
+ wrapper
+ .childAt(0)
+ .should.have.className('title')
+ .and.contain(panels[0].title)
+
+ expect(wrapper.childAt(0).key()).to.equal('panel-1-title')
+
+ wrapper
+ .childAt(1)
+ .should.have.className('content')
+ .and.contain(panels[0].content)
+
+ expect(wrapper.childAt(1).key()).to.equal('panel-1-content')
+ })
+
+ const checkIfAllowsSettingTheActiveProp = panels => {
const wrapper = shallow()
// first panel (active)
@@ -295,12 +313,40 @@ describe('Accordion', () => {
.find('AccordionContent')
.at(1)
.should.have.prop('active', false)
+ }
+
+ it('allows setting the active prop', () => {
+ const panels = [{
+ active: true,
+ title: faker.lorem.sentence(),
+ content: faker.lorem.paragraph(),
+ }, {
+ active: false,
+ title: faker.lorem.sentence(),
+ content: faker.lorem.paragraph(),
+ }]
+
+ checkIfAllowsSettingTheActiveProp(panels)
+ })
+
+ it('allows setting the active prop for custom title and content', () => {
+ const panels = [{
+ active: true,
+ title: (faker.lorem.sentence()
),
+ content: (faker.lorem.paragraph()
),
+ }, {
+ active: false,
+ title: (faker.lorem.sentence()
),
+ content: (faker.lorem.paragraph()
),
+ }]
+
+ checkIfAllowsSettingTheActiveProp(panels)
})
describe('onClick', () => {
it('can be omitted', () => {
const panels = [{
- text: faker.lorem.sentence(),
+ title: faker.lorem.sentence(),
content: faker.lorem.paragraph(),
}]
const wrapper = mount()
diff --git a/test/specs/modules/Accordion/AccordionContent-test.js b/test/specs/modules/Accordion/AccordionContent-test.js
index b6d803f14e..ecd68f3e7a 100644
--- a/test/specs/modules/Accordion/AccordionContent-test.js
+++ b/test/specs/modules/Accordion/AccordionContent-test.js
@@ -5,4 +5,5 @@ describe('AccordionContent', () => {
common.isConformant(AccordionContent)
common.rendersChildren(AccordionContent)
common.propKeyOnlyToClassName(AccordionContent, 'active')
+ common.implementsCreateMethod(AccordionContent)
})
diff --git a/test/specs/modules/Accordion/AccordionTitle-test.js b/test/specs/modules/Accordion/AccordionTitle-test.js
index 125d0f18f2..7dcb1c960c 100644
--- a/test/specs/modules/Accordion/AccordionTitle-test.js
+++ b/test/specs/modules/Accordion/AccordionTitle-test.js
@@ -6,4 +6,5 @@ describe('AccordionTitle', () => {
common.isConformant(AccordionTitle)
common.rendersChildren(AccordionTitle)
common.propKeyOnlyToClassName(AccordionTitle, 'active')
+ common.implementsCreateMethod(AccordionTitle)
})