From 1920de43982facd1d39db549bdd441ed3d6b1f9d Mon Sep 17 00:00:00 2001 From: Michael Worobec Date: Thu, 5 Sep 2019 15:07:22 +1000 Subject: [PATCH] allow for centered dropdown menus --- src/Dropdown.js | 19 +++++-------------- src/DropdownContext.js | 2 +- src/DropdownMenu.js | 18 +++++++++--------- test/DropdownSpec.js | 11 ++++++++--- www/src/examples/Dropdown.js | 7 ++++--- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/Dropdown.js b/src/Dropdown.js index 856fcc93..bdf26aa0 100644 --- a/src/Dropdown.js +++ b/src/Dropdown.js @@ -49,9 +49,9 @@ const propTypes = { itemSelector: PropTypes.string.isRequired, /** - * Align the menu to the 'end' side of the placement side of the Dropdown toggle. The default placement is `top-start` or `bottom-start`. + * Align the menu to the 'center' or 'end' side of the placement side of the Dropdown toggle. The default placement is `top-start` or `bottom-start`. */ - alignEnd: PropTypes.bool, + align: PropTypes.string, /** * Whether or not the Dropdown is visible. @@ -97,7 +97,7 @@ const defaultProps = { */ function Dropdown({ drop, - alignEnd, + align, defaultShow, show: rawShow, onToggle: rawOnToggle, @@ -144,22 +144,13 @@ function Dropdown({ toggle, drop, show, - alignEnd, + align, menuElement, toggleElement, setMenu, setToggle, }), - [ - toggle, - drop, - show, - alignEnd, - menuElement, - toggleElement, - setMenu, - setToggle, - ], + [toggle, drop, show, align, menuElement, toggleElement, setMenu, setToggle], ); if (menuElement && lastShow && !show) { diff --git a/src/DropdownContext.js b/src/DropdownContext.js index 37a3ebe0..a215549f 100644 --- a/src/DropdownContext.js +++ b/src/DropdownContext.js @@ -5,7 +5,7 @@ const DropdownContext = React.createContext({ toggleRef() {}, onToggle() {}, toggleNode: undefined, - alignEnd: null, + align: null, show: null, drop: null, }); diff --git a/src/DropdownMenu.js b/src/DropdownMenu.js index fd8b1ac7..11cec7d5 100644 --- a/src/DropdownMenu.js +++ b/src/DropdownMenu.js @@ -20,8 +20,7 @@ export function useDropdownMenu(options = {}) { } = options; const show = context.show == null ? options.show : context.show; - const alignEnd = - context.alignEnd == null ? options.alignEnd : context.alignEnd; + const align = context.align == null ? options.align : context.align; if (show && !hasShownRef.current) { hasShownRef.current = true; @@ -34,10 +33,11 @@ export function useDropdownMenu(options = {}) { const { drop, setMenu, menuElement, toggleElement } = context; - let placement = alignEnd ? 'bottom-end' : 'bottom-start'; - if (drop === 'up') placement = alignEnd ? 'top-end' : 'top-start'; - else if (drop === 'right') placement = alignEnd ? 'right-end' : 'right-start'; - else if (drop === 'left') placement = alignEnd ? 'left-end' : 'left-start'; + let placement = 'bottom'; + if (drop === 'up') placement = 'top'; + else if (drop === 'right' || drop === 'left') placement = drop; + if (align === 'right') placement += `-end`; + else placement += `-${align || 'start'}`; const popper = usePopper(toggleElement, menuElement, { placement, @@ -62,7 +62,7 @@ export function useDropdownMenu(options = {}) { }; const childArgs = { show, - alignEnd, + align, hasShown: hasShownRef.current, close: handleClose, }; @@ -99,7 +99,7 @@ const propTypes = { * * @type {Function ({ * show: boolean, - * alignEnd: boolean, + * align: string, * close: (?SyntheticEvent) => void, * placement: Placement, * outOfBoundaries: ?boolean, @@ -129,7 +129,7 @@ const propTypes = { * Generally this is provided by the parent `Dropdown` component, * but may also be specified as a prop directly. */ - alignEnd: PropTypes.bool, + align: PropTypes.string, /** * Enables the Popper.js `flip` modifier, allowing the Dropdown to diff --git a/test/DropdownSpec.js b/test/DropdownSpec.js index b9bc5105..198bc838 100644 --- a/test/DropdownSpec.js +++ b/test/DropdownSpec.js @@ -74,13 +74,18 @@ describe('', () => { buttonNode.getAttribute('id').should.be.ok; }); - it('forwards alignEnd to menu', () => { + it('forwards align to menu', () => { const renderSpy = sinon.spy(args => { - args.alignEnd.should.equal(true); + args.align.should.equal('center'); }); mount( - , + , ); renderSpy.should.have.been.called; diff --git a/www/src/examples/Dropdown.js b/www/src/examples/Dropdown.js index 04f2bee0..9d9d51fc 100644 --- a/www/src/examples/Dropdown.js +++ b/www/src/examples/Dropdown.js @@ -38,12 +38,12 @@ const Toggle = ({ id, children }) => { ); }; -const DropdownButton = ({ show, onToggle, drop, alignEnd, title, role }) => ( +const DropdownButton = ({ show, onToggle, drop, align, title, role }) => ( {({ props }) => ( @@ -70,7 +70,8 @@ class DropdownExample extends React.Component { onToggle={nextShow => this.setState({ show: nextShow })} title={`${show ? 'Close' : 'Open'} Dropdown`} /> - + +