Skip to content

Commit fd3f09c

Browse files
authored
Fix backspace to shift focus to previous element in useDateSegment (#5715)
* Fix focus shift on clearing minute fields
1 parent bf7071f commit fd3f09c

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

packages/@react-aria/datepicker/src/useDateSegment.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,13 @@ export function useDateSegment(segment: DateSegment, state: DateFieldState, ref:
9393
let parser = useMemo(() => new NumberParser(locale, {maximumFractionDigits: 0}), [locale]);
9494

9595
let backspace = () => {
96+
if (segment.text === segment.placeholder) {
97+
focusManager.focusPrevious();
98+
}
9699
if (parser.isValidPartialNumber(segment.text) && !state.isReadOnly && !segment.isPlaceholder) {
97100
let newValue = segment.text.slice(0, -1);
98101
let parsed = parser.parse(newValue);
102+
newValue = parsed === 0 ? '' : newValue;
99103
if (newValue.length === 0 || parsed === 0) {
100104
state.clearSegment(segment.type);
101105
} else {

packages/react-aria-components/stories/DateField.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import clsx from 'clsx';
1414
import {DateField, DateInput, DateSegment, Label} from 'react-aria-components';
15+
import {parseAbsoluteToLocal} from '@internationalized/date';
1516
import React from 'react';
1617
import styles from '../example/index.css';
1718

@@ -20,7 +21,7 @@ export default {
2021
};
2122

2223
export const DateFieldExample = () => (
23-
<DateField data-testid="date-field-example">
24+
<DateField data-testid="date-field-example" defaultValue={parseAbsoluteToLocal('2024-01-01T01:01:00Z')}>
2425
<Label style={{display: 'block'}}>Date</Label>
2526
<DateInput className={styles.field} data-testid2="date-input">
2627
{segment => <DateSegment segment={segment} className={clsx(styles.segment, {[styles.placeholder]: segment.isPlaceholder})} />}

packages/react-aria-components/test/DateField.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,35 @@ describe('DateField', () => {
258258
expect(getDescription()).not.toContain('Constraints not satisfied');
259259
expect(group).not.toHaveAttribute('data-invalid');
260260
});
261+
262+
it('should focus previous segment when backspacing on an empty date segment', async () => {
263+
let {getAllByRole} = render(
264+
<DateField defaultValue={new CalendarDate(2024, 12, 31)}>
265+
<Label>Birth date</Label>
266+
<DateInput>
267+
{segment => <DateSegment segment={segment} />}
268+
</DateInput>
269+
</DateField>
270+
);
271+
272+
let segments = getAllByRole('spinbutton');
273+
await user.click(segments[2]);
274+
expect(document.activeElement).toBe(segments[2]);
275+
276+
// Press backspace to delete '2024'
277+
for (let i = 0; i < 4; i++) {
278+
await user.keyboard('{backspace}');
279+
}
280+
expect(document.activeElement).toBe(segments[2]);
281+
await user.keyboard('{backspace}');
282+
expect(document.activeElement).toBe(segments[1]);
283+
284+
// Press backspace to delete '31'
285+
for (let i = 0; i < 2; i++) {
286+
await user.keyboard('{backspace}');
287+
}
288+
expect(document.activeElement).toBe(segments[1]);
289+
await user.keyboard('{backspace}');
290+
expect(document.activeElement).toBe(segments[0]);
291+
});
261292
});

0 commit comments

Comments
 (0)