Skip to content

Commit

Permalink
fix(DatePicker): fix calendar dropdown position (#4846)
Browse files Browse the repository at this point in the history
This change inroduces a Flatpickr plugin that ensures that the calendar
dropdown is put in the correct floating position even if the floating
menu container is changed via `appendTo` and the floating menu
container has significant offset from `<body>`.

Fixes #4818.
  • Loading branch information
asudoh committed Jan 10, 2020
1 parent 9b1ce9b commit 1e09d2c
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
7 changes: 6 additions & 1 deletion packages/react/src/components/DatePicker/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import flatpickr from 'flatpickr';
import l10n from 'flatpickr/dist/l10n/index';
import { settings } from 'carbon-components';
import DatePickerInput from '../DatePickerInput';
import carbonFlatpickrAppendToPlugin from './plugins/appendToPlugin';
import carbonFlatpickrFixEventsPlugin from './plugins/fixEventsPlugin';
import carbonFlatpickrRangePlugin from './plugins/rangePlugin';
import { match, keys } from '../../internal/keyboard';
Expand Down Expand Up @@ -340,7 +341,6 @@ export default class DatePicker extends Component {
this.cal = new flatpickr(this.inputField, {
disableMobile: true,
defaultDate: value,
appendTo,
mode: datePickerType,
allowInput: true,
dateFormat: dateFormat,
Expand All @@ -351,6 +351,11 @@ export default class DatePicker extends Component {
datePickerType === 'range'
? new carbonFlatpickrRangePlugin({ input: this.toInputField })
: () => {},
appendTo
? carbonFlatpickrAppendToPlugin({
appendTo,
})
: () => {},
carbonFlatpickrMonthSelectPlugin({
selectorFlatpickrMonthYearContainer: '.flatpickr-current-month',
selectorFlatpickrYearContainer: '.numInputWrapper',
Expand Down
64 changes: 64 additions & 0 deletions packages/react/src/components/DatePicker/plugins/appendToPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @license
*
* Copyright IBM Corp. 2019
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @param {object} config Plugin configuration.
* @returns {Plugin} A Flatpickr plugin to put adjust the position of calendar dropdown.
*/
export default config => fp => {
/**
* Adjusts the floating meun position after Flatpicker sets it.
*/
const handlePreCalendarPosition = () => {
Promise.resolve().then(() => {
const {
calendarContainer,
config: fpConfig,
_positionElement: positionElement,
} = fp;
const { appendTo } = fpConfig;
const {
left: containerLeft,
top: containerTop,
} = appendTo.getBoundingClientRect();
const {
left: refLeft,
bottom: refBottom,
} = positionElement.getBoundingClientRect();
if (
(appendTo !== appendTo.ownerDocument.body ||
containerLeft !== 0 ||
containerTop !== 0) &&
appendTo.ownerDocument.defaultView
.getComputedStyle(appendTo)
.getPropertyValue('position') === 'static'
) {
throw new Error(
'Floating menu container must not have `position:static`.'
);
}
// `2` for negative mergin on calendar dropdown
calendarContainer.style.top = `${refBottom - containerTop + 2}px`;
calendarContainer.style.left = `${refLeft - containerLeft}px`;
});
};

/**
* Registers this Flatpickr plugin.
*/
const register = () => {
fp.loadedPlugins.push('carbonFlatpickrAppendToPlugin');
};

return {
appendTo: config.appendTo,
onReady: register,
onPreCalendarPosition: handlePreCalendarPosition,
};
};

0 comments on commit 1e09d2c

Please sign in to comment.