React Component to integrate Flyouts into your project.
- easy to use
- pragmatic and predictable behaviours
- pre-defined styles for menu and dropdowns
- pre-defined light (default) and dark themes
- pre-defined styles for beautiful dropdown lists
- customizable
$ npm install react-flyout
react-flyout is composed by 3 files
- Core
- stateless component of the flyout itself
- handles everything related to how the flyout looks and behaves when opened
- Wrapper
- handles state
- exposes the open/close methods
- Styles
- well... you know... styles.
Create your own Flyout component in your project and extend it with the FlyoutWrapper to access the open/close methods. In this component you'll use your projects event system to listen to the open/close events.
import FlyoutWrapper from '';
class Flyout extends FlyoutWrapper {
// use this.open to open the flyout
// use this.close to close the flyout
// deal with these your using your own event system :)
}
See the example section for a use case.
You can pass various options as an object in the Flyout props <Flyout options={{}}>
- align: (string)
bottom left
: the Flyout will be aligned to the bottom of the trigger and will grow from right (of the trigger) to the leftright bottom
: the Flyout will be aligned to the right of the trigger and will grow from top (of the trigger) to bottom- ...
- type: (string)
dropdown
(default) /menu
- theme: (string)
light
(default) /dark
- fixed: (bool) set as
true
if the Flyout is contained withing a fixed element - mobile: (bool) when
true
the Flyout will open full width/height bellow the medium media query - dropdownIconsLeft: set as
true
iftype: dropdown
to style (left) icons on dropdown lists - dropdownIconsRight: set as
true
iftype: dropdown
to style (right) icons on dropdown lists
Media Queries are only customizable if you use the extend FlyoutWrapper method. You'll then need to set a this.mediaQueries
object on your Flyout Component.
this.mediaQueries = {
breakpointSmall: 640,
breakpointMedium: 1024,
breakpointLarge: 1920,
mediumUp: 641,
largeUp: 1025
};
Media Queries follow Foundation conventions and currently only the mediumUp value is used (when option.mobile = true
).
Styles are available as SCSS and use the BEM naming convention. Everything was kept simple and basic except the type: dropdown
which as pre-defined styles for (menu) lists.
Customization can be made by creating your own file:
// override default variables
$f_z_index_flyout: (...);
$f_z_index_flyout--dropdown: (...);
$f_font_size_big: (...);
$f_font_size_small: (...);
$f_color_light: (...);
$f_color_dark: (...);
$f_color_border: (...);
$f_border_radius: (...);
// import original styles
@import "react-flyout/flyout";
// define your styles
(...)
Bellow you'll find a use case on a React+Alt project.
Extends FlyoutWrapper and uses Alt's ActionListeners to listen to the open/close events without the need of a store.
'use strict';
import React from '';
import ActionListeners from '';
import {Constants} from '';
import FlyoutWrapper from '';
class Flyout extends FlyoutWrapper {
constructor(props) {
super();
}
// componentWillMount() {
// // CUSTOM MEDIA QUERIES
// this.mediaQueries = {
// breakpointSmall: 1,
// breakpointMedium: 2,
// breakpointLarge: 3,
// mediumUp: 4,
// largeUp: 5
// };
// }
componentWillUnmount() {
// REMOVE LISTENERS
let listeners = new ActionListeners(this.context.flux);
listeners.removeActionListener(this.listenToOpen);
listeners.removeActionListener(this.listenToClose);
}
componentDidMount() {
// ADD LISTENERS
let actions = this.context.flux.getActions(Constants.actions.flyout);
let listeners = new ActionListeners(this.context.flux);
this.listenToOpen = listeners.addActionListener(actions.OPEN_FLYOUT, (obj) => {
if (this.props.id !== obj.id) {
if (this.state.open) {
// console.info('flyout - listened to open for another flyout, closing:', obj.id);
this.close();
}
} else {
if (!this.state.open) {
// console.info('flyout - listened to open for this flyout, opening:', obj.id);
this.open();
}
}
});
this.listenToClose = listeners.addActionListener(actions.CLOSE_FLYOUT, (obj) => {
if (this.props.id !== obj.id) return false;
// console.info('flyout - listened to close', obj.id);
if (this.state.open) this.close();
});
}
};
Flyout.contextTypes = {
flux: React.PropTypes.object.isRequired
};
export default Flyout;
'use strict';
class FlyoutActions {
constructor() {
this.generateActions(
'openFlyout',
'closeFlyout'
);
}
}
export default FlyoutActions;
Mixin to import in the component that contains the Flyout trigger. Contains methods to make the action calls that will dispatch the open/close events which will be caught by the Flyout component above.
'use strict';
import React from '';
import {Constants} from '';
export const FlyoutsMixin = {
contextTypes: {
flux: React.PropTypes.object.isRequired
},
flyoutOpen(id) {
let obj = {};
obj.id = id;
this.context.flux.getActions(Constants.actions.flyout).openFlyout(obj);
},
flyoutClose(id) {
let obj = {};
obj.id = id;
this.context.flux.getActions(Constants.actions.flyout).closeFlyout(obj);
}
};
In this example you can see a dropdown Flyout.
Take a closer look at the first <li>
with both left and right icons.
import Flyout from '';
import {FlyoutsMixin} from '';
(...)
render() {
return (
<div className="has-flyout">
<button data-flyout-id="flyout-foobar" onClick={this.flyoutOpen.bind(this, 'flyout-foobar')}>TOGGLE</button>
<Flyout id="flyout-foobar" options={{align: 'bottom left', type: 'dropdown', dropdownIconsLeft: true, dropdownIconsRight: true}}>
<ul>
<li>
<a href="#">
<i class="fa fa-sort-alpha-asc"></i>
Order By 0
<i class="fa fa-check check"></i>
</a>
</li>
<li>
<a href="#">
<i class="fa fa-sort-alpha-desc"></i>
Order By 1
</a>
</li>
<li>
<a href="#">
<i class="fa fa-clock-o"></i>
Order By 2
</a>
</li>
<li>
<a href="#">
<i class="fa fa-clock-o"></i>
Order By 3
</a>
</li>
</ul>
</Flyout>
</div>
);
}
This example showcases a hamburguer menu that opens a Flyout when clicked.
If the topbar that contains the hamburguer is fixed options.fixed = true
is necessary.
import Flyout from '';
import {FlyoutsMixin} from '';
(...)
render() {
return (
<div className="has-flyout">
<i className="fa fa-bars" data-flyout-id="flyout-foobar" onClick={this.flyoutOpen.bind(this, 'flyout-foobar')}></i>
<Flyout id="flyout-foobar" options={{align: 'bottom right', mobile: true, theme: 'dark', fixed: true}}>
content
</Flyout>
</div>
);
}