From 106cd0f32b3b7ff48097ecf68f27f567252aa217 Mon Sep 17 00:00:00 2001 From: Maja Zarkova Date: Thu, 31 Oct 2024 15:39:06 +0200 Subject: [PATCH 1/6] Add successMessage to useCustomValidity composable --- .../src/composables/useCustomValidity.ts | 59 +++++++++++++------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/packages/sit-onyx/src/composables/useCustomValidity.ts b/packages/sit-onyx/src/composables/useCustomValidity.ts index 7b70686bd6..9d408ca8d8 100644 --- a/packages/sit-onyx/src/composables/useCustomValidity.ts +++ b/packages/sit-onyx/src/composables/useCustomValidity.ts @@ -6,13 +6,17 @@ import type { BaseSelectOption } from "../types"; import { areObjectsFlatEqual } from "../utils/objects"; import { getFirstInvalidType, transformValidityStateToObject } from "../utils/validity"; -export type CustomErrorType = string | FormErrorMessages; +export type CustomMessageType = string | FormMessages; export type CustomValidityProp = { /** * Custom error message to show. Will only show up after the user has interacted with the input. */ - customError?: CustomErrorType; + customError?: CustomMessageType; + /** + * Custom success message to show. Will only show up after the user has interacted with the input. + */ + customSuccess?: CustomMessageType; }; export type UseCustomValidityOptions = { @@ -45,39 +49,38 @@ export const TRANSLATED_INPUT_TYPES = Object.keys( export type TranslatedInputType = (typeof TRANSLATED_INPUT_TYPES)[number]; /** - * Translated error messages that inform about causes for invalidity of form components + * Translated messages that inform about the validity state of form components */ -export type FormErrorMessages = { +export type FormMessages = { /** - * A short error message preview to inform the user about the cause of the error + * A short message preview to inform the user about the validity state */ shortMessage: string; /** - * An extended informative error message to provide more info - * how the error cause can be resolved + * An extended informative message to provide more info */ longMessage?: string; }; /** - * Transforms a customError into the format needed to display an error preview and extended message + * Transforms a customMessage into the format needed to display an error preview and extended message */ -export const getCustomErrors = (customError?: CustomErrorType): FormErrorMessages | undefined => { - if (!customError) return; - if (typeof customError === "string") { +export const getCustomMessages = (customMessage?: CustomMessageType): FormMessages | undefined => { + if (!customMessage) return; + if (typeof customMessage === "string") { // we can't guarantee a custom error message will be short, // so in case it overflows, by adding it to "longMessage", // it will still be visible in a tooltip - return { shortMessage: customError, longMessage: customError }; + return { shortMessage: customMessage, longMessage: customMessage }; } - return customError; + return customMessage; }; /** - * Returns a string combining short + long message or just the customError if it was provided as single string. + * Returns a string combining short + long message or just the customMessage if it was provided as single string. * Will be used e.g. for customInvalidity and showing a tooltip e.g. in RadioButtons */ -export const getCustomErrorText = (customError?: CustomErrorType): string | undefined => { +export const getCustomText = (customError?: CustomMessageType): string | undefined => { if (!customError) return; if (typeof customError === "string") { return customError; @@ -128,7 +131,7 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { /** * Sync custom error with the native input validity. */ - watchEffect(() => el.setCustomValidity(getCustomErrorText(options.props.customError) ?? "")); + watchEffect(() => el.setCustomValidity(getCustomText(options.props.customError) ?? "")); watch( // we need to watch all props instead of only modelValue so the validity is re-checked @@ -166,11 +169,11 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { }, } satisfies Directive; - const errorMessages = computed(() => { + const errorMessages = computed(() => { if (!validityState.value || validityState.value.valid) return; const errorType = getFirstInvalidType(validityState.value); - const customErrors = getCustomErrors(options.props.customError); + const customErrors = getCustomMessages(options.props.customError); // a custom error message always is considered first if (customErrors || errorType === "customError") { if (!customErrors) return; @@ -207,6 +210,22 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { }; }); + const successMessages = computed(() => { + if (validityState.value === undefined || !validityState.value.valid) return; + + const errorType = getFirstInvalidType(validityState.value); + const customErrors = getCustomMessages(options.props.customError); + + // a custom error message always is considered first + if (customErrors || errorType === "customError") { + if (customErrors) return; + } + + const customSuccess = getCustomMessages(options.props.customSuccess); + + return customSuccess; + }); + return { /** * Directive to set the custom error message and emit validityChange event. @@ -216,5 +235,9 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { * A custom error or the default translation of the first invalid state if one exists. */ errorMessages, + /** + * A custom success message if provided by the user. + */ + successMessages, }; }; From db4fe5feb65d677d2c3ceb9bed3d15732659a39b Mon Sep 17 00:00:00 2001 From: Maja Zarkova Date: Thu, 31 Oct 2024 16:45:13 +0200 Subject: [PATCH 2/6] Adjust comments --- packages/sit-onyx/src/composables/useCustomValidity.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sit-onyx/src/composables/useCustomValidity.ts b/packages/sit-onyx/src/composables/useCustomValidity.ts index 9d408ca8d8..d7363c3359 100644 --- a/packages/sit-onyx/src/composables/useCustomValidity.ts +++ b/packages/sit-onyx/src/composables/useCustomValidity.ts @@ -68,7 +68,7 @@ export type FormMessages = { export const getCustomMessages = (customMessage?: CustomMessageType): FormMessages | undefined => { if (!customMessage) return; if (typeof customMessage === "string") { - // we can't guarantee a custom error message will be short, + // we can't guarantee a custom message will be short, // so in case it overflows, by adding it to "longMessage", // it will still be visible in a tooltip return { shortMessage: customMessage, longMessage: customMessage }; @@ -93,7 +93,7 @@ export const getCustomText = (customError?: CustomMessageType): string | undefin }; /** - * Composable for unified handling of custom error messages for form components. + * Composable for unified handling of custom messages for form components. * Will call `setCustomValidity()` accordingly and emit the "validityChange" event * whenever the input value / error changes. * From 4eb2b8ec1882e0540183b267355c8cde0a91fec3 Mon Sep 17 00:00:00 2001 From: Maja Zarkova Date: Thu, 31 Oct 2024 16:57:27 +0200 Subject: [PATCH 3/6] Fix errors --- .../src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue b/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue index d819a65c68..146ceb5483 100644 --- a/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue +++ b/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue @@ -1,6 +1,6 @@ From a12409688ee51fa589cd4321f29e64860377f5af Mon Sep 17 00:00:00 2001 From: Maja Zarkova Date: Fri, 1 Nov 2024 09:59:25 +0200 Subject: [PATCH 4/6] Fix errors --- packages/sit-onyx/src/components/OnyxFormElement/types.ts | 4 ++-- packages/sit-onyx/src/components/OnyxInput/OnyxInput.ct.tsx | 4 ++-- packages/sit-onyx/src/components/OnyxSelect/OnyxSelect.ct.tsx | 4 ++-- .../sit-onyx/src/components/OnyxStepper/OnyxStepper.ct.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/sit-onyx/src/components/OnyxFormElement/types.ts b/packages/sit-onyx/src/components/OnyxFormElement/types.ts index e7528184ed..55bd186f30 100644 --- a/packages/sit-onyx/src/components/OnyxFormElement/types.ts +++ b/packages/sit-onyx/src/components/OnyxFormElement/types.ts @@ -1,5 +1,5 @@ import type { RequiredMarkerProp } from "../../composables/required"; -import type { FormErrorMessages } from "../../composables/useCustomValidity"; +import type { FormMessages } from "../../composables/useCustomValidity"; export type OnyxFormElementProps = RequiredMarkerProp & { /** @@ -40,7 +40,7 @@ export type OnyxFormElementProps = RequiredMarkerProp & { /** * Error messages that inform about causes for invalidity of form components */ - errorMessages?: FormErrorMessages; + errorMessages?: FormMessages; /** * Maximum number of characters that are allowed to be entered. * Warning: when the value is (pre)set programmatically, diff --git a/packages/sit-onyx/src/components/OnyxInput/OnyxInput.ct.tsx b/packages/sit-onyx/src/components/OnyxInput/OnyxInput.ct.tsx index 14e720caf0..a6730dbfb6 100644 --- a/packages/sit-onyx/src/components/OnyxInput/OnyxInput.ct.tsx +++ b/packages/sit-onyx/src/components/OnyxInput/OnyxInput.ct.tsx @@ -1,5 +1,5 @@ import { DENSITIES } from "../../composables/density"; -import type { FormErrorMessages } from "../../composables/useCustomValidity"; +import type { FormMessages } from "../../composables/useCustomValidity"; import { expect, test } from "../../playwright/a11y"; import { executeMatrixScreenshotTest } from "../../playwright/screenshots"; import { createFormElementUtils } from "../OnyxFormElement/OnyxFormElement.ct-utils"; @@ -108,7 +108,7 @@ test.describe("Screenshot tests", () => { const message = showLongMessage ? "Very long message that should be truncated" : "Test message"; - const errorMessages: FormErrorMessages = { + const errorMessages: FormMessages = { shortMessage: showLongMessage ? "Very long error preview that should be truncated" : "Test error", diff --git a/packages/sit-onyx/src/components/OnyxSelect/OnyxSelect.ct.tsx b/packages/sit-onyx/src/components/OnyxSelect/OnyxSelect.ct.tsx index 06202691a5..a86646fac8 100644 --- a/packages/sit-onyx/src/components/OnyxSelect/OnyxSelect.ct.tsx +++ b/packages/sit-onyx/src/components/OnyxSelect/OnyxSelect.ct.tsx @@ -1,7 +1,7 @@ import type { MountResultJsx } from "@playwright/experimental-ct-vue"; import { comboboxSelectOnlyTesting, comboboxTesting } from "@sit-onyx/headless/playwright"; import { DENSITIES } from "../../composables/density"; -import type { FormErrorMessages } from "../../composables/useCustomValidity"; +import type { FormMessages } from "../../composables/useCustomValidity"; import { expect, test } from "../../playwright/a11y"; import { adjustAbsolutePositionScreenshot, @@ -315,7 +315,7 @@ test.describe("Invalidity handling screenshots", () => { const message = showLongMessage ? "Very long message that should be truncated" : "Test message"; - const errorMessages: FormErrorMessages = { + const errorMessages: FormMessages = { shortMessage: showLongMessage ? "Very long error preview that should be truncated" : "Test error", diff --git a/packages/sit-onyx/src/components/OnyxStepper/OnyxStepper.ct.tsx b/packages/sit-onyx/src/components/OnyxStepper/OnyxStepper.ct.tsx index 2b66d28bad..4d1a6c56dd 100644 --- a/packages/sit-onyx/src/components/OnyxStepper/OnyxStepper.ct.tsx +++ b/packages/sit-onyx/src/components/OnyxStepper/OnyxStepper.ct.tsx @@ -1,5 +1,5 @@ import { DENSITIES } from "../../composables/density"; -import type { FormErrorMessages } from "../../composables/useCustomValidity"; +import type { FormMessages } from "../../composables/useCustomValidity"; import { expect, test } from "../../playwright/a11y"; import { executeMatrixScreenshotTest } from "../../playwright/screenshots"; import { createFormElementUtils } from "../OnyxFormElement/OnyxFormElement.ct-utils"; @@ -100,7 +100,7 @@ test.describe("Screenshot tests", () => { const message = showLongMessage ? "Very long message that should be truncated" : "Test message"; - const errorMessages: FormErrorMessages = { + const errorMessages: FormMessages = { shortMessage: showLongMessage ? "Very long error preview that should be truncated" : "Test error", From a0d5a8fc7a85374cdb2fd483ed1123f66b9a8343 Mon Sep 17 00:00:00 2001 From: Maja Zarkova Date: Mon, 4 Nov 2024 13:42:51 +0200 Subject: [PATCH 5/6] Apply review feedback --- .../OnyxErrorTooltip/OnyxErrorTooltip.vue | 4 ++-- .../src/composables/useCustomValidity.ts | 22 ++++++------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue b/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue index 146ceb5483..158743db30 100644 --- a/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue +++ b/packages/sit-onyx/src/components/OnyxErrorTooltip/OnyxErrorTooltip.vue @@ -1,6 +1,6 @@ diff --git a/packages/sit-onyx/src/composables/useCustomValidity.ts b/packages/sit-onyx/src/composables/useCustomValidity.ts index d7363c3359..7a9b6d933e 100644 --- a/packages/sit-onyx/src/composables/useCustomValidity.ts +++ b/packages/sit-onyx/src/composables/useCustomValidity.ts @@ -16,7 +16,7 @@ export type CustomValidityProp = { /** * Custom success message to show. Will only show up after the user has interacted with the input. */ - customSuccess?: CustomMessageType; + customMessage?: CustomMessageType; }; export type UseCustomValidityOptions = { @@ -65,7 +65,7 @@ export type FormMessages = { /** * Transforms a customMessage into the format needed to display an error preview and extended message */ -export const getCustomMessages = (customMessage?: CustomMessageType): FormMessages | undefined => { +export const getFormMessages = (customMessage?: CustomMessageType): FormMessages | undefined => { if (!customMessage) return; if (typeof customMessage === "string") { // we can't guarantee a custom message will be short, @@ -80,7 +80,7 @@ export const getCustomMessages = (customMessage?: CustomMessageType): FormMessag * Returns a string combining short + long message or just the customMessage if it was provided as single string. * Will be used e.g. for customInvalidity and showing a tooltip e.g. in RadioButtons */ -export const getCustomText = (customError?: CustomMessageType): string | undefined => { +export const getFormMessageText = (customError?: CustomMessageType): string | undefined => { if (!customError) return; if (typeof customError === "string") { return customError; @@ -131,7 +131,7 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { /** * Sync custom error with the native input validity. */ - watchEffect(() => el.setCustomValidity(getCustomText(options.props.customError) ?? "")); + watchEffect(() => el.setCustomValidity(getFormMessageText(options.props.customError) ?? "")); watch( // we need to watch all props instead of only modelValue so the validity is re-checked @@ -173,7 +173,7 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { if (!validityState.value || validityState.value.valid) return; const errorType = getFirstInvalidType(validityState.value); - const customErrors = getCustomMessages(options.props.customError); + const customErrors = getFormMessages(options.props.customError); // a custom error message always is considered first if (customErrors || errorType === "customError") { if (!customErrors) return; @@ -213,17 +213,9 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { const successMessages = computed(() => { if (validityState.value === undefined || !validityState.value.valid) return; - const errorType = getFirstInvalidType(validityState.value); - const customErrors = getCustomMessages(options.props.customError); - - // a custom error message always is considered first - if (customErrors || errorType === "customError") { - if (customErrors) return; - } - - const customSuccess = getCustomMessages(options.props.customSuccess); + const customMessage = getFormMessages(options.props.customMessage); - return customSuccess; + return customMessage; }); return { From ad7acfecb4606e3851bd7dd669310ba17713eb52 Mon Sep 17 00:00:00 2001 From: Maja Zarkova Date: Mon, 4 Nov 2024 15:14:39 +0200 Subject: [PATCH 6/6] Apply code suggestions --- packages/sit-onyx/src/composables/useCustomValidity.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/sit-onyx/src/composables/useCustomValidity.ts b/packages/sit-onyx/src/composables/useCustomValidity.ts index 7a9b6d933e..1d49a38706 100644 --- a/packages/sit-onyx/src/composables/useCustomValidity.ts +++ b/packages/sit-onyx/src/composables/useCustomValidity.ts @@ -14,9 +14,9 @@ export type CustomValidityProp = { */ customError?: CustomMessageType; /** - * Custom success message to show. Will only show up after the user has interacted with the input. + * Success message to show. Will only show up after the user has interacted with the input. */ - customMessage?: CustomMessageType; + successMessage?: CustomMessageType; }; export type UseCustomValidityOptions = { @@ -213,9 +213,7 @@ export const useCustomValidity = (options: UseCustomValidityOptions) => { const successMessages = computed(() => { if (validityState.value === undefined || !validityState.value.valid) return; - const customMessage = getFormMessages(options.props.customMessage); - - return customMessage; + return getFormMessages(options.props.successMessage); }); return {