Repository: react-materialize/react-materialize
Pull request #736 (2018-12-23 16:08:55)

3.0.0-beta.0 FAB Button
# Description
Updates `fixed action button` to work with materializecss 1.0.0.
Issue: #583
Motivation: this change is necessary so `fab` can properly work with materializecss 1.0.0.

Before 1.0.0:
- FAB worked with `'vertical', 'horizontal', 'fabClickOnly' and 'toolbar'` [options](https://github.com/react-materialize/react-materialize/blob/02712763e88f4aae53fa08bf090bf66312273489/src/Button.js#L118)
- Hover and click events were manually added during [fab render](https://github.com/react-materialize/react-materialize/blob/02712763e88f4aae53fa08bf090bf66312273489/src/Button.js#L81)

Materializecss 1.0.0
- FAB now works with `'top', 'left', right', 'bottom', 'hoverEnabled', 'toolbarEnabled'`; all into fabs initialization.
- Houver and click events are initialized by materializecss js now (as tooltio does)
 
## Type of change
- [x] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] This change requires a documentation update

# How Has This Been Tested?
- Unit testing
- Browser testing with stories

# Checklist:
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] My changes generate no new warnings
- [x] I have not generated a new package version. (the maintainers will handle that)



Patch:
diff --git a/src/Button.js b/src/Button.js
index 4188810..60a984a 100644
--- a/src/Button.js
+++ b/src/Button.js
@@ -21,7 +21,7 @@ class Button extends Component {
     }
 
     if (fab) {
-      this.instance = M.FloatingActionButton.init(this._floatingActionBtn);
+      this.instance = M.FloatingActionButton.init(this._floatingActionBtn, fab);
     }
   }
 
@@ -36,7 +36,6 @@ class Button extends Component {
       className,
       node,
       fab,
-      fabClickOnly,
       modal,
       flat,
       floating,
@@ -48,7 +47,6 @@ class Button extends Component {
       ...other
     } = this.props;
 
-    const toggle = fabClickOnly ? 'click-to-toggle' : '';
     let C = node;
     let classes = {
       btn: true,
@@ -72,7 +70,7 @@ class Button extends Component {
       classes['modal-' + modal] = true;
     }
     if (fab) {
-      return this.renderFab(cx(classes, className), fab, toggle);
+      return this.renderFab(cx(classes, className));
     } else {
       return (
         <C
@@ -90,12 +88,11 @@ class Button extends Component {
     }
   }
 
-  renderFab(className, mode, clickOnly) {
-    const classes = cx(mode, clickOnly);
+  renderFab(className) {
     return (
       <div
         ref={el => (this._floatingActionBtn = el)}
-        className={cx('fixed-action-btn', classes)}
+        className={cx('fixed-action-btn')}
       >
         <a className={className}>{this.renderIcon()}</a>
         <ul>
@@ -129,9 +126,22 @@ Button.propTypes = {
   /**
    * Fixed action button
    * If enabled, any children button will be rendered as actions, remember to provide an icon.
-   * @default vertical. This will disable any onClick function from being called on the main button.
+   *  FAB Options are here: https://materializecss.com/floating-action-button.html#options
+   * @default false
+   * @default options {
+   *  direction: 'top',
+   *  hoverEnabled: true,
+   *  toolbarEnabled: false,
+   * }
    */
-  fab: PropTypes.oneOf(['vertical', 'horizontal', 'toolbar']),
+  fab: PropTypes.oneOfType([
+    PropTypes.bool,
+    PropTypes.shape({
+      direction: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
+      hoverEnabled: PropTypes.bool,
+      toolbarEnabled: PropTypes.bool
+    })
+  ]),
   /**
    * The icon to display, if specified it will create a button with the material icon.
    */
@@ -164,12 +174,7 @@ Button.propTypes = {
     'purple',
     'green',
     'teal'
-  ]),
-  /**
-   * FAB Click-Only
-   * Turns a FAB from a hover-toggle to a click-toggle
-   */
-  fabClickOnly: PropTypes.bool
+  ])
 };
 
 Button.defaultProps = {


Test patch:
diff --git a/test/Button.spec.js b/test/Button.spec.js
index 1a6d181..5630ad8 100644
--- a/test/Button.spec.js
+++ b/test/Button.spec.js
@@ -47,14 +47,14 @@ describe('Button', () => {
   });
 
   test('should apply FAB hover', () => {
-    wrapper = shallow(<Button fab="vertical">Stuff</Button>);
+    wrapper = shallow(<Button fab>Stuff</Button>);
     wrapper.simulate('hover');
     expect(wrapper.find('.fixed-action-btn active'));
   });
 
   test('should apply FAB click-only', () => {
     wrapper = shallow(
-      <Button fab="horizontal" fabClickOnly>
+      <Button fab fabOptions={{ hoverEnabled: false }}>
         Stuff
       </Button>
     );
@@ -132,28 +132,32 @@ describe('Button', () => {
       }
     };
     const restore = mocker('FloatingActionButton', fabMock);
-    const fab = 'vertical';
+    const fabOptions = {
+      direction: 'left',
+      hoverEnabled: false,
+      toolbarEnabled: true
+    };
     let wrapper;
+    const FabButton = (fabOptions = true) => (
+      <Button
+        floating
+        fab={fabOptions}
+        className="red"
+        large
+        style={{
+          bottom: '45px',
+          right: '24px'
+        }}
+      >
+        <Button floating icon="insert_chart" className="red" />
+        <Button floating icon="format_quote" className="yellow darken-1" />
+        <Button floating icon="publish" className="green" />
+        <Button floating icon="attach_file" className="blue" />
+      </Button>
+    );
 
     beforeEach(() => {
       fabInitMock.mockClear();
-      wrapper = mount(
-        <Button
-          floating
-          fab={fab}
-          className="red"
-          large
-          style={{
-            bottom: '45px',
-            right: '24px'
-          }}
-        >
-          <Button floating icon="insert_chart" className="red" />
-          <Button floating icon="format_quote" className="yellow darken-1" />
-          <Button floating icon="publish" className="green" />
-          <Button floating icon="attach_file" className="blue" />
-        </Button>
-      );
     });
 
     afterAll(() => {
@@ -161,9 +165,15 @@ describe('Button', () => {
     });
 
     test('initializes FloatingActionButton instance', () => {
+      wrapper = mount(FabButton());
       expect(fabInitMock).toHaveBeenCalled();
     });
+    test('initializes FloatingActionButton with fab options', () => {
+      wrapper = mount(FabButton(fabOptions));
+      expect(fabInitMock).toHaveBeenCalledWith(fabOptions);
+    });
     test('destroys FloatingActionButton instance when unmounted', () => {
+      wrapper = mount(FabButton());
       wrapper.unmount();
       expect(fabInstanceDestroyMock).toHaveBeenCalled();
     });