Skip to content

Commit

Permalink
feat(v5): Update dropdown (#5471)
Browse files Browse the repository at this point in the history
* feat(v5): Update dropdown

- Set default element of DropdownDivider to hr
- Add variant prop for DropdownMenu
- Add menuVariant prop for DropdownButton and NavDropdown

* Add active state to dark dropdown example to showcase highlight
  • Loading branch information
kyletsang committed Oct 26, 2020
1 parent 1ee2d7e commit f728394
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const DropdownHeader = createWithBsPrefix('dropdown-header', {
defaultProps: { role: 'heading' },
});
const DropdownDivider = createWithBsPrefix('dropdown-divider', {
Component: 'hr',
defaultProps: { role: 'separator' },
});
const DropdownItemText = createWithBsPrefix('dropdown-item-text', {
Expand Down
16 changes: 15 additions & 1 deletion src/DropdownButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import PropTypes from 'prop-types';

import Dropdown, { DropdownProps } from './Dropdown';
import DropdownToggle, { PropsFromToggle } from './DropdownToggle';
import DropdownMenu, { alignPropType, AlignType } from './DropdownMenu';
import DropdownMenu, {
alignPropType,
AlignType,
DropdownMenuVariant,
} from './DropdownMenu';

export interface DropdownButtonProps
extends DropdownProps,
Expand All @@ -15,6 +19,7 @@ export interface DropdownButtonProps
renderMenuOnMount?: boolean;
rootCloseEvent?: 'click' | 'mousedown';
bsPrefix?: string;
menuVariant?: DropdownMenuVariant;
}

const propTypes = {
Expand Down Expand Up @@ -59,6 +64,13 @@ const propTypes = {
*/
rootCloseEvent: PropTypes.string,

/**
* Menu color variant.
*
* Omitting this will use the default light color.
*/
menuVariant: PropTypes.oneOf<DropdownMenuVariant>(['dark']),

/** @ignore */
bsPrefix: PropTypes.string,
/** @ignore */
Expand Down Expand Up @@ -90,6 +102,7 @@ const DropdownButton = React.forwardRef<HTMLDivElement, DropdownButtonProps>(
disabled,
href,
id,
menuVariant,
...props
}: DropdownButtonProps,
ref,
Expand All @@ -110,6 +123,7 @@ const DropdownButton = React.forwardRef<HTMLDivElement, DropdownButtonProps>(
role={menuRole}
renderOnMount={renderMenuOnMount}
rootCloseEvent={rootCloseEvent}
variant={menuVariant}
>
{children}
</DropdownMenu>
Expand Down
12 changes: 12 additions & 0 deletions src/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export type ResponsiveAlignProp =

export type AlignType = AlignDirection | ResponsiveAlignProp;

export type DropdownMenuVariant = 'dark';

export interface DropdownMenuProps extends BsPrefixPropsWithChildren {
show?: boolean;
renderOnMount?: boolean;
Expand All @@ -37,6 +39,7 @@ export interface DropdownMenuProps extends BsPrefixPropsWithChildren {
onSelect?: SelectCallback;
rootCloseEvent?: 'click' | 'mousedown';
popperConfig?: UseDropdownMenuOptions['popperConfig'];
variant?: DropdownMenuVariant;
}

type DropdownMenu = BsPrefixRefForwardingComponent<'div', DropdownMenuProps>;
Expand Down Expand Up @@ -108,6 +111,13 @@ const propTypes = {
* A set of popper options and props passed directly to Popper.
*/
popperConfig: PropTypes.object,

/**
* Menu color variant.
*
* Omitting this will use the default light color.
*/
variant: PropTypes.oneOf<DropdownMenuVariant>(['dark']),
};

const defaultProps: Partial<DropdownMenuProps> = {
Expand Down Expand Up @@ -135,6 +145,7 @@ const DropdownMenu: DropdownMenu = React.forwardRef(
// Need to define the default "as" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595
as: Component = 'div',
popperConfig,
variant,
...props
}: DropdownMenuProps,
ref,
Expand Down Expand Up @@ -220,6 +231,7 @@ const DropdownMenu: DropdownMenu = React.forwardRef(
prefix,
show && 'show',
alignEnd && `${prefix}-right`,
variant && `${prefix}-${variant}`,
...alignClasses,
)}
/>
Expand Down
11 changes: 11 additions & 0 deletions src/NavDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';

import Dropdown, { DropdownProps } from './Dropdown';
import { DropdownMenuVariant } from './DropdownMenu';
import NavItem from './NavItem';
import NavLink from './NavLink';
import { BsPrefixRefForwardingComponent } from './helpers';
Expand All @@ -16,6 +17,7 @@ export interface NavDropdownProps
menuRole?: string;
renderMenuOnMount?: boolean;
rootCloseEvent?: 'click' | 'mousedown';
menuVariant?: DropdownMenuVariant;
}

type NavDropdown = BsPrefixRefForwardingComponent<'div', NavDropdownProps> & {
Expand Down Expand Up @@ -58,6 +60,13 @@ const propTypes = {
*/
rootCloseEvent: PropTypes.string,

/**
* Menu color variant.
*
* Omitting this will use the default light color.
*/
menuVariant: PropTypes.oneOf<DropdownMenuVariant>(['dark']),

/** @ignore */
bsPrefix: PropTypes.string,
};
Expand All @@ -74,6 +83,7 @@ const NavDropdown: NavDropdown = (React.forwardRef(
disabled,
active,
renderMenuOnMount,
menuVariant,
...props
}: NavDropdownProps,
ref,
Expand All @@ -94,6 +104,7 @@ const NavDropdown: NavDropdown = (React.forwardRef(
role={menuRole}
renderOnMount={renderMenuOnMount}
rootCloseEvent={rootCloseEvent}
variant={menuVariant}
>
{children}
</Dropdown.Menu>
Expand Down
13 changes: 13 additions & 0 deletions test/DropdownButtonSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ describe('<DropdownButton>', () => {
).find('button.dropdown-toggle.btn-success.btn-sm');
});

it('passes menuVariant to dropdown menu', () => {
const wrapper = mount(
<DropdownButton title="blah" menuVariant="dark" id="test">
<DropdownItem>Item 1</DropdownItem>
</DropdownButton>,
);

expect(wrapper.find('DropdownMenu').props()).to.have.property(
'variant',
'dark',
);
});

it('forwards onSelect handler to DropdownItems', (done) => {
const selectedEvents = [];

Expand Down
2 changes: 1 addition & 1 deletion test/DropdownItemSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Dropdown from '../src/Dropdown';
describe('<Dropdown.Item>', () => {
it('renders divider', () => {
mount(<Dropdown.Divider />).assertSingle(
'div.dropdown-divider[role="separator"]',
'hr.dropdown-divider[role="separator"]',
);
});

Expand Down
8 changes: 8 additions & 0 deletions test/DropdownMenuSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ describe('<Dropdown.Menu>', () => {
).assertSingle('.dropdown-menu-lg-right');
});

it('should render variant', () => {
mount(
<DropdownMenu show variant="dark">
<DropdownItem>Item</DropdownItem>
</DropdownMenu>,
).assertSingle('.dropdown-menu.dropdown-menu-dark');
});

// it.only('warns about bad refs', () => {
// class Parent extends React.Component {
// componentDidCatch() {}
Expand Down
13 changes: 13 additions & 0 deletions test/NavDropdownSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,17 @@ describe('<NavDropdown>', () => {

wrapper.assertSingle('a#test-id');
});

it('passes menuVariant to dropdown menu', () => {
const wrapper = mount(
<NavDropdown title="blah" menuVariant="dark" id="test">
<DropdownItem>Item 1</DropdownItem>
</NavDropdown>,
);

expect(wrapper.find('DropdownMenu').props()).to.have.property(
'variant',
'dark',
);
});
});
33 changes: 33 additions & 0 deletions www/src/examples/Dropdown/ButtonDark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<>
<Dropdown>
<Dropdown.Toggle id="dropdown-button-dark-example1" variant="secondary">
Dropdown Button
</Dropdown.Toggle>

<Dropdown.Menu variant="dark">
<Dropdown.Item href="#/action-1" active>
Action
</Dropdown.Item>
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item href="#/action-4">Separated link</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>

<DropdownButton
id="dropdown-button-dark-example2"
variant="secondary"
menuVariant="dark"
title="Dropdown button"
className="mt-2"
>
<Dropdown.Item href="#/action-1" active>
Action
</Dropdown.Item>
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item href="#/action-4">Separated link</Dropdown.Item>
</DropdownButton>
</>;
21 changes: 21 additions & 0 deletions www/src/examples/Dropdown/NavbarDark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Navbar variant="dark" bg="dark" expand="lg">
<Container fluid>
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="navbar-dark-example" />
<Navbar.Collapse id="navbar-dark-example">
<Nav>
<NavDropdown
id="nav-dropdown-dark-example"
title="Dropdown"
menuVariant="dark"
>
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>;
16 changes: 15 additions & 1 deletion www/src/pages/components/dropdowns.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import MenuHeaders from '../../examples/Dropdown/MenuHeaders';
import SplitBasic from '../../examples/Dropdown/SplitBasic';
import SplitVariants from '../../examples/Dropdown/SplitVariants';
import DropdownVariants from '../../examples/Dropdown/Variants';
import ButtonDark from '../../examples/Dropdown/ButtonDark';
import NavbarDark from '../../examples/Dropdown/NavbarDark';

import styles from '../../css/examples.module.scss';

Expand Down Expand Up @@ -87,12 +89,24 @@ convenience component.

<ReactPlayground codeText={SplitVariants} />

### Sizing
## Sizing

Dropdowns work with buttons of all sizes.

<ReactPlayground codeText={DropdownButtonSizes} />

## Dark dropdowns

Opt into darker dropdowns to match a dark navbar or custom style by adding
`variant="dark"` onto an existing `DropdownMenu`. Alternatively, use
`menuVariant="dark"` when using the `DropdownButton` component.

<ReactPlayground codeText={ButtonDark} />

Using `menuVariant="dark"` in a `NavDropdown`:

<ReactPlayground codeText={NavbarDark} />

## Drop directions

Trigger dropdown menus above, below, left, or to the right of their
Expand Down
3 changes: 3 additions & 0 deletions www/src/pages/migrating.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ Below is a _rough_ account of the breaking API changes as well as the minimal ch

- `ColOrder` is now maximum 5 instead of 12.

### Dropdown
- dropdown dividers use `hr` by default instead of `div`.

### Form

- removed `inline`.
Expand Down

0 comments on commit f728394

Please sign in to comment.