Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow expand "AccordionItem" programmatically #13

Merged
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ ReactDOM.render(<Example />, document.querySelector('[data-mount]'));
<td>accordion</td>
<td>CSS class(es) applied to the component</td>
</tr>
<tr>
<td>activeItems</td>
<td>Array</td>
<td>[]</td>
<td>Indexes (or custom keys) to pre expand items. Can be changed dynamically. Doesn't have the priority against `AccordionItem - expanded` on first render.</td>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have some other documentation mentioning this customKey prop.

</tr>
</tbody>
</table>

Expand Down Expand Up @@ -128,6 +134,12 @@ ReactDOM.render(<Example />, document.querySelector('[data-mount]'));
<td>null</td>
<td>Class name for hidden body state</td>
</tr>
<tr>
<td>customKey</td>
<td>String</td>
<td></td>
<td>Custom key to be used as a reference in `Accordion - activeItems`</td>
</tr>
</tbody>
</table>

Expand Down
4 changes: 4 additions & 0 deletions demo/css/demo.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
margin-top: 1.875rem;
}

.u-margin-right {
margin-right: 1.875rem;
}

.block {
padding: 1.25rem;
}
Expand Down
1,095 changes: 581 additions & 514 deletions demo/js/demo.js

Large diffs are not rendered by default.

242 changes: 242 additions & 0 deletions src/Accordion/__snapshots__/accordion.spec.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Accordion close accordions via accordion props props dynamicly 1`] = `
<div
className="accordion"
role="tablist"
>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion different className 1`] = `
<div
className="testCSSClass"
Expand All @@ -24,6 +48,119 @@ exports[`Accordion different className 1`] = `
</div>
`;

exports[`Accordion different className with the same activeItems prop 1`] = `
<div
className="test-2"
role="tablist"
>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={true}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion expand accordion via accordion props dynamicly 1`] = `
<div
className="accordion"
role="tablist"
>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={true}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion expand multiple accordions via accordion props props dynamicly 1`] = `
<div
className="accordion"
role={null}
>
<div
accordion={false}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={false}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={false}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion expand multiple accordions via accordion props props dynamicly with default
expanded on accordion items 1`] = `
<div
className="accordion"
role={null}
>
<div
accordion={false}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={false}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={false}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion handleClick function accordion false 1`] = `
<div
className="accordion"
Expand Down Expand Up @@ -168,6 +305,111 @@ exports[`Accordion handles disabled children 1`] = `
</div>
`;

exports[`Accordion pre expand accordion via accordion props 1`] = `
<div
className="accordion"
role="tablist"
>
<div
accordion={true}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion pre expand accordion via accordion props vs accordion item props. Expanded only second item. 1`] = `
<div
className="accordion"
role="tablist"
>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={true}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion pre expand accordion via accordion props with custom key 1`] = `
<div
className="accordion"
role="tablist"
>
<div
accordion={true}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={true}
customKey="custom"
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion pre expand multiple accordions via accordion props 1`] = `
<div
className="accordion"
role={null}
>
<div
accordion={false}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={false}
disabled={undefined}
expanded={false}
onClick={[Function]}
>
Fake Child
</div>
<div
accordion={false}
disabled={undefined}
expanded={true}
onClick={[Function]}
>
Fake Child
</div>
</div>
`;

exports[`Accordion pre expanded accordion 1`] = `
<div
className="accordion"
Expand Down
35 changes: 31 additions & 4 deletions src/Accordion/accordion.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { isArraysEqualShallow } from '../utils';

const defaultProps = {
accordion: true,
onChange: () => {},
className: 'accordion',
activeItems: [],
};

const propTypes = {
Expand All @@ -13,6 +15,10 @@ const propTypes = {
PropTypes.arrayOf(PropTypes.element),
PropTypes.object,
]).isRequired,
activeItems: PropTypes.arrayOf(PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
])),
className: PropTypes.string,
onChange: PropTypes.func,
};
Expand All @@ -28,17 +34,38 @@ class Accordion extends Component {
this.renderItems = this.renderItems.bind(this);
}

componentWillReceiveProps(nextProps) {
if (!isArraysEqualShallow(nextProps.activeItems, this.state.activeItems)) {
let newActiveItems;
if (nextProps.accordion) {
newActiveItems = nextProps.activeItems.length
? [nextProps.activeItems[0]]
: [];
} else {
newActiveItems = nextProps.activeItems.slice();
}
this.setState({
activeItems: newActiveItems,
});

nextProps.onChange(nextProps.accordion ? newActiveItems[0] : newActiveItems);
}
}

preExpandedItems() {
const activeItems = [];
let activeItems = [];
React.Children.map(this.props.children, (item, index) => {
if (item.props.expanded) {
if (this.props.accordion) {
if (activeItems.length === 0) activeItems.push(index);
if (activeItems.length === 0) activeItems.push(item.props.customKey || index);
} else {
activeItems.push(index);
activeItems.push(item.props.customKey || index);
}
}
});
if (activeItems.length === 0 && this.props.activeItems.length !== 0) {
activeItems = this.props.accordion ? [this.props.activeItems[0]] : this.props.activeItems.slice();
}
return activeItems;
}

Expand Down Expand Up @@ -68,7 +95,7 @@ class Accordion extends Component {
const { accordion, children } = this.props;

return React.Children.map(children, (item, index) => {
const key = index;
const key = item.props.customKey || index;
const expanded = (this.state.activeItems.indexOf(key) !== -1) && (!item.props.disabled);

return React.cloneElement(item, {
Expand Down
Loading