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

Disable popper when inNavbar #692

Merged
merged 6 commits into from
Dec 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/lib/Components/DropdownsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default class DropdownPage extends React.Component {
<Helmet title="Dropdowns" />
<h3>Dropdowns</h3>
<p>
The <code>Dropdown</code> component is used to pass the <code>isOpen</code> & <code>toggle</code> props via context to the following components: <code>DropdownToggle</code>, <code>DropdownMenu</code>. The <code>DropdownToggle</code> uses the <code>Button</code> component internally, meaning it also accepts all the props the <Link to="/components/buttons/">Button component</Link> accepts.
The <code>Dropdown</code> component is used to pass the <code>isOpen</code> &amp; <code>toggle</code> props via context to the following components: <code>DropdownToggle</code>, <code>DropdownMenu</code>. The <code>DropdownToggle</code> uses the <code>Button</code> component internally, meaning it also accepts all the props the <Link to="/components/buttons/">Button component</Link> accepts.
</p>
<div className="docs-example">
<DropdownExample />
Expand All @@ -59,6 +59,8 @@ export default class DropdownPage extends React.Component {
isOpen: PropTypes.bool,
// For Dropdown usage inside a Nav
nav: PropTypes.bool,
// For Dropdown usage inside a Navbar (disables popper)
inNavbar: PropTypes.bool,
tag: PropTypes.string, // default: 'div' unless nav=true, then 'li'
toggle: PropTypes.func
};
Expand Down
30 changes: 29 additions & 1 deletion docs/lib/examples/Navbar.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import React from 'react';
import { Collapse, Navbar, NavbarToggler, NavbarBrand, Nav, NavItem, NavLink } from 'reactstrap';
import {
Collapse,
Navbar,
NavbarToggler,
NavbarBrand,
Nav,
NavItem,
NavLink,
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem } from 'reactstrap';

export default class Example extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -29,6 +40,23 @@ export default class Example extends React.Component {
<NavItem>
<NavLink href="https://github.com/reactstrap/reactstrap">Github</NavLink>
</NavItem>
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
Options
</DropdownToggle>
<DropdownMenu >
<DropdownItem>
Option 1
</DropdownItem>
<DropdownItem>
Option 2
</DropdownItem>
<DropdownItem divider />
<DropdownItem>
Reset
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</Collapse>
</Navbar>
Expand Down
6 changes: 5 additions & 1 deletion src/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@ const propTypes = {
children: PropTypes.node,
className: PropTypes.string,
cssModule: PropTypes.object,
inNavbar: PropTypes.bool,
};

const defaultProps = {
isOpen: false,
dropup: false,
nav: false,
inNavbar: false,
};

const childContextTypes = {
toggle: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired,
dropup: PropTypes.bool.isRequired,
inNavbar: PropTypes.bool.isRequired,
};

class Dropdown extends React.Component {
Expand All @@ -50,6 +53,7 @@ class Dropdown extends React.Component {
toggle: this.props.toggle,
isOpen: this.props.isOpen,
dropup: this.props.dropup,
inNavbar: this.props.inNavbar,
};
}

Expand Down Expand Up @@ -173,7 +177,7 @@ class Dropdown extends React.Component {
size,
nav,
...attrs
} = omit(this.props, ['toggle', 'disabled']);
} = omit(this.props, ['toggle', 'disabled', 'inNavbar']);

attrs.tag = attrs.tag || (nav ? 'li' : 'div');

Expand Down
3 changes: 2 additions & 1 deletion src/DropdownMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const defaultProps = {
const contextTypes = {
isOpen: PropTypes.bool.isRequired,
dropup: PropTypes.bool.isRequired,
inNavbar: PropTypes.bool.isRequired,
};

const noFlipModifier = { flip: { enabled: false } };
Expand All @@ -38,7 +39,7 @@ const DropdownMenu = (props, context) => {

let Tag = tag;

if (context.isOpen) {
if (context.isOpen && !context.inNavbar) {
Tag = Popper;
const position1 = context.dropup ? 'top' : 'bottom';
const position2 = right ? 'end' : 'start';
Expand Down
13 changes: 13 additions & 0 deletions src/DropdownToggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const defaultProps = {
const contextTypes = {
isOpen: PropTypes.bool.isRequired,
toggle: PropTypes.func.isRequired,
inNavbar: PropTypes.bool.isRequired,
};

class DropdownToggle extends React.Component {
Expand Down Expand Up @@ -79,6 +80,18 @@ class DropdownToggle extends React.Component {
Tag = tag;
}

if (this.context.inNavbar) {
return (
<Tag
{...props}
className={classes}
onClick={this.onClick}
aria-expanded={this.context.isOpen}
children={children}
/>
);
}

return (
<Target
{...props}
Expand Down
34 changes: 33 additions & 1 deletion src/__tests__/Dropdown.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { mount } from 'enzyme';
import { Popper, Target } from 'react-popper';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from '../';
import { keyCodes } from '../utils';


describe('Dropdown', () => {
let isOpen;
let toggle;
Expand Down Expand Up @@ -773,4 +773,36 @@ describe('Dropdown', () => {
expect(wrapper.find('.nav-item').hostNodes().children().length).toBe(2);
});
});

describe('Dropdown in navbar', () => {
it('should open without popper with inNavbar prop', () => {
isOpen = true;
const wrapper = mount(
<Dropdown nav inNavbar isOpen={isOpen} toggle={toggle}>
<DropdownToggle caret nav>Toggle</DropdownToggle>
<DropdownMenu>
<DropdownItem>Test</DropdownItem>
</DropdownMenu>
</Dropdown>
);

expect(wrapper.find('.dropdown-toggle').first().type()).toEqual('a');
expect(wrapper.find('.dropdown-menu').first().type()).toEqual('div');
});

it('should open with popper without inNavbar prop', () => {
isOpen = true;
const wrapper = mount(
<Dropdown nav isOpen={isOpen} toggle={toggle}>
<DropdownToggle caret nav>Toggle</DropdownToggle>
<DropdownMenu>
<DropdownItem>Test</DropdownItem>
</DropdownMenu>
</Dropdown>
);

expect(wrapper.find('.dropdown-toggle').first().type()).toEqual(Target);
expect(wrapper.find('.dropdown-menu').first().type()).toEqual(Popper);
});
});
});
26 changes: 14 additions & 12 deletions src/__tests__/DropdownMenu.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { DropdownMenu } from '../';
describe('DropdownMenu', () => {
let isOpen;
let dropup;
let inNavbar;
let popperManager;

beforeEach(() => {
isOpen = false;
dropup = false;
inNavbar = false;
popperManager = {
getTargetNode: () => ({}),
};
Expand All @@ -23,7 +25,7 @@ describe('DropdownMenu', () => {
<p>Content</p>
</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -39,7 +41,7 @@ describe('DropdownMenu', () => {
<p>Content</p>
</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -55,7 +57,7 @@ describe('DropdownMenu', () => {
<p>Content</p>
</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -69,7 +71,7 @@ describe('DropdownMenu', () => {
const wrapper = mount(
<DropdownMenu>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -82,7 +84,7 @@ describe('DropdownMenu', () => {
const wrapper = mount(
<DropdownMenu right>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -95,7 +97,7 @@ describe('DropdownMenu', () => {
const wrapper = shallow(
<DropdownMenu>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -109,7 +111,7 @@ describe('DropdownMenu', () => {
const wrapper = shallow(
<DropdownMenu>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -122,7 +124,7 @@ describe('DropdownMenu', () => {
const wrapper = shallow(
<DropdownMenu>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -135,7 +137,7 @@ describe('DropdownMenu', () => {
const wrapper = shallow(
<DropdownMenu>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -148,7 +150,7 @@ describe('DropdownMenu', () => {
const wrapper = shallow(
<DropdownMenu flip={false}>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -160,7 +162,7 @@ describe('DropdownMenu', () => {
const wrapper = mount(
<DropdownMenu right>Ello world</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
}
);
Expand All @@ -171,7 +173,7 @@ describe('DropdownMenu', () => {
it('should render custom tag', () => {
const wrapper = mount(<DropdownMenu tag="main">Yo!</DropdownMenu>,
{
context: { isOpen, dropup, popperManager },
context: { isOpen, dropup, inNavbar, popperManager },
childContextTypes: { popperManager }
});

Expand Down