Repository: react-materialize/react-materialize
Pull request #784 (2019-03-24 11:38:51)

Fix Collapsable expandable bug
Collapsible was not allowed to be set to expandable, fixed


Patch:
diff --git a/src/Collapsible.js b/src/Collapsible.js
index e5725b7..5d3f35c 100644
--- a/src/Collapsible.js
+++ b/src/Collapsible.js
@@ -15,7 +15,10 @@ class Collapsible extends Component {
   }
 
   componentDidMount() {
-    this.instance = M.Collapsible.init(this._collapsible, this.props.options);
+    this.instance = M.Collapsible.init(this._collapsible, {
+      accordion: this.props.accordion,
+      ...this.props.options
+    });
   }
 
   componentWillUnmount() {
@@ -29,11 +32,12 @@ class Collapsible extends Component {
 
     delete props.defaultActiveKey;
 
+    const collapsible = accordion ? 'accordion' : 'expandable';
     const classes = {
-      collapsible: true,
+      collapsible,
+      expandable: accordion !== true,
       popout
     };
-    const collapsible = accordion ? 'accordion' : 'expandable';
 
     return (
       <ul
@@ -87,7 +91,7 @@ Collapsible.propTypes = {
   /**
    * There are two ways a collapsible can behave. It can either allow multiple sections to stay open,
    * or it can only allow one section to stay open at a time, which is called an accordion.
-   * @default false
+   * @default true
    */
   accordion: PropTypes.bool,
   className: PropTypes.string,
diff --git a/src/Dropdown.js b/src/Dropdown.js
index 40b026d..4cb65aa 100644
--- a/src/Dropdown.js
+++ b/src/Dropdown.js
@@ -16,7 +16,7 @@ class Dropdown extends Component {
 
     if (typeof M !== undefined) {
       const selector = document.querySelectorAll(this._trigger);
-      this.instance = M.Dropdown.init(selector, options)[0];
+      this.instance = M.Dropdown.init(selector, options);
     }
   }
 
diff --git a/src/NavItem.js b/src/NavItem.js
index 9a484ad..471a0a8 100644
--- a/src/NavItem.js
+++ b/src/NavItem.js
@@ -1,9 +1,14 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
-const NavItem = ({ divider, ...props }) => {
+const NavItem = ({ divider, children, href = '', onClick, ...props }) => {
   if (divider) return <li className="divider" />;
-  return <a {...props} />;
+  const a = onClick ? (
+    <a onClick={onClick}>{children}</a>
+  ) : (
+    <a href={href}>{children}</a>
+  );
+  return <li {...props}>{a}</li>;
 };
 
 NavItem.propTypes = {
diff --git a/stories/Collapsible.stories.js b/stories/Collapsible.stories.js
index 9090033..dbaf275 100644
--- a/stories/Collapsible.stories.js
+++ b/stories/Collapsible.stories.js
@@ -9,11 +9,12 @@ stories.addParameters({
   info: {
     text: `Collapsibles are accordion elements that expand 
     when clicked on. They allow you to hide content that is 
-    not immediately relevant to the user.`
+    not immediately relevant to the user. Expandable can be 
+    set by adding accordion={false} as a prop.`
   }
 });
 
-stories.add('Collapsible - CollapsibleItem', () => (
+stories.add('Default', () => (
   <Collapsible>
     <CollapsibleItem header="Better safe than sorry. That's my motto." icon='filter_drama'>
       Better safe than sorry. That's my motto.
@@ -26,3 +27,17 @@ stories.add('Collapsible - CollapsibleItem', () => (
     </CollapsibleItem>
   </Collapsible>
 ));
+
+stories.add('Expandable', () => (
+  <Collapsible accordion={false}>
+    <CollapsibleItem header="Better safe than sorry. That's my motto." icon='filter_drama'>
+      Better safe than sorry. That's my motto.
+    </CollapsibleItem>
+    <CollapsibleItem header="Yeah, you do seem to have a little 'shit creek' action going." icon='place'>
+      Yeah, you do seem to have a little 'shit creek' action going.
+    </CollapsibleItem>
+    <CollapsibleItem header="You know, FYI, you can buy a paddle. Did you not plan for this contingency?" icon='whatshot'>
+      You know, FYI, you can buy a paddle. Did you not plan for this contingency?
+    </CollapsibleItem>
+  </Collapsible>
+));


Test patch:
diff --git a/test/Collapsible.spec.js b/test/Collapsible.spec.js
index 3a933dd..609c2e7 100644
--- a/test/Collapsible.spec.js
+++ b/test/Collapsible.spec.js
@@ -19,6 +19,7 @@ describe('<Collapsible />', () => {
   const restore = mocker('Collapsible', collapsibleMock);
 
   const options = {
+    accordion: true,
     onOpenStart: () => {},
     inDuration: 100,
     outDuration: 50
@@ -48,8 +49,8 @@ describe('<Collapsible />', () => {
     expect(wrapper).toMatchSnapshot();
   });
 
-  test('with accordion', () => {
-    wrapper = shallow(<Collapsible accordion />);
+  test('expandable', () => {
+    wrapper = shallow(<Collapsible accordion={false} />);
     expect(wrapper).toMatchSnapshot();
   });
 
diff --git a/test/DropdownButton.spec.js b/test/DropdownButton.spec.js
index 0db2491..60274a3 100644
--- a/test/DropdownButton.spec.js
+++ b/test/DropdownButton.spec.js
@@ -43,7 +43,7 @@ describe('<Dropdown />', () => {
     const dropdownMock = {
       init: (el, options) => {
         dropdownInitMock(options);
-        return [{ destroy: dropdownInstanceDestroyMock }];
+        return { destroy: dropdownInstanceDestroyMock };
       }
     };
 
diff --git a/test/NavItem.spec.js b/test/NavItem.spec.js
index 236db37..50029a6 100644
--- a/test/NavItem.spec.js
+++ b/test/NavItem.spec.js
@@ -11,6 +11,16 @@ describe('<NavItem />', () => {
     expect(wrapper).toMatchSnapshot();
   });
 
+  test('passes className to first node', () => {
+    wrapper = shallow(
+      <NavItem className="red" href="get-started.html">
+        Getting
+      </NavItem>
+    );
+
+    expect(wrapper.find('li.red')).toHaveLength(1);
+  });
+
   test('passes node as a child', () => {
     wrapper = shallow(
       <NavItem href="get-started.html">
@@ -41,13 +51,27 @@ describe('<NavItem />', () => {
 
   test('passes onClick as parameter', () => {
     const onClick = jest.fn();
-    wrapper = shallow(<NavItem onClick={onClick}>Getting</NavItem>);
+    wrapper = shallow(
+      <NavItem onClick={onClick} href="get-started.html">
+        Getting
+      </NavItem>
+    );
 
     expect(wrapper).toMatchSnapshot();
 
-    wrapper.simulate('click');
+    wrapper
+      .children()
+      .at(0)
+      .simulate('click');
 
     expect(onClick).toHaveBeenCalled();
+
+    expect(
+      wrapper
+        .children()
+        .at(0)
+        .prop('href')
+    ).toBeUndefined();
   });
 
   test('passes href as parameter', () => {
diff --git a/test/__snapshots__/Collapsible.spec.js.snap b/test/__snapshots__/Collapsible.spec.js.snap
index b96eff5..8624647 100644
--- a/test/__snapshots__/Collapsible.spec.js.snap
+++ b/test/__snapshots__/Collapsible.spec.js.snap
@@ -122,6 +122,13 @@ exports[`<Collapsible /> defaultActiveKey 2`] = `
 </Collapsible>
 `;
 
+exports[`<Collapsible /> expandable 1`] = `
+<ul
+  className="collapsible expandable"
+  data-collapsible="expandable"
+/>
+`;
+
 exports[`<Collapsible /> renders 1`] = `
 <ul
   className="collapsible"
@@ -393,13 +400,6 @@ exports[`<Collapsible /> updates activeKey 2`] = `
 </Collapsible>
 `;
 
-exports[`<Collapsible /> with accordion 1`] = `
-<ul
-  className="collapsible"
-  data-collapsible="accordion"
-/>
-`;
-
 exports[`<Collapsible /> with expanded prop 1`] = `
 <Collapsible
   accordion={true}
diff --git a/test/__snapshots__/NavItem.spec.js.snap b/test/__snapshots__/NavItem.spec.js.snap
index b49671f..7c09ca3 100644
--- a/test/__snapshots__/NavItem.spec.js.snap
+++ b/test/__snapshots__/NavItem.spec.js.snap
@@ -1,35 +1,43 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`<NavItem /> passes href as parameter 1`] = `
-<a
-  href="get-started.html"
->
-  Getting
-</a>
+<li>
+  <a
+    href="get-started.html"
+  >
+    Getting
+  </a>
+</li>
 `;
 
 exports[`<NavItem /> passes node as a child 1`] = `
-<a
-  href="get-started.html"
->
-  <p>
-    Go Home
-  </p>
-</a>
+<li>
+  <a
+    href="get-started.html"
+  >
+    <p>
+      Go Home
+    </p>
+  </a>
+</li>
 `;
 
 exports[`<NavItem /> passes onClick as parameter 1`] = `
-<a
-  onClick={[MockFunction]}
->
-  Getting
-</a>
+<li>
+  <a
+    onClick={[MockFunction]}
+  >
+    Getting
+  </a>
+</li>
 `;
 
 exports[`<NavItem /> renders 1`] = `
-<a
-  href="get-started.html"
->
-  Getting
-</a>
+<li>
+  <a
+    href="get-started.html"
+  >
+    Getting
+  </a>
+</li>
 `;