Skip to content

Commit bd18332

Browse files
authored
fix(date-inputs): header focus problem fix (#1160)
* fix(date-inputs): header focus problem fix * chore: throw away old approach * chore: simplify RTL * chore: add visual test * chore: force build on ci
1 parent 0e9ca9b commit bd18332

File tree

9 files changed

+54
-49
lines changed

9 files changed

+54
-49
lines changed

src/components/inputs/date-input/date-input-open.visualroute.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ export const routePath = '/date-input-open';
88

99
export const component = () => (
1010
<Suite>
11-
<Spec label="minimal">
11+
<Spec label="minimal" propsToList={['value', 'horizontalConstraint']}>
1212
<DateInput
1313
id="date-input"
14+
data-testid="date-input"
1415
value={value}
1516
onChange={() => {}}
1617
horizontalConstraint="m"

src/components/inputs/date-input/date-input.story.js

+10
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,24 @@ class DateInputStory extends React.Component {
1818
this.setState({ value: event.target.value });
1919
};
2020

21+
handleFocus = event => {
22+
action('onFocus')(event);
23+
};
24+
25+
handleBlur = event => {
26+
action('onBlur')(event);
27+
};
28+
2129
render() {
2230
const placeholder = text('placeholder', '');
2331
return (
2432
<Section>
2533
<div>
2634
<DateInput
2735
value={this.state.value}
36+
onBlur={this.handleBlur}
2837
onChange={this.handleChange}
38+
onFocus={this.handleFocus}
2939
horizontalConstraint={select(
3040
'horizontalConstraint',
3141
['m', 'l', 'xl', 'scale'],

src/components/inputs/date-input/date-input.visualspec.js

+19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { percySnapshot } from '@percy/puppeteer';
2+
import { getDocument, queries, wait } from 'pptr-testing-library';
3+
4+
const { getByLabelText, getByTestId, getByText } = queries;
25

36
describe('DateInput', () => {
47
it('Default', async () => {
@@ -11,5 +14,21 @@ describe('DateInput', () => {
1114
await page.click('#date-input');
1215
await expect(page).toMatch('November');
1316
await percySnapshot(page, 'DateInput - open');
17+
18+
const doc = await getDocument(page);
19+
const input = await getByTestId(doc, 'date-input');
20+
21+
const prevMonthButton = await getByLabelText(doc, 'show prev month');
22+
await prevMonthButton.click();
23+
24+
await wait(() => getByText(doc, 'October'));
25+
// our input should still be focused even though we clicked a header button
26+
27+
await input.press('Backspace');
28+
await input.press('Backspace');
29+
await input.press('Backspace');
30+
await input.press('Backspace');
31+
await input.type('2017');
32+
await wait(() => getByText(doc, '2017'));
1433
});
1534
});

src/components/inputs/date-time-input/date-time-input.story.js

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ class DateTimeInputStory extends React.Component {
1818
this.setState({ value: event.target.value });
1919
};
2020

21+
onBlur = event => {
22+
action('onBlur')(event);
23+
};
24+
onFocus = event => action('onFocus')(event);
25+
2126
render() {
2227
const placeholder = text('placeholder', '');
2328
return (
@@ -47,6 +52,8 @@ class DateTimeInputStory extends React.Component {
4752
isDisabled={boolean('isDisabled', false)}
4853
hasError={boolean('hasError', false)}
4954
hasWarning={boolean('hasWarning', false)}
55+
onBlur={this.onBlur}
56+
onFocus={this.onFocus}
5057
/>
5158
</Section>
5259
);

src/components/inputs/localized-rich-text-input/rich-text-input.js

-11
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,6 @@ class RichTextInput extends React.PureComponent {
6363
// for calling our passed onBlur handler
6464
// https://github.com/ianstormtaylor/slate/issues/2434
6565
onBlur = (event, editor, next) => {
66-
// we don't call next() if it's a button to stop our input from losing
67-
// slate focus
68-
if (
69-
event.relatedTarget &&
70-
event.relatedTarget.getAttribute('data-button-type') ===
71-
'rich-text-button'
72-
) {
73-
event.preventDefault();
74-
return;
75-
}
76-
7766
next();
7867

7968
if (this.props.onBlur) {

src/components/inputs/rich-text-input/rich-text-input.js

-22
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,6 @@ class RichTextInput extends React.PureComponent {
6969
// for calling our passed onBlur handler
7070
// https://github.com/ianstormtaylor/slate/issues/2434
7171
onBlur = (event, editor, next) => {
72-
// we don't call next() if it's a button to stop our input from losing
73-
// slate focus
74-
75-
if (
76-
event.relatedTarget &&
77-
event.relatedTarget.getAttribute('data-button-type') ===
78-
'rich-text-button'
79-
) {
80-
event.preventDefault();
81-
return;
82-
}
83-
8472
next();
8573

8674
if (this.props.onBlur) {
@@ -95,16 +83,6 @@ class RichTextInput extends React.PureComponent {
9583
};
9684

9785
onFocus = (event, editor, next) => {
98-
// we don't call next() if it's from the toolbar
99-
if (
100-
event.relatedTarget &&
101-
event.relatedTarget.getAttribute('data-button-type') ===
102-
'rich-text-button'
103-
) {
104-
event.preventDefault();
105-
return;
106-
}
107-
10886
next();
10987
if (this.props.onFocus) {
11088
const fakeEvent = {

src/components/internals/calendar-header/calendar-header.js

+8
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,16 @@ const WrapperComponent = styled.div`
1717

1818
const CalendarHeader = props => {
1919
const intl = useIntl();
20+
// https://codepen.io/mudassir0909/pen/eIHqB
21+
22+
// we prevent all our defined onClicks inside of the CalendarHeader
23+
// from blurring our input.
24+
const onMouseDown = React.useCallback(event => {
25+
event.preventDefault();
26+
}, []);
2027
return (
2128
<div
29+
onMouseDown={onMouseDown}
2230
css={css`
2331
display: flex;
2432
padding: 10px 2% 6px;

src/components/internals/rich-text-body/rich-text-body-button.js

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ const RichTextBodyButton = props => {
1919
{...restOfProps}
2020
type="button"
2121
tabIndex={-1}
22-
data-button-type="rich-text-button"
2322
aria-disabled={props.isDisabled}
2423
disabled={props.isDisabled}
2524
aria-label={props.label}

src/components/internals/rich-text-body/rich-text-body.js

+8-14
Original file line numberDiff line numberDiff line change
@@ -252,19 +252,13 @@ const RichTextEditorBody = React.forwardRef((props, ref) => {
252252
);
253253
}
254254

255-
const { focus } = props.editor;
256-
257-
const onToolbarClick = React.useCallback(() => {
258-
// if clicking on a dropdown, we need to both focus the RichTextInput
259-
// and open the dropdown.
260-
// if we don't use setTimeout, our dropdown opening will be hijacked by the
261-
// editors rerendering. (a so called `race condition`)
262-
// the reason we keep this here, is because any onClick from our dropdown or our mark buttons
263-
// will propogate to here.
264-
if (!props.editor.value.selection.isFocused) {
265-
setTimeout(focus, 0);
266-
}
267-
}, [props.editor.value.selection.isFocused, focus]);
255+
// https://codepen.io/mudassir0909/pen/eIHqB
256+
257+
// we prevent all our defined onClicks inside of the CalendarHeader
258+
// from blurring our input.
259+
const onToolbarMouseDown = React.useCallback(event => {
260+
event.preventDefault();
261+
}, []);
268262

269263
return (
270264
<Container
@@ -274,7 +268,7 @@ const RichTextEditorBody = React.forwardRef((props, ref) => {
274268
isReadOnly={props.isReadOnly}
275269
isDisabled={props.isDisabled}
276270
>
277-
<Toolbar onClick={onToolbarClick}>
271+
<Toolbar onMouseDown={onToolbarMouseDown}>
278272
<ToolbarMainControls>
279273
<Dropdown
280274
label={intl.formatMessage(messages.styleDropdownLabel)}

0 commit comments

Comments
 (0)