diff --git a/.changeset/fuzzy-years-focus.md b/.changeset/fuzzy-years-focus.md new file mode 100644 index 000000000..e13834085 --- /dev/null +++ b/.changeset/fuzzy-years-focus.md @@ -0,0 +1,5 @@ +--- +"bits-ui": patch +--- + +fix(DateField): keep focus on the year while correcting its first digit diff --git a/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts b/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts index 1da2a23ea..1f7e7159a 100644 --- a/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts +++ b/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts @@ -211,6 +211,7 @@ export class DateFieldRootState { descriptionNode = $state(null); validationNode = $state(null); states = initSegmentStates(); + #segmentClearedValue = false; dayPeriodNode = $state(null); rangeRoot: DateRangeFieldRootState | undefined = undefined; name = $state(""); @@ -311,6 +312,10 @@ export class DateFieldRootState { $effect(() => { if (this.value.current === undefined) { + if (this.#segmentClearedValue) { + this.#segmentClearedValue = false; + return; + } this.segmentValues = initializeSegmentValues(this.inferredGranularity); } }); @@ -680,6 +685,7 @@ export class DateFieldRootState { }) ); } else { + this.#segmentClearedValue = true; this.setValue(undefined); this.segmentValues = newSegmentValues; } @@ -1220,7 +1226,7 @@ class DateFieldYearSegmentState extends BaseNumericSegmentState { if (prev === null) { this.announcer.announce(num); - return `000${num}`; + return `${num}`; } const str = prev.toString() + num.toString(); @@ -1234,6 +1240,9 @@ class DateFieldYearSegmentState extends BaseNumericSegmentState { str.length <= 4 ) { this.announcer.announce(mergedInt); + if (str.length === 4) { + moveToNext = true; + } return str; } @@ -1253,7 +1262,7 @@ class DateFieldYearSegmentState extends BaseNumericSegmentState { return mergedIntStr; }); - if (this.#pressedKeys.length === 4 || this.#pressedKeys.length === this.#backspaceCount) { + if (this.#pressedKeys.length === 4) { moveToNext = true; } @@ -1280,9 +1289,8 @@ class DateFieldYearSegmentState extends BaseNumericSegmentState { return null; } const next = str.slice(0, -1); - this.announcer.announce(next); - - return `${next}`; + this.announcer.announce(Number.parseInt(next)); + return next; }); if (moveToPrev) { diff --git a/tests/src/tests/date-field/date-field.browser.test.ts b/tests/src/tests/date-field/date-field.browser.test.ts index 616d5de16..f35d1f4f7 100644 --- a/tests/src/tests/date-field/date-field.browser.test.ts +++ b/tests/src/tests/date-field/date-field.browser.test.ts @@ -650,6 +650,20 @@ describe("date field", () => { await expect.element(hour).toHaveFocus(); }); + it("should keep focus on the year after correcting its first digit", async () => { + const t = setup({ granularity: "hour" }); + const { getHour } = getTimeSegments(page.getByTestId); + + await t.year.click(); + await userEvent.keyboard("1"); + await userEvent.keyboard(kbd.BACKSPACE); + await userEvent.keyboard("2"); + + await expect.element(t.year).toHaveTextContent("2"); + await expect.element(t.year).toHaveFocus(); + await expect.element(getHour()).not.toHaveFocus(); + }); + it("should allow going from 12PM -> 12AM without changing the display hour to 0", async () => { setup({ value: new CalendarDateTime(2023, 10, 12, 12, 30, 0, 0), @@ -1103,6 +1117,14 @@ describe("date field", () => { await userEvent.keyboard(kbd.ARROW_DOWN); await expect.element(hour).toHaveTextContent("19"); }); + + it("should not affect day/month segments when backspacing the year", async () => { + const t = setup({ value: new CalendarDate(2023, 10, 12) }); + await t.year.click(); + await userEvent.keyboard(kbd.BACKSPACE); + await expect.element(t.day).toHaveTextContent("12"); + await expect.element(t.month).toHaveTextContent("10"); + }); }); /**