diff --git a/semcore/date-picker/__tests__/date-picker.axe-test.tsx b/semcore/date-picker/__tests__/date-picker.axe-test.tsx index 0c76158d81..7c239240b6 100644 --- a/semcore/date-picker/__tests__/date-picker.axe-test.tsx +++ b/semcore/date-picker/__tests__/date-picker.axe-test.tsx @@ -87,6 +87,38 @@ test.describe(`@date-picker ${TAG.ACCESSIBILITY}`, () => { } }); + test('Reset date', async ({ page }) => { + await loadPage(page, 'stories/components/date-picker/docs/examples/reset_date_picker.tsx', 'en'); + + // base check + { + const violations = await getAccessibilityViolations({ page }); + + expect(violations).toEqual([]); + } + + // reset picker check + { + await page.keyboard.press('Tab'); + await page.keyboard.press('Tab'); + await page.keyboard.press('Enter'); + + const violations = await getAccessibilityViolations({ page }); + + expect(violations).toEqual([]); + } + + // opened date picker check + { + await page.keyboard.press('Shift+Tab'); + await page.keyboard.press('Enter'); + + const violations = await getAccessibilityViolations({ page }); + + expect(violations).toEqual([]); + } + }); + test('Date range comparator', async ({ page }) => { await loadPage(page, 'stories/components/date-picker/docs/examples/date_range_comparator.tsx', 'en'); diff --git a/semcore/date-picker/__tests__/date-picker.browser-test.tsx b/semcore/date-picker/__tests__/date-picker.browser-test.tsx index b00c83da03..d1108175f4 100644 --- a/semcore/date-picker/__tests__/date-picker.browser-test.tsx +++ b/semcore/date-picker/__tests__/date-picker.browser-test.tsx @@ -468,6 +468,22 @@ test.describe(`${TAG.FUNCTIONAL}`, () => { }); }); + test('Verify it is possible to reset the date', { + tag: [TAG.PRIORITY_HIGH, + TAG.MOUSE, + '@date-picker'], + }, async ({ page }) => { + await loadPage(page, 'stories/components/date-picker/docs/examples/reset_date_picker.tsx', 'en'); + + const input = page.locator('input[data-ui-name="DatePicker.Trigger"]'); + + const initialValue = await input.inputValue(); + await locators.button(page).click(); + const newValue = await input.inputValue(); + expect(newValue).not.toBe(initialValue); + expect(newValue).toBe(''); + }); + test('Verify datepicker with today button by keyboard interactions', { tag: [TAG.PRIORITY_HIGH, TAG.KEYBOARD, diff --git a/stories/components/date-picker/docs/__tests__/reset_date_picker.test.tsx b/stories/components/date-picker/docs/__tests__/reset_date_picker.test.tsx new file mode 100644 index 0000000000..f2f570b70e --- /dev/null +++ b/stories/components/date-picker/docs/__tests__/reset_date_picker.test.tsx @@ -0,0 +1,19 @@ +import { expect, userEvent, within } from 'storybook/test'; + +export async function ResetDatePickerTest({ canvasElement }: { canvasElement: HTMLElement }) { + const canvas = within(canvasElement); + + const triggers = canvasElement.querySelector('[data-ui-name="DatePicker.Trigger"]'); + const resetButton = canvasElement.querySelector('[data-ui-name="Button"]'); + + if (!triggers) { + throw new Error(`Expected at least 1 triggers`); + } + + if (!resetButton) { + throw new Error(`Expected at resetButton`); + } + + await userEvent.click(resetButton); + await userEvent.click(triggers); +} diff --git a/stories/components/date-picker/docs/date-picker.stories.tsx b/stories/components/date-picker/docs/date-picker.stories.tsx index 2774764ba8..0c6cd12978 100644 --- a/stories/components/date-picker/docs/date-picker.stories.tsx +++ b/stories/components/date-picker/docs/date-picker.stories.tsx @@ -9,6 +9,7 @@ import { DateRangeComparatorAdvancedTest } from './__tests__/date_range_comparat import { DisabledDatesTest } from './__tests__/disabled_dates.test'; import { MonthRangeComparatorTest } from './__tests__/month_range_comparator.test'; import { MonthRangePickerTest } from './__tests__/month_range_picker.test'; +import { ResetDatePickerTest } from './__tests__/reset_date_picker.test'; import { TriggerAndPopperTest } from './__tests__/trigger_popper.test'; import { WeekPickerTest } from './__tests__/week_picker.test'; import CustomDateRangesExample from './examples/custom_date_ranges'; @@ -20,6 +21,7 @@ import DatepickerExample from './examples/datepicker'; import DisabledDatesExample from './examples/disabled_dates'; import MonthRangeComparatorAdvanceUseExample from './examples/month_range_comparator_advanced_use'; import MonthRangePickerExample from './examples/monthrangepicker'; +import ResetDatePickerExample from './examples/reset_date_picker'; import TriggerAndPopperExample from './examples/trigger_and_popper'; import WeekPickerExample from './examples/week_picker'; import { playWrapper } from '../../../utils/playWrapper'; @@ -35,6 +37,12 @@ export const CustomDateRanges: StoryObj = { }; +export const ResetDatePicker: StoryObj = { + render: ResetDatePickerExample, + play: playWrapper(ResetDatePickerTest), + +}; + export const CustomDay: StoryObj = { render: CustomDayExample, play: playWrapper(CustomDaysTest), diff --git a/stories/components/date-picker/docs/examples/reset_date_picker.tsx b/stories/components/date-picker/docs/examples/reset_date_picker.tsx new file mode 100644 index 0000000000..145870909e --- /dev/null +++ b/stories/components/date-picker/docs/examples/reset_date_picker.tsx @@ -0,0 +1,27 @@ +import { Flex } from '@semcore/ui/base-components'; +import Button from '@semcore/ui/button'; +import type { DateConstructorParams } from '@semcore/ui/date-picker'; +import { DatePicker } from '@semcore/ui/date-picker'; +import { Text } from '@semcore/ui/typography'; +import React from 'react'; + +const Demo = () => { + const [value, setValue] = React.useState(new Date('06/29/2020')); + + return ( + + + Date picker with reset + + + setValue(date)}> + + + + + + + ); +}; + +export default Demo; diff --git a/website/docs/components/date-picker/date-picker-code.md b/website/docs/components/date-picker/date-picker-code.md index 5258f9ce48..2e6a383b60 100644 --- a/website/docs/components/date-picker/date-picker-code.md +++ b/website/docs/components/date-picker/date-picker-code.md @@ -88,6 +88,18 @@ Date ranges may be customized or switched off at all, by transferring `periods={ ::: +## Reset date + +To reset the date, set `value` to an empty string. + +::: sandbox + + + +::: + ## Week picker You can manually select a custom period, if needed (for example, a week) by taking all the control in manual mode. For example, you can create the WeekPeaker using DateRangePicker. diff --git a/website/docs/get-started-guide/dev-starter-guide/dev-starter-guide.md b/website/docs/get-started-guide/dev-starter-guide/dev-starter-guide.md index 8d4ebf12e4..4a10f5eba6 100644 --- a/website/docs/get-started-guide/dev-starter-guide/dev-starter-guide.md +++ b/website/docs/get-started-guide/dev-starter-guide/dev-starter-guide.md @@ -76,11 +76,15 @@ By default, our components work in uncontrolled mode. Once you provide a value a ::: tip This logic is similar to the [native input](https://reactjs.org/docs/forms.html#controlled-components) behavior, where you control the value and the `onChange` serves as a request for change. In this case, it's up to you whether to change the value or not. -The handlers for these types of properties follow a specific notation: `on{ eventName }Change`. +The handlers for these types of properties follow a specific notation: `on{eventName}Change`. ::: If you choose not to set these properties, the component will operate in an uncontrolled mode. Furthermore, all properties that can be changed have an initial state located in the `default + { Property name }` property, which can be modified by assigning a different value. For example, if a tooltip has a `visible` property that is closed by default, you can set the `defaultVisible={true}` value to have it initially open. +::: tip +Some `value` types are optional—meaning you can omit them entirely to keep the component in uncontrolled mode. However, their type might not include `undefined` as a valid value type. In that case explicitly passing `undefined` may lead to unexpected component behavior. +::: + ### Handlers Consistency is crucial for a library as it ensures predictability. In our library, all event handlers follow the same format: