From a0ff4dc811f18e89063bf7ae163b83425101e2b7 Mon Sep 17 00:00:00 2001
From: mark-tate <143323+mark-tate@users.noreply.github.com>
Date: Fri, 13 Dec 2024 10:55:30 +0000
Subject: [PATCH 1/4] enabled uncontrolled/un-controlled open behaviour for
`DatePicker`
- added `openOnClick`, `openOnKeyDown` and `openOnFocus` props to `DatePicker`.
- revise the controlled behaviour of the `open` prop on `DatePickerOverlay`.
- add examples for controlled and uncontrolled behaviour.
---
.changeset/serious-kings-decide.md | 9 +
.../date-picker/DatePicker.single.cy.tsx | 101 ++++++++++-
packages/lab/src/date-picker/DatePicker.tsx | 22 ++-
.../lab/src/date-picker/DatePickerOverlay.tsx | 1 +
.../date-picker/DatePickerOverlayProvider.tsx | 87 +++++++---
.../src/date-picker/DatePickerRangeInput.tsx | 30 +---
.../src/date-picker/DatePickerSingleInput.tsx | 13 --
packages/lab/src/date-picker/useKeyboard.ts | 36 ++++
.../date-picker/date-picker.stories.tsx | 162 +++++++++++++++++-
site/docs/components/date-picker/examples.mdx | 16 ++
.../examples/date-picker/ControlledOpen.tsx | 126 ++++++++++++++
.../examples/date-picker/UncontrolledOpen.tsx | 61 +++++++
site/src/examples/date-picker/index.ts | 2 +
13 files changed, 592 insertions(+), 74 deletions(-)
create mode 100644 .changeset/serious-kings-decide.md
create mode 100644 packages/lab/src/date-picker/useKeyboard.ts
create mode 100644 site/src/examples/date-picker/ControlledOpen.tsx
create mode 100644 site/src/examples/date-picker/UncontrolledOpen.tsx
diff --git a/.changeset/serious-kings-decide.md b/.changeset/serious-kings-decide.md
new file mode 100644
index 00000000000..3bddf2257c5
--- /dev/null
+++ b/.changeset/serious-kings-decide.md
@@ -0,0 +1,9 @@
+---
+"@salt-ds/lab": minor
+---
+
+enabled uncontrolled/un-controlled open behaviour for `DatePicker`
+
+- added `openOnClick`, `openOnKeyDown` and `openOnFocus` props to `DatePicker`.
+- revise the controlled behaviour of the `open` prop on `DatePickerOverlay`.
+- add examples for controlled and uncontrolled behaviour.
diff --git a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
index 7759c061a3a..a1e771ad296 100644
--- a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
+++ b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
@@ -26,6 +26,7 @@ const adapters = [adapterDateFns, adapterDayjs, adapterLuxon, adapterMoment];
const {
// Storybook wraps components in it's own LocalizationProvider, so do not compose Stories
+ ControlledOpen,
Single,
SingleControlled,
SingleWithConfirmation,
@@ -35,7 +36,8 @@ const {
SingleWithMinMaxDate,
SingleWithTodayButton,
SingleCustomFormat,
-} = datePickerStories as any; // not using composeStories yet, will break certain test below
+ UncontrolledOpen,
+} = datePickerStories as any;
describe("GIVEN a DatePicker where selectionVariant is single", () => {
describe("WHEN default state", () => {
@@ -388,11 +390,6 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
cy.findByRole("button", { name: "Apply" }).realClick();
// Verify that the calendar is closed and the new date is applied
cy.findByRole("application").should("not.exist");
- // cy.get("@appliedDateSpy").should(
- // "have.been.calledWith",
- // Cypress.sinon.match.any,
- // updatedDate,
- // );
cy.get("@appliedDateSpy").should((spy: any) => {
const [_event, date] = spy.lastCall.args;
expect(adapter.isValid(date)).to.be.true;
@@ -483,6 +480,74 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
updatedFormattedDateValue,
);
});
+
+ it("SHOULD be able to enable the overlay to open on click", () => {
+ cy.mount(
+ ,
+ );
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on click
+ cy.document().find("input").realClick();
+ cy.findByRole("application").should("exist");
+ // Simulate selecting a new date
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).should("exist");
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.document()
+ .find("input")
+ .should("have.value", updatedFormattedDateValue);
+ });
+
+ it("SHOULD be able to enable the overlay to open on keydown", () => {
+ cy.mount(
+ ,
+ );
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on arrow down
+ cy.document().find("input").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.realPress("ArrowDown");
+ cy.findByRole("application").should("exist");
+ // Simulate selecting a new date
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).should("exist");
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.document()
+ .find("input")
+ .should("have.value", updatedFormattedDateValue);
+ });
+
+ it("SHOULD be able to enable the overlay to open on focus", () => {
+ cy.mount(
+ ,
+ );
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on focus
+ cy.document().find("input").focus();
+ cy.findByRole("application").should("exist");
+ // Simulate selecting a new date
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).should("exist");
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.document()
+ .find("input")
+ .should("have.value", updatedFormattedDateValue);
+ });
});
describe("controlled component", () => {
@@ -567,6 +632,30 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
});
});
+ it("SHOULD be able to control the overlay open state", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar
+ cy.document().find("input").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.findByRole("button", { name: "Open Calendar" }).realClick();
+ cy.findByRole("application").should("exist");
+ // Simulate selecting a new date
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).should("exist");
+ cy.findByRole("button", {
+ name: adapter.format(updatedDate, "DD MMMM YYYY"),
+ }).realClick();
+ cy.findByRole("application").should("exist");
+ cy.findByRole("button", { name: "Apply" }).realClick();
+ // Verify that the calendar is closed and the new date is applied
+ cy.findByRole("application").should("not.exist");
+ cy.document()
+ .find("input")
+ .should("have.value", updatedFormattedDateValue);
+ });
+
it("SHOULD support format prop on the input", () => {
const format = "YYYY-MM-DD";
diff --git a/packages/lab/src/date-picker/DatePicker.tsx b/packages/lab/src/date-picker/DatePicker.tsx
index e9a162dd46f..dcf524995e7 100644
--- a/packages/lab/src/date-picker/DatePicker.tsx
+++ b/packages/lab/src/date-picker/DatePicker.tsx
@@ -21,6 +21,12 @@ export interface DatePickerBaseProps {
children?: ReactNode;
/** the open/close state of the overlay. The open/close state will be controlled when this prop is provided. */
open?: boolean;
+ /** When `open` is uncontrolled, set this to `true` to open on focus */
+ openOnFocus?: boolean;
+ /** When `open` is uncontrolled, set this to `true` to open on click */
+ openOnClick?: boolean;
+ /** When `open` is uncontrolled, set this to `true` to open on arrow key down */
+ openOnKeyDown?: boolean;
/**
* Handler for when open state changes
* @param newOpen - true when opened
@@ -124,12 +130,24 @@ export const DatePickerMain = forwardRef>(
export const DatePicker = forwardRef(function DatePicker<
TDate extends DateFrameworkType,
>(props: DatePickerProps, ref: React.Ref) {
- const { open, defaultOpen, onOpen, readOnly, ...rest } = props;
+ const {
+ defaultOpen,
+ open,
+ openOnClick,
+ openOnFocus,
+ openOnKeyDown,
+ onOpen,
+ readOnly,
+ ...rest
+ } = props;
return (
diff --git a/packages/lab/src/date-picker/DatePickerOverlay.tsx b/packages/lab/src/date-picker/DatePickerOverlay.tsx
index e4327331dd9..548ab541ce0 100644
--- a/packages/lab/src/date-picker/DatePickerOverlay.tsx
+++ b/packages/lab/src/date-picker/DatePickerOverlay.tsx
@@ -63,6 +63,7 @@ export const DatePickerOverlay = forwardRef<
focusManagerProps={
floatingUIResult?.context
? {
+ returnFocus: false,
context: floatingUIResult.context,
initialFocus: 4,
}
diff --git a/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx b/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
index a8ff0a923f2..6a8f30cf3ed 100644
--- a/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
+++ b/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
@@ -1,7 +1,11 @@
import {
+ type ElementProps,
+ type FloatingContext,
type OpenChangeReason,
flip,
+ useClick,
useDismiss,
+ useFocus,
useInteractions,
} from "@floating-ui/react";
import { createContext, useControlled, useFloatingUI } from "@salt-ds/core";
@@ -9,10 +13,10 @@ import {
type ReactNode,
useCallback,
useContext,
- useEffect,
useMemo,
useRef,
} from "react";
+import { useKeyboard } from "./useKeyboard";
/**
* Interface representing the state for a DatePicker overlay.
@@ -81,6 +85,18 @@ interface DatePickerOverlayProviderProps {
* If `true`, the overlay is open.
*/
open?: boolean;
+ /**
+ * When `open` is uncontrolled, set this to `true` to open on focus
+ */
+ openOnFocus?: boolean;
+ /**
+ * When `open` is uncontrolled, set this to `true` to open on click
+ */
+ openOnClick?: boolean;
+ /**
+ * When `open` is uncontrolled, set this to `true` to open on arrow key down
+ */
+ openOnKeyDown?: boolean;
/**
* Handler for when open state changes
* @param newOpen - true when opened
@@ -94,6 +110,10 @@ interface DatePickerOverlayProviderProps {
* The content to be rendered inside the overlay provider.
*/
children: ReactNode;
+ /**
+ * A factory method to create a set of interaction, if provided overrides the default interactions
+ */
+ interactions?: (context: FloatingContext) => Array;
/**
* When true, shouldn't open the overlay.
*/
@@ -102,8 +122,18 @@ interface DatePickerOverlayProviderProps {
export const DatePickerOverlayProvider: React.FC<
DatePickerOverlayProviderProps
-> = ({ open: openProp, defaultOpen, onOpen, children, readOnly }) => {
- const [open, setOpenState] = useControlled({
+> = ({
+ open: openProp,
+ openOnClick,
+ openOnFocus,
+ openOnKeyDown,
+ defaultOpen,
+ onOpen,
+ children,
+ interactions,
+ readOnly,
+}) => {
+ const [open, setOpenState, isOpenControlled] = useControlled({
controlled: openProp,
default: Boolean(defaultOpen),
name: "DatePicker",
@@ -112,36 +142,30 @@ export const DatePickerOverlayProvider: React.FC<
const triggeringElement = useRef(null);
const onDismissCallback = useRef<() => void>();
- useEffect(() => {
- if (!open) {
- const trigger = triggeringElement.current as HTMLElement;
- if (trigger) {
- trigger.focus();
- }
- if (trigger instanceof HTMLInputElement) {
- setTimeout(() => {
- trigger.setSelectionRange(0, trigger.value.length);
- }, 0);
- }
- triggeringElement.current = null;
- }
- }, [open]);
-
const setOpen = useCallback(
- (
- newOpen: boolean,
- _event?: Event | undefined,
- reason?: OpenChangeReason | undefined,
- ) => {
+ (newOpen: boolean, _event?: Event, reason?: OpenChangeReason) => {
if (newOpen) {
if (readOnly) {
// When not open overlay when readOnly
return;
}
triggeringElement.current = document.activeElement as HTMLElement;
+ } else if (!isOpenControlled) {
+ const trigger = triggeringElement.current as HTMLElement;
+ if (trigger) {
+ trigger.focus();
+ }
+ if (trigger instanceof HTMLInputElement) {
+ setTimeout(() => {
+ trigger.setSelectionRange(0, trigger.value.length);
+ }, 1);
+ }
+ triggeringElement.current = null;
}
+
setOpenState(newOpen);
onOpen?.(newOpen);
+
if (
reason === "escape-key" ||
(reason === "outside-press" && onDismissCallback.current)
@@ -162,7 +186,22 @@ export const DatePickerOverlayProvider: React.FC<
const {
getFloatingProps: _getFloatingPropsCallback,
getReferenceProps: _getReferenceProps,
- } = useInteractions([useDismiss(floatingUIResult.context)]);
+ } = useInteractions(
+ interactions
+ ? interactions(floatingUIResult.context)
+ : [
+ useDismiss(floatingUIResult.context),
+ useFocus(floatingUIResult.context, {
+ enabled: !!openOnFocus,
+ }),
+ useKeyboard(floatingUIResult.context, { enabled: !!openOnKeyDown }),
+ useClick(floatingUIResult.context, {
+ enabled: !!openOnClick,
+ toggle: false,
+ }),
+ ],
+ );
+
const getFloatingPropsCallback = useMemo(
() => _getFloatingPropsCallback,
[_getFloatingPropsCallback],
diff --git a/packages/lab/src/date-picker/DatePickerRangeInput.tsx b/packages/lab/src/date-picker/DatePickerRangeInput.tsx
index f8a9db18e6d..e0d15bdf664 100644
--- a/packages/lab/src/date-picker/DatePickerRangeInput.tsx
+++ b/packages/lab/src/date-picker/DatePickerRangeInput.tsx
@@ -6,8 +6,6 @@ import {
} from "@salt-ds/date-adapters";
import { clsx } from "clsx";
import {
- type KeyboardEvent,
- type KeyboardEventHandler,
type SyntheticEvent,
forwardRef,
useCallback,
@@ -121,9 +119,8 @@ export const DatePickerRangeInput = forwardRef(function DatePickerRangeInput<
const { dateAdapter } = useLocalization();
const {
className,
- endInputProps: endInputPropsProp,
- startInputProps: startInputPropsProp,
- onKeyDown,
+ endInputProps,
+ startInputProps,
defaultValue,
format,
value: valueProp,
@@ -193,29 +190,6 @@ export const DatePickerRangeInput = forwardRef(function DatePickerRangeInput<
}
}, [cancelled]);
- const startInputProps: {
- onKeyDown: KeyboardEventHandler;
- } = {
- onKeyDown: (event: KeyboardEvent) => {
- if (event.key === "ArrowDown") {
- setOpen(true);
- }
- startInputPropsProp?.onKeyDown?.(event);
- },
- ...startInputPropsProp,
- };
- const endInputProps: {
- onKeyDown: KeyboardEventHandler;
- } = {
- onKeyDown: (event: KeyboardEvent) => {
- if (event.key === "ArrowDown") {
- setOpen(true);
- }
- endInputPropsProp?.onKeyDown?.(event);
- },
- ...endInputPropsProp,
- };
-
return (
) => {
- if (event.key === "ArrowDown") {
- setOpen(true);
- onKeyDown?.(event);
- }
- },
- [onKeyDown],
- );
-
// biome-ignore lint/correctness/useExhaustiveDependencies: should run when open changes and not selected date or value
useEffect(() => {
if (open) {
@@ -200,7 +188,6 @@ export const DatePickerSingleInput = forwardRef<
)
}
- onKeyDown={handleOnKeyDown}
{...rest}
/>
);
diff --git a/packages/lab/src/date-picker/useKeyboard.ts b/packages/lab/src/date-picker/useKeyboard.ts
new file mode 100644
index 00000000000..5c93c315277
--- /dev/null
+++ b/packages/lab/src/date-picker/useKeyboard.ts
@@ -0,0 +1,36 @@
+import type { ElementProps, FloatingContext } from "@floating-ui/react";
+import { useMemo } from "react";
+
+export interface UseKeyboardProps {
+ /**
+ * Whether the hook is enabled
+ * @default true
+ */
+ enabled?: boolean;
+}
+
+/**
+ * Floating UI Interactions hook, that will open DatePicker on keydown
+ * @param context
+ * @param props
+ */
+export function useKeyboard(
+ context: FloatingContext,
+ props: UseKeyboardProps,
+): ElementProps {
+ const { onOpenChange } = context;
+ const { enabled = true } = props;
+ const reference: ElementProps["reference"] = useMemo(
+ () => ({
+ onKeyDown(event) {
+ if (event.key === "ArrowDown") {
+ event.preventDefault();
+ onOpenChange(true, event.nativeEvent, "reference-press");
+ }
+ },
+ }),
+ [onOpenChange],
+ );
+
+ return useMemo(() => (enabled ? { reference } : {}), [enabled, reference]);
+}
diff --git a/packages/lab/stories/date-picker/date-picker.stories.tsx b/packages/lab/stories/date-picker/date-picker.stories.tsx
index 8e22b0270bc..81b220b40bc 100644
--- a/packages/lab/stories/date-picker/date-picker.stories.tsx
+++ b/packages/lab/stories/date-picker/date-picker.stories.tsx
@@ -1,3 +1,4 @@
+import type { OpenChangeReason } from "@floating-ui/react";
import {
Button,
Divider,
@@ -8,6 +9,7 @@ import {
FormFieldLabel as FormLabel,
StackLayout,
Text,
+ ToggleButton,
} from "@salt-ds/core";
import {
DateDetailErrorEnum,
@@ -175,7 +177,7 @@ Range.args = {
export const SingleReadOnly = DatePickerSingleTemplate.bind({});
SingleReadOnly.args = {
- readOnly: true,
+ readOnly: true
};
export const RangeReadOnly = DatePickerRangeTemplate.bind({});
@@ -2692,3 +2694,161 @@ WithExperimentalTime.parameters = {
},
},
};
+
+export const UncontrolledOpen: StoryFn<
+ DatePickerSingleProps
+> = ({ selectionVariant, defaultSelectedDate, ...args }) => {
+ const [openOnClick, setOpenOnClick] = useState(false);
+ const [openOnKeyDown, setOpenOnKeyDown] = useState(false);
+ const [openOnFocus, setOpenOnFocus] = useState(false);
+ return (
+
+
+
+ setOpenOnFocus(event.currentTarget.value === "true")
+ }
+ >
+ Open On Focus
+
+
+ setOpenOnClick(event.currentTarget.value === "true")
+ }
+ >
+ Open On Click
+
+
+ setOpenOnKeyDown(event.currentTarget.value === "true")
+ }
+ >
+ Open On Key Down
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export const ControlledOpen: StoryFn<
+ DatePickerSingleProps
+> = ({ selectionVariant, defaultSelectedDate, ...args }) => {
+ const [open, setOpen] = useState(false);
+ const [selectedDate, setSelectedDate] = useState<
+ SingleDateSelection | null | undefined
+ >(defaultSelectedDate ?? null);
+ const { dateAdapter } = useLocalization();
+ const triggerRef = useRef(null);
+ const applyButtonRef = useRef(null);
+ const datePickerRef = useRef(null);
+
+ const handleSelectionChange = useCallback(
+ (
+ _event: SyntheticEvent,
+ date: SingleDateSelection | null,
+ _details: DateInputSingleDetails | undefined,
+ ) => {
+ setSelectedDate(date ?? null);
+ },
+ [dateAdapter],
+ );
+
+ const handleApply = useCallback(
+ (
+ event: SyntheticEvent,
+ date: SingleDateSelection | null,
+ ) => {
+ console.log(
+ `Applied StartDate: ${date ? dateAdapter.format(date, "DD MMM YYYY") : date}`,
+ );
+ setSelectedDate(date);
+ setOpen(false);
+ },
+ [dateAdapter],
+ );
+
+ const handleOpen = useCallback(
+ (
+ newOpen: boolean,
+ _event?: Event | undefined,
+ reason?: OpenChangeReason | undefined,
+ ) => {
+ if (!newOpen && reason === undefined) {
+ triggerRef?.current?.focus();
+ setTimeout(() => {
+ triggerRef?.current?.setSelectionRange(
+ 0,
+ triggerRef.current.value.length,
+ );
+ }, 1);
+ }
+ setOpen(newOpen);
+ },
+ [],
+ );
+
+ return (
+
+
+ {
+ setOpen(event.currentTarget.value === "true");
+ }}
+ >
+ Open
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/site/docs/components/date-picker/examples.mdx b/site/docs/components/date-picker/examples.mdx
index 28f59328b09..8cd1d391fb0 100644
--- a/site/docs/components/date-picker/examples.mdx
+++ b/site/docs/components/date-picker/examples.mdx
@@ -170,5 +170,21 @@ A `DatePicker` component with a border provides a visually distinct area for sel
+
+
+## Uncontrolled open
+
+By default, the overlay's open state is uncontrolled and opens only when the calendar button is used. However, it can also be configured to open using the `openOnClick`, `openOnKeyDown` and `openOnFocus` props.
+
+
+
+
+
+## Controlled open
+
+By default, the overlay's open state is uncontrolled and opens only when the calendar button is pressed. However, you can fully control the overlay's open behavior using the `open` prop. When you manage the open state, you also take responsibility for handling the input's focus behavior after a selection is made.
+
+
+
```
diff --git a/site/src/examples/date-picker/ControlledOpen.tsx b/site/src/examples/date-picker/ControlledOpen.tsx
new file mode 100644
index 00000000000..026876710c0
--- /dev/null
+++ b/site/src/examples/date-picker/ControlledOpen.tsx
@@ -0,0 +1,126 @@
+import type { OpenChangeReason } from "@floating-ui/react";
+import {
+ Divider,
+ FlexItem,
+ FlexLayout,
+ StackLayout,
+ ToggleButton,
+} from "@salt-ds/core";
+import type { DateFrameworkType } from "@salt-ds/date-adapters";
+import {
+ type DateInputSingleDetails,
+ DatePicker,
+ DatePickerActions,
+ DatePickerOverlay,
+ DatePickerSingleInput,
+ DatePickerSinglePanel,
+ DatePickerTrigger,
+ type SingleDateSelection,
+ useLocalization,
+} from "@salt-ds/lab";
+import {
+ type ReactElement,
+ type SyntheticEvent,
+ useCallback,
+ useRef,
+ useState,
+} from "react";
+
+export const ControlledOpen = (): ReactElement => {
+ const [open, setOpen] = useState(false);
+ const [selectedDate, setSelectedDate] = useState<
+ SingleDateSelection | null | undefined
+ >(null);
+ const { dateAdapter } = useLocalization();
+ const triggerRef = useRef(null);
+ const applyButtonRef = useRef(null);
+ const datePickerRef = useRef(null);
+
+ const handleSelectionChange = useCallback(
+ (
+ _event: SyntheticEvent,
+ date: SingleDateSelection | null,
+ _details: DateInputSingleDetails | undefined,
+ ) => {
+ setSelectedDate(date ?? null);
+ },
+ [dateAdapter],
+ );
+
+ const handleApply = useCallback(
+ (
+ event: SyntheticEvent,
+ date: SingleDateSelection | null,
+ ) => {
+ console.log(
+ `Applied StartDate: ${date ? dateAdapter.format(date, "DD MMM YYYY") : date}`,
+ );
+ setSelectedDate(date);
+ setOpen(false);
+ },
+ [dateAdapter],
+ );
+
+ const handleOpen = useCallback(
+ (
+ newOpen: boolean,
+ _event?: Event | undefined,
+ reason?: OpenChangeReason | undefined,
+ ) => {
+ if (reason === undefined) {
+ triggerRef?.current?.focus();
+ setTimeout(() => {
+ triggerRef?.current?.setSelectionRange(
+ 0,
+ triggerRef.current.value.length,
+ );
+ }, 1);
+ }
+ setOpen(newOpen);
+ },
+ [],
+ );
+
+ return (
+
+
+ {
+ setOpen(event.currentTarget.value === "true");
+ }}
+ >
+ Open
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/site/src/examples/date-picker/UncontrolledOpen.tsx b/site/src/examples/date-picker/UncontrolledOpen.tsx
new file mode 100644
index 00000000000..201b38760f3
--- /dev/null
+++ b/site/src/examples/date-picker/UncontrolledOpen.tsx
@@ -0,0 +1,61 @@
+import { FlexLayout, StackLayout, ToggleButton } from "@salt-ds/core";
+import {
+ DatePicker,
+ DatePickerOverlay,
+ DatePickerSingleInput,
+ DatePickerSinglePanel,
+ DatePickerTrigger,
+} from "@salt-ds/lab";
+import { type ReactElement, useState } from "react";
+
+export const UncontrolledOpen = (): ReactElement => {
+ const [openOnClick, setOpenOnClick] = useState(false);
+ const [openOnKeyDown, setOpenOnKeyDown] = useState(false);
+ const [openOnFocus, setOpenOnFocus] = useState(false);
+ return (
+
+
+
+ setOpenOnFocus(event.currentTarget.value === "true")
+ }
+ >
+ Open On Focus
+
+
+ setOpenOnClick(event.currentTarget.value === "true")
+ }
+ >
+ Open On Click
+
+
+ setOpenOnKeyDown(event.currentTarget.value === "true")
+ }
+ >
+ Open On Key Down
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/site/src/examples/date-picker/index.ts b/site/src/examples/date-picker/index.ts
index 38d075f5ff2..3be5f46bf18 100644
--- a/site/src/examples/date-picker/index.ts
+++ b/site/src/examples/date-picker/index.ts
@@ -19,3 +19,5 @@ export * from "./RangeWithLocaleEsES";
export * from "./RangeWithMinMaxDate";
export * from "./RangeWithFormField";
export * from "./RangeBordered";
+export * from "./ControlledOpen";
+export * from "./UncontrolledOpen";
From 57c3dffdcd915943a9ac4a6fe1e608ad035e1f64 Mon Sep 17 00:00:00 2001
From: mark-tate <143323+mark-tate@users.noreply.github.com>
Date: Fri, 13 Dec 2024 21:46:19 +0000
Subject: [PATCH 2/4] update un-controlled open behaviour to be disabled when
read-only
---
.../date-picker/DatePicker.single.cy.tsx | 41 +++++++++----------
.../date-picker/DatePickerOverlayProvider.tsx | 15 +++----
.../date-picker/date-picker.stories.tsx | 2 +-
3 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
index a1e771ad296..032495cca33 100644
--- a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
+++ b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
@@ -90,6 +90,11 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
cy.findByRole("textbox").click().type("{downArrow}", { force: true });
cy.findByRole("application").should("not.exist");
});
+
+ it("SHOULD not open overlay if defaultOpen is set", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ });
});
adapters.forEach((adapter: SaltDateAdapter) => {
@@ -482,9 +487,7 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
});
it("SHOULD be able to enable the overlay to open on click", () => {
- cy.mount(
- ,
- );
+ cy.mount();
cy.findByRole("application").should("not.exist");
// Simulate opening the calendar on click
cy.document().find("input").realClick();
@@ -497,18 +500,14 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
name: adapter.format(updatedDate, "DD MMMM YYYY"),
}).realClick();
cy.findByRole("application").should("not.exist");
- cy.document()
- .find("input")
- .should("have.value", updatedFormattedDateValue);
+ cy.findByRole("textbox").should(
+ "have.value",
+ updatedFormattedDateValue,
+ );
});
it("SHOULD be able to enable the overlay to open on keydown", () => {
- cy.mount(
- ,
- );
+ cy.mount();
cy.findByRole("application").should("not.exist");
// Simulate opening the calendar on arrow down
cy.document().find("input").realClick();
@@ -523,15 +522,14 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
name: adapter.format(updatedDate, "DD MMMM YYYY"),
}).realClick();
cy.findByRole("application").should("not.exist");
- cy.document()
- .find("input")
- .should("have.value", updatedFormattedDateValue);
+ cy.findByRole("textbox").should(
+ "have.value",
+ updatedFormattedDateValue,
+ );
});
it("SHOULD be able to enable the overlay to open on focus", () => {
- cy.mount(
- ,
- );
+ cy.mount();
cy.findByRole("application").should("not.exist");
// Simulate opening the calendar on focus
cy.document().find("input").focus();
@@ -544,9 +542,10 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
name: adapter.format(updatedDate, "DD MMMM YYYY"),
}).realClick();
cy.findByRole("application").should("not.exist");
- cy.document()
- .find("input")
- .should("have.value", updatedFormattedDateValue);
+ cy.findByRole("textbox").should(
+ "have.value",
+ updatedFormattedDateValue,
+ );
});
});
diff --git a/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx b/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
index 6a8f30cf3ed..3ca3623b84e 100644
--- a/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
+++ b/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
@@ -113,7 +113,7 @@ interface DatePickerOverlayProviderProps {
/**
* A factory method to create a set of interaction, if provided overrides the default interactions
*/
- interactions?: (context: FloatingContext) => Array;
+ interactions?: (context: FloatingContext) => Array;
/**
* When true, shouldn't open the overlay.
*/
@@ -126,7 +126,7 @@ export const DatePickerOverlayProvider: React.FC<
open: openProp,
openOnClick,
openOnFocus,
- openOnKeyDown,
+ openOnKeyDown = true,
defaultOpen,
onOpen,
children,
@@ -135,7 +135,7 @@ export const DatePickerOverlayProvider: React.FC<
}) => {
const [open, setOpenState, isOpenControlled] = useControlled({
controlled: openProp,
- default: Boolean(defaultOpen),
+ default: readOnly ? false : Boolean(defaultOpen),
name: "DatePicker",
state: "openDatePickerOverlay",
});
@@ -146,7 +146,6 @@ export const DatePickerOverlayProvider: React.FC<
(newOpen: boolean, _event?: Event, reason?: OpenChangeReason) => {
if (newOpen) {
if (readOnly) {
- // When not open overlay when readOnly
return;
}
triggeringElement.current = document.activeElement as HTMLElement;
@@ -192,11 +191,13 @@ export const DatePickerOverlayProvider: React.FC<
: [
useDismiss(floatingUIResult.context),
useFocus(floatingUIResult.context, {
- enabled: !!openOnFocus,
+ enabled: !!openOnFocus && !readOnly,
+ }),
+ useKeyboard(floatingUIResult.context, {
+ enabled: !!openOnKeyDown && !readOnly,
}),
- useKeyboard(floatingUIResult.context, { enabled: !!openOnKeyDown }),
useClick(floatingUIResult.context, {
- enabled: !!openOnClick,
+ enabled: !!openOnClick && !readOnly,
toggle: false,
}),
],
diff --git a/packages/lab/stories/date-picker/date-picker.stories.tsx b/packages/lab/stories/date-picker/date-picker.stories.tsx
index 81b220b40bc..af025a9cb65 100644
--- a/packages/lab/stories/date-picker/date-picker.stories.tsx
+++ b/packages/lab/stories/date-picker/date-picker.stories.tsx
@@ -177,7 +177,7 @@ Range.args = {
export const SingleReadOnly = DatePickerSingleTemplate.bind({});
SingleReadOnly.args = {
- readOnly: true
+ readOnly: true,
};
export const RangeReadOnly = DatePickerRangeTemplate.bind({});
From 2b97d3d447ba7cfac597096ca6134de5c72964ae Mon Sep 17 00:00:00 2001
From: mark-tate <143323+mark-tate@users.noreply.github.com>
Date: Mon, 16 Dec 2024 14:57:34 +0000
Subject: [PATCH 3/4] fix tests
---
.../date-picker/DatePicker.range.cy.tsx | 40 ++++++
.../date-picker/DatePicker.single.cy.tsx | 126 ++++++------------
2 files changed, 79 insertions(+), 87 deletions(-)
diff --git a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx
index 86d2e0c0d0a..637e156d6c3 100644
--- a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx
+++ b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx
@@ -65,6 +65,46 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
// Verify that the calendar is displayed
cy.findAllByRole("application").should("have.length", 2);
});
+
+ it("SHOULD be able to enable the overlay to open on click", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on click
+ cy.findByLabelText("Start date").realClick();
+ cy.findAllByRole("application").should("have.length", 2);
+ cy.document().find("body").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.findByLabelText("End date").realClick();
+ cy.findAllByRole("application").should("have.length", 2);
+ });
+
+ it("SHOULD be able to enable the overlay to open on keydown", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on arrow down
+ cy.findByLabelText("Start date").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.realPress("ArrowDown");
+ cy.findAllByRole("application").should("have.length", 2);
+ cy.document().find("body").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.findByLabelText("End date").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.realPress("ArrowDown");
+ cy.findAllByRole("application").should("have.length", 2);
+ });
+
+ it("SHOULD be able to enable the overlay to open on focus", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on focus
+ cy.findByLabelText("Start date").focus();
+ cy.findAllByRole("application").should("have.length", 2);
+ cy.document().find("body").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.findByLabelText("End date").focus();
+ cy.findAllByRole("application").should("have.length", 2);
+ });
});
describe("WHEN readOnly", () => {
diff --git a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
index 032495cca33..2809282a37b 100644
--- a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
+++ b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
@@ -36,7 +36,6 @@ const {
SingleWithMinMaxDate,
SingleWithTodayButton,
SingleCustomFormat,
- UncontrolledOpen,
} = datePickerStories as any;
describe("GIVEN a DatePicker where selectionVariant is single", () => {
@@ -67,6 +66,45 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
// Verify that the calendar is displayed
cy.findByRole("application").should("exist");
});
+
+ it("SHOULD be able to enable the overlay to open on click", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on click
+ cy.document().find("input").realClick();
+ cy.findByRole("application").should("exist");
+ });
+
+ it("SHOULD be able to enable the overlay to open on keydown", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on arrow down
+ cy.document().find("input").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.realPress("ArrowDown");
+ cy.findByRole("application").should("exist");
+ });
+
+ it("SHOULD be able to enable the overlay to open on focus", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar on focus
+ cy.document().find("input").focus();
+ cy.findByRole("application").should("exist");
+ });
+
+ it("SHOULD be able to control the overlay open state", () => {
+ cy.mount();
+ cy.findByRole("application").should("not.exist");
+ // Simulate opening the calendar through a controlled state
+ cy.document().find("input").realClick();
+ cy.findByRole("application").should("not.exist");
+ cy.findByRole("button", { name: "Open Calendar" }).realClick();
+ cy.findByRole("application").should("exist");
+ cy.findByRole("button", { name: "Cancel" }).realClick();
+ // Verify that the calendar can be closed by user
+ cy.findByRole("application").should("not.exist");
+ });
});
describe("WHEN readOnly", () => {
@@ -485,68 +523,6 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
updatedFormattedDateValue,
);
});
-
- it("SHOULD be able to enable the overlay to open on click", () => {
- cy.mount();
- cy.findByRole("application").should("not.exist");
- // Simulate opening the calendar on click
- cy.document().find("input").realClick();
- cy.findByRole("application").should("exist");
- // Simulate selecting a new date
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).should("exist");
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).realClick();
- cy.findByRole("application").should("not.exist");
- cy.findByRole("textbox").should(
- "have.value",
- updatedFormattedDateValue,
- );
- });
-
- it("SHOULD be able to enable the overlay to open on keydown", () => {
- cy.mount();
- cy.findByRole("application").should("not.exist");
- // Simulate opening the calendar on arrow down
- cy.document().find("input").realClick();
- cy.findByRole("application").should("not.exist");
- cy.realPress("ArrowDown");
- cy.findByRole("application").should("exist");
- // Simulate selecting a new date
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).should("exist");
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).realClick();
- cy.findByRole("application").should("not.exist");
- cy.findByRole("textbox").should(
- "have.value",
- updatedFormattedDateValue,
- );
- });
-
- it("SHOULD be able to enable the overlay to open on focus", () => {
- cy.mount();
- cy.findByRole("application").should("not.exist");
- // Simulate opening the calendar on focus
- cy.document().find("input").focus();
- cy.findByRole("application").should("exist");
- // Simulate selecting a new date
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).should("exist");
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).realClick();
- cy.findByRole("application").should("not.exist");
- cy.findByRole("textbox").should(
- "have.value",
- updatedFormattedDateValue,
- );
- });
});
describe("controlled component", () => {
@@ -631,30 +607,6 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
});
});
- it("SHOULD be able to control the overlay open state", () => {
- cy.mount();
- cy.findByRole("application").should("not.exist");
- // Simulate opening the calendar
- cy.document().find("input").realClick();
- cy.findByRole("application").should("not.exist");
- cy.findByRole("button", { name: "Open Calendar" }).realClick();
- cy.findByRole("application").should("exist");
- // Simulate selecting a new date
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).should("exist");
- cy.findByRole("button", {
- name: adapter.format(updatedDate, "DD MMMM YYYY"),
- }).realClick();
- cy.findByRole("application").should("exist");
- cy.findByRole("button", { name: "Apply" }).realClick();
- // Verify that the calendar is closed and the new date is applied
- cy.findByRole("application").should("not.exist");
- cy.document()
- .find("input")
- .should("have.value", updatedFormattedDateValue);
- });
-
it("SHOULD support format prop on the input", () => {
const format = "YYYY-MM-DD";
From 1ed601d35402b47b314d202527017ee4d98591c8 Mon Sep 17 00:00:00 2001
From: mark-tate <143323+mark-tate@users.noreply.github.com>
Date: Fri, 20 Dec 2024 15:01:06 +0000
Subject: [PATCH 4/4] remove `openOnFocus`
---
.changeset/serious-kings-decide.md | 2 +-
.../__e2e__/date-picker/DatePicker.range.cy.tsx | 12 ------------
.../__e2e__/date-picker/DatePicker.single.cy.tsx | 8 --------
packages/lab/src/date-picker/DatePicker.tsx | 4 ----
.../src/date-picker/DatePickerOverlayProvider.tsx | 9 ---------
.../lab/stories/date-picker/date-picker.stories.tsx | 11 -----------
site/docs/components/date-picker/examples.mdx | 2 +-
site/src/examples/date-picker/UncontrolledOpen.tsx | 11 -----------
8 files changed, 2 insertions(+), 57 deletions(-)
diff --git a/.changeset/serious-kings-decide.md b/.changeset/serious-kings-decide.md
index 3bddf2257c5..5d16a1da34c 100644
--- a/.changeset/serious-kings-decide.md
+++ b/.changeset/serious-kings-decide.md
@@ -4,6 +4,6 @@
enabled uncontrolled/un-controlled open behaviour for `DatePicker`
-- added `openOnClick`, `openOnKeyDown` and `openOnFocus` props to `DatePicker`.
+- added `openOnClick` and `openOnKeyDown` props to `DatePicker`.
- revise the controlled behaviour of the `open` prop on `DatePickerOverlay`.
- add examples for controlled and uncontrolled behaviour.
diff --git a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx
index 637e156d6c3..d9a2be0fb16 100644
--- a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx
+++ b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.range.cy.tsx
@@ -93,18 +93,6 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
cy.realPress("ArrowDown");
cy.findAllByRole("application").should("have.length", 2);
});
-
- it("SHOULD be able to enable the overlay to open on focus", () => {
- cy.mount();
- cy.findByRole("application").should("not.exist");
- // Simulate opening the calendar on focus
- cy.findByLabelText("Start date").focus();
- cy.findAllByRole("application").should("have.length", 2);
- cy.document().find("body").realClick();
- cy.findByRole("application").should("not.exist");
- cy.findByLabelText("End date").focus();
- cy.findAllByRole("application").should("have.length", 2);
- });
});
describe("WHEN readOnly", () => {
diff --git a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
index 2809282a37b..a1368df1f6f 100644
--- a/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
+++ b/packages/lab/src/__tests__/__e2e__/date-picker/DatePicker.single.cy.tsx
@@ -85,14 +85,6 @@ describe("GIVEN a DatePicker where selectionVariant is single", () => {
cy.findByRole("application").should("exist");
});
- it("SHOULD be able to enable the overlay to open on focus", () => {
- cy.mount();
- cy.findByRole("application").should("not.exist");
- // Simulate opening the calendar on focus
- cy.document().find("input").focus();
- cy.findByRole("application").should("exist");
- });
-
it("SHOULD be able to control the overlay open state", () => {
cy.mount();
cy.findByRole("application").should("not.exist");
diff --git a/packages/lab/src/date-picker/DatePicker.tsx b/packages/lab/src/date-picker/DatePicker.tsx
index dcf524995e7..55c9c553003 100644
--- a/packages/lab/src/date-picker/DatePicker.tsx
+++ b/packages/lab/src/date-picker/DatePicker.tsx
@@ -21,8 +21,6 @@ export interface DatePickerBaseProps {
children?: ReactNode;
/** the open/close state of the overlay. The open/close state will be controlled when this prop is provided. */
open?: boolean;
- /** When `open` is uncontrolled, set this to `true` to open on focus */
- openOnFocus?: boolean;
/** When `open` is uncontrolled, set this to `true` to open on click */
openOnClick?: boolean;
/** When `open` is uncontrolled, set this to `true` to open on arrow key down */
@@ -134,7 +132,6 @@ export const DatePicker = forwardRef(function DatePicker<
defaultOpen,
open,
openOnClick,
- openOnFocus,
openOnKeyDown,
onOpen,
readOnly,
@@ -146,7 +143,6 @@ export const DatePicker = forwardRef(function DatePicker<
defaultOpen={defaultOpen}
open={open}
openOnClick={openOnClick}
- openOnFocus={openOnFocus}
openOnKeyDown={openOnKeyDown}
onOpen={onOpen}
readOnly={readOnly}
diff --git a/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx b/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
index 3ca3623b84e..2d0b32a209a 100644
--- a/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
+++ b/packages/lab/src/date-picker/DatePickerOverlayProvider.tsx
@@ -5,7 +5,6 @@ import {
flip,
useClick,
useDismiss,
- useFocus,
useInteractions,
} from "@floating-ui/react";
import { createContext, useControlled, useFloatingUI } from "@salt-ds/core";
@@ -85,10 +84,6 @@ interface DatePickerOverlayProviderProps {
* If `true`, the overlay is open.
*/
open?: boolean;
- /**
- * When `open` is uncontrolled, set this to `true` to open on focus
- */
- openOnFocus?: boolean;
/**
* When `open` is uncontrolled, set this to `true` to open on click
*/
@@ -125,7 +120,6 @@ export const DatePickerOverlayProvider: React.FC<
> = ({
open: openProp,
openOnClick,
- openOnFocus,
openOnKeyDown = true,
defaultOpen,
onOpen,
@@ -190,9 +184,6 @@ export const DatePickerOverlayProvider: React.FC<
? interactions(floatingUIResult.context)
: [
useDismiss(floatingUIResult.context),
- useFocus(floatingUIResult.context, {
- enabled: !!openOnFocus && !readOnly,
- }),
useKeyboard(floatingUIResult.context, {
enabled: !!openOnKeyDown && !readOnly,
}),
diff --git a/packages/lab/stories/date-picker/date-picker.stories.tsx b/packages/lab/stories/date-picker/date-picker.stories.tsx
index af025a9cb65..4c2250a969f 100644
--- a/packages/lab/stories/date-picker/date-picker.stories.tsx
+++ b/packages/lab/stories/date-picker/date-picker.stories.tsx
@@ -2700,19 +2700,9 @@ export const UncontrolledOpen: StoryFn<
> = ({ selectionVariant, defaultSelectedDate, ...args }) => {
const [openOnClick, setOpenOnClick] = useState(false);
const [openOnKeyDown, setOpenOnKeyDown] = useState(false);
- const [openOnFocus, setOpenOnFocus] = useState(false);
return (
-
- setOpenOnFocus(event.currentTarget.value === "true")
- }
- >
- Open On Focus
-
diff --git a/site/docs/components/date-picker/examples.mdx b/site/docs/components/date-picker/examples.mdx
index 8cd1d391fb0..35ce418c458 100644
--- a/site/docs/components/date-picker/examples.mdx
+++ b/site/docs/components/date-picker/examples.mdx
@@ -174,7 +174,7 @@ A `DatePicker` component with a border provides a visually distinct area for sel
## Uncontrolled open
-By default, the overlay's open state is uncontrolled and opens only when the calendar button is used. However, it can also be configured to open using the `openOnClick`, `openOnKeyDown` and `openOnFocus` props.
+By default, the overlay's open state is uncontrolled and opens only when the calendar button is used. However, it can also be configured to open using the `openOnClick` and `openOnKeyDown`props.
diff --git a/site/src/examples/date-picker/UncontrolledOpen.tsx b/site/src/examples/date-picker/UncontrolledOpen.tsx
index 201b38760f3..77d3f492599 100644
--- a/site/src/examples/date-picker/UncontrolledOpen.tsx
+++ b/site/src/examples/date-picker/UncontrolledOpen.tsx
@@ -11,19 +11,9 @@ import { type ReactElement, useState } from "react";
export const UncontrolledOpen = (): ReactElement => {
const [openOnClick, setOpenOnClick] = useState(false);
const [openOnKeyDown, setOpenOnKeyDown] = useState(false);
- const [openOnFocus, setOpenOnFocus] = useState(false);
return (
-
- setOpenOnFocus(event.currentTarget.value === "true")
- }
- >
- Open On Focus
-
{
selectionVariant={"single"}
openOnClick={openOnClick}
openOnKeyDown={openOnKeyDown}
- openOnFocus={openOnFocus}
>