diff --git a/packages/ui-date-input/src/DateInput2/README.md b/packages/ui-date-input/src/DateInput2/README.md
index 0d0554c0d0..f9b383c1e5 100644
--- a/packages/ui-date-input/src/DateInput2/README.md
+++ b/packages/ui-date-input/src/DateInput2/README.md
@@ -1,5 +1,5 @@
---
-describes: DateInput
+describes: DateInput2
---
This component is an updated version of [`DateInput`](/#DateInput) that's easier to configure for developers, has a better UX, better accessibility features and a year picker. We recommend using this instead of `DateInput` which will be deprecated in the future.
@@ -74,7 +74,7 @@ This component is an updated version of [`DateInput`](/#DateInput) that's easier
invalidDateErrorMessage="Invalid date"
withYearPicker={{
screenReaderLabel: 'Year picker',
- startYear: 1999,
+ startYear: 1900,
endYear: 2024
}}
/>
@@ -103,7 +103,7 @@ This component is an updated version of [`DateInput`](/#DateInput) that's easier
invalidDateErrorMessage="Invalid date"
withYearPicker={{
screenReaderLabel: 'Year picker',
- startYear: 1999,
+ startYear: 1900,
endYear: 2024
}}
/>
@@ -112,3 +112,54 @@ This component is an updated version of [`DateInput`](/#DateInput) that's easier
render()
```
+
+### With custom validation
+
+```js
+---
+type: example
+---
+const Example = () => {
+ const [value, setValue] = useState('')
+ const [messages, setMessages] = useState([])
+
+ const handleDateValidation = (dateString, isValidDate) => {
+ if (!isValidDate) {
+ setMessages([{
+ type: 'error',
+ text: 'This is not a valid date'
+ }])
+ } else if (new Date(dateString) < new Date('January 1, 1900')) {
+ setMessages([{
+ type: 'error',
+ text: 'Use date after January 1, 1900'
+ }])
+ } else {
+ setMessages([])
+ }
+ }
+
+ return (
+ setValue(value)}
+ withYearPicker={{
+ screenReaderLabel: 'Year picker',
+ startYear: 1900,
+ endYear: 2024
+ }}
+ />
+ )
+}
+
+render()
+```
diff --git a/packages/ui-date-input/src/DateInput2/index.tsx b/packages/ui-date-input/src/DateInput2/index.tsx
index a311a28b55..a66ae4e80a 100644
--- a/packages/ui-date-input/src/DateInput2/index.tsx
+++ b/packages/ui-date-input/src/DateInput2/index.tsx
@@ -56,17 +56,7 @@ function isValidMomentDate(
return moment
.tz(
dateString,
- [
- moment.ISO_8601,
- 'llll',
- 'LLLL',
- 'lll',
- 'LLL',
- 'll',
- 'LL',
- 'l',
- 'L'
- ],
+ [moment.ISO_8601, 'llll', 'LLLL', 'lll', 'LLL', 'll', 'LL', 'l', 'L'],
locale,
true,
timezone
@@ -92,6 +82,7 @@ const DateInput2 = ({
onChange,
onBlur,
withYearPicker,
+ onRequestValidateDate,
invalidDateErrorMessage,
locale,
timezone,
@@ -145,14 +136,16 @@ const DateInput2 = ({
setInputMessages(messages || [])
return true
}
- if (!onlyRemoveError) {
- setInputMessages([
+ if (!onlyRemoveError && typeof invalidDateErrorMessage === 'string') {
+ setInputMessages((messages) => [
{
type: 'error',
- text: invalidDateErrorMessage || '',
- }
+ text: invalidDateErrorMessage
+ },
+ ...messages
])
}
+
return false
}
@@ -176,17 +169,18 @@ const DateInput2 = ({
}
const handleBlur = (e: SyntheticEvent) => {
- onBlur?.(e)
const isInputValid = validateInput(false)
if (isInputValid && value) {
- const formattedDate = new Date(value).toLocaleDateString(getLocale(), {
- month: 'long',
- year: 'numeric',
- day: 'numeric',
- timeZone: getTimezone()
- })
- handleInputChange(e, formattedDate)
+ const formattedDate = new Date(value).toLocaleDateString(getLocale(), {
+ month: 'long',
+ year: 'numeric',
+ day: 'numeric',
+ timeZone: getTimezone()
+ })
+ handleInputChange(e, formattedDate)
}
+ onRequestValidateDate?.(value, isInputValid)
+ onBlur?.(e)
}
return (
diff --git a/packages/ui-date-input/src/DateInput2/props.ts b/packages/ui-date-input/src/DateInput2/props.ts
index 543eec034b..186fd5466d 100644
--- a/packages/ui-date-input/src/DateInput2/props.ts
+++ b/packages/ui-date-input/src/DateInput2/props.ts
@@ -99,7 +99,18 @@ type DateInput2Props = {
*/
onRequestHideCalendar?: (event: SyntheticEvent) => void
/**
- * The message shown to the user when the date is invalid.
+ * Callback fired when the input is blurred. Feedback should be provided
+ * to the user when this function is called if the selected date or input
+ * value is invalid. The component has an internal check whether the date can
+ * be parsed to a valid date.
+ */
+ onRequestValidateDate?: (
+ value?: string,
+ internalValidationPassed?: boolean
+ ) => void | FormMessage[]
+ /**
+ * The message shown to the user when the date is invalid. If this prop is not set, validation is bypassed.
+ * If it's set to an empty string, validation happens and the input border changes to red if validation hasn't passed.
**/
invalidDateErrorMessage?: string
/**
@@ -165,6 +176,7 @@ const propTypes: PropValidators = {
messages: PropTypes.arrayOf(FormPropTypes.message),
onRequestShowCalendar: PropTypes.func,
onRequestHideCalendar: PropTypes.func,
+ onRequestValidateDate: PropTypes.func,
invalidDateErrorMessage: PropTypes.oneOfType([
PropTypes.func,
PropTypes.string
diff --git a/packages/ui-text-input/src/TextInput/styles.ts b/packages/ui-text-input/src/TextInput/styles.ts
index bb84c43e09..3bd79c1f5c 100644
--- a/packages/ui-text-input/src/TextInput/styles.ts
+++ b/packages/ui-text-input/src/TextInput/styles.ts
@@ -220,6 +220,11 @@ const generateStyle = (
...flexBase
},
afterElement: {
+ // TODO this is added for the case when there is an IconButton inside a TextInput (like in the DateInput2 component)
+ // and the button size makes the whole input 2px larger (because of the borders)
+ // this is not the best solution and in the long term we should work with the design team to figure out how to handle such cases
+ marginTop: '-1px',
+ marginBottom: '-1px',
label: 'textInput__afterElement',
...flexItemBase,
paddingInlineEnd: componentTheme.padding,