refactor(date): updated errorMessage story and modified to import props (#3112)

* refactor(date): updated errorMessage story and modified to import props

* docs(date): add errorMessageFunction examples

* chore: add changeset

* fix: remove unnecessary props

* fix: typo
This commit is contained in:
Ryo Matsukawa 2024-06-15 09:00:11 +09:00 committed by GitHub
parent 3da81494c3
commit df0126f93f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 243 additions and 18 deletions

View File

@ -0,0 +1,6 @@
---
"@nextui-org/date-input": patch
"@nextui-org/date-picker": patch
---
chore(date): update errorMessageFunction story and docs for date libraries

View File

@ -0,0 +1,30 @@
const App = `import {DateInput} from "@nextui-org/react";
import {CalendarDate, parseDate} from "@internationalized/date";
export default function App() {
return (
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
<DateInput
label={"Birth date"}
defaultValue={parseDate("2024-04-04")}
placeholderValue={new CalendarDate(1995, 11, 6)}
description={"This is my birth date."}
isInvalid
errorMessage={(value) => {
if (value.isInvalid) {
return "Please enter a valid date.";
}
}}
className="max-w-xs"
/>
</div>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -7,6 +7,7 @@ import labelPlacements from "./label-placements";
import description from "./description";
import startEndContent from "./start-end-content";
import errorMessage from "./error-message";
import errorMessageFunction from "./error-message-function";
import controlled from "./controlled";
import timeZones from "./time-zones";
import granularity from "./granularity";
@ -25,6 +26,7 @@ export const dateInputContent = {
description,
startEndContent,
errorMessage,
errorMessageFunction,
controlled,
timeZones,
granularity,

View File

@ -0,0 +1,26 @@
const App = `import {DatePicker} from "@nextui-org/react";
export default function App() {
return (
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
<DatePicker
label="Birth date"
className="max-w-[284px]"
isInvalid
errorMessage={(value) => {
if (value.isInvalid) {
return "Please enter a valid date.";
}
}}
/>
</div>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -6,6 +6,7 @@ import variants from "./variants";
import labelPlacements from "./label-placements";
import description from "./description";
import errorMessage from "./error-message";
import errorMessageFunction from "./error-message-function";
import withMonthAndYearPickers from "./with-month-and-year-pickers";
import withTimeField from "./with-time-field";
import selectorIcon from "./selector-icon";
@ -28,6 +29,7 @@ export const datePickerContent = {
labelPlacements,
description,
errorMessage,
errorMessageFunction,
withMonthAndYearPickers,
withTimeField,
selectorIcon,

View File

@ -0,0 +1,30 @@
const App = `import {DateRangePicker} from "@nextui-org/react";
import {parseDate} from "@internationalized/date";
export default function App() {
return (
<DateRangePicker
isInvalid
label="Stay duration"
variant="bordered"
errorMessage={(value) => {
if (value.isInvalid) {
return "Please enter your stay duration";
}
}}
defaultValue={{
start: parseDate("2024-04-01"),
end: parseDate("2024-04-08"),
}}
className="max-w-xs"
/>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -6,6 +6,7 @@ import variants from "./variants";
import labelPlacements from "./label-placements";
import description from "./description";
import errorMessage from "./error-message";
import errorMessageFunction from "./error-message-function";
import withTimeField from "./with-time-field";
import selectorIcon from "./selector-icon";
import controlled from "./controlled";
@ -28,6 +29,7 @@ export const dateRangePickerContent = {
labelPlacements,
description,
errorMessage,
errorMessageFunction,
withTimeField,
selectorIcon,
controlled,

View File

@ -0,0 +1,23 @@
const App = `import {TimeInput} from "@nextui-org/react";
export default function App() {
return (
<TimeInput
label="Event Time"
isInvalid
errorMessage={(value) => {
if (value.isInvalid) {
return "Please enter a valid time";
}
}}
/>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -0,0 +1,19 @@
const App = `import {TimeInput} from "@nextui-org/react";
export default function App() {
return (
<TimeInput
label="Event Time"
isInvalid
errorMessage="Please enter a valid time"
/>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -4,6 +4,8 @@ import disabled from "./disabled";
import readonly from "./read-only";
import withoutLabel from "./without-label";
import withDescription from "./with-description";
import errorMessage from "./error-message";
import errorMessageFunction from "./error-message-function";
import labelPlacement from "./label-placement";
import startContent from "./start-content";
import endContent from "./end-content";
@ -23,6 +25,8 @@ export const timeInputContent = {
readonly,
withoutLabel,
withDescription,
errorMessage,
errorMessageFunction,
labelPlacement,
startContent,
endContent,

View File

@ -84,6 +84,10 @@ You can combine the `isInvalid` and `errorMessage` properties to show an invalid
<CodeDemo title="With Error Message" files={dateInputContent.errorMessage} />
You can also pass an error message as a function. This allows for dynamic error message handling based on the [ValidationResult]((https://github.com/adobe/react-spectrum/blob/1cacbf1d438675feb3859fee54b17e620b458d9c/packages/%40react-types/shared/src/inputs.d.ts#L44-L51)).
<CodeDemo title="With Error Message Function" files={dateInputContent.errorMessageFunction} />
### Controlled
You can use the `value` and `onChange` properties to control the input value.

View File

@ -77,6 +77,10 @@ You can combine the `isInvalid` and `errorMessage` properties to show an invalid
<CodeDemo title="With Error Message" files={datePickerContent.errorMessage} />
You can also pass an error message as a function. This allows for dynamic error message handling based on the [ValidationResult]((https://github.com/adobe/react-spectrum/blob/1cacbf1d438675feb3859fee54b17e620b458d9c/packages/%40react-types/shared/src/inputs.d.ts#L44-L51)).
<CodeDemo title="With Error Message Function" files={datePickerContent.errorMessageFunction} />
### With Month and Year Pickers
<CodeDemo title="With Month and Year Pickers" files={datePickerContent.withMonthAndYearPickers} />

View File

@ -92,6 +92,10 @@ You can combine the `isInvalid` and `errorMessage` properties to show an invalid
<CodeDemo title="With Error Message" files={dateRangePickerContent.errorMessage} />
You can also pass an error message as a function. This allows for dynamic error message handling based on the [ValidationResult]((https://github.com/adobe/react-spectrum/blob/1cacbf1d438675feb3859fee54b17e620b458d9c/packages/%40react-types/shared/src/inputs.d.ts#L44-L51)).
<CodeDemo title="With Error Message Function" files={dateRangePickerContent.errorMessageFunction} />
### With Time Fields
DateRangePicker automatically includes time fields when a `CalendarDateTime` or `ZonedDateTime` object is provided as the value.

View File

@ -78,6 +78,17 @@ A description for the field. Provides a hint such as specific requirements for w
<CodeDemo title="With Description" files={timeInputContent.withDescription} />
### With Error Message
You can combine the `isInvalid` and `errorMessage` properties to show an invalid input.
<CodeDemo title="With Error Message" files={timeInputContent.errorMessage} />
You can also pass an error message as a function. This allows for dynamic error message handling based on the [ValidationResult]((https://github.com/adobe/react-spectrum/blob/1cacbf1d438675feb3859fee54b17e620b458d9c/packages/%40react-types/shared/src/inputs.d.ts#L44-L51)).
<CodeDemo title="With Error Message Function" files={timeInputContent.errorMessageFunction} />
### Label Placement
The label's overall position relative to the element it is labeling.

View File

@ -1,21 +1,11 @@
import type {HTMLAttributes, ReactElement, ReactNode} from "react";
import type {GroupDOMAttributes} from "@react-types/shared";
import type {GroupDOMAttributes, HelpTextProps, ValidationResult} from "@react-types/shared";
import {useMemo} from "react";
import {forwardRef} from "@nextui-org/system";
import {dataAttr} from "@nextui-org/shared-utils";
// TODO: Use HelpTextProps from "@react-types/shared"; once we upgrade react-aria packages to the latest version.
export interface ValidationResult {
/** Whether the input value is invalid. */
isInvalid: boolean;
/** The current error messages for the input if it is invalid, otherwise an empty array. */
validationErrors: string[];
/** The native validation details for the input. */
validationDetails: ValidityState;
}
export interface DateInputGroupProps extends ValidationResult {
export interface DateInputGroupProps extends ValidationResult, HelpTextProps {
children?: ReactElement | ReactElement[];
shouldLabelBeOutside?: boolean;
label?: ReactNode;
@ -27,10 +17,6 @@ export interface DateInputGroupProps extends ValidationResult {
labelProps?: HTMLAttributes<HTMLElement>;
descriptionProps?: HTMLAttributes<HTMLElement>;
errorMessageProps?: HTMLAttributes<HTMLElement>;
/** A description for the field. Provides a hint such as specific requirements for what to choose. */
description?: ReactNode;
/** An error message for the field. */
errorMessage?: ReactNode | ((v: ValidationResult) => ReactNode);
}
export const DateInputGroup = forwardRef<"div", DateInputGroupProps>((props, ref) => {

View File

@ -13,6 +13,7 @@ import {
} from "@internationalized/date";
import {CalendarBoldIcon} from "@nextui-org/shared-icons";
import {useDateFormatter, I18nProvider} from "@react-aria/i18n";
import {ValidationResult} from "@react-types/shared";
import {DateInput, DateInputProps} from "../src";
@ -254,10 +255,25 @@ export const WithErrorMessage = {
args: {
...defaultProps,
isInvalid: true,
errorMessage: "Please enter a valid date",
},
};
export const WithErrorMessageFunction = {
render: Template,
args: {
...defaultProps,
isInvalid: true,
errorMessage: (value: ValidationResult) => {
if (value.isInvalid) {
return "Please enter a valid date";
}
},
},
};
export const IsInvalid = {
render: Template,

View File

@ -9,6 +9,7 @@ import {
ZonedDateTime,
} from "@internationalized/date";
import {useDateFormatter} from "@react-aria/i18n";
import {ValidationResult} from "@react-types/shared";
import {TimeInput, TimeInputProps, TimeInputValue as TimeValue} from "../src";
@ -192,6 +193,30 @@ export const WithDescription = {
},
};
export const WithErrorMessage = {
render: Template,
args: {
...defaultProps,
isInvalid: true,
errorMessage: "Please enter a valid time",
},
};
export const WithErrorMessageFunction = {
render: Template,
args: {
...defaultProps,
isInvalid: true,
errorMessage: (value: ValidationResult) => {
if (value.isInvalid) {
return "Please enter a valid date";
}
},
},
};
export const LabelPlacement = {
render: LabelPlacementTemplate,

View File

@ -17,6 +17,7 @@ import {I18nProvider, useDateFormatter, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/theme";
import {ValidationResult} from "@react-types/shared";
import {DatePicker, DatePickerProps} from "../src";
@ -424,10 +425,25 @@ export const WithErrorMessage = {
args: {
...defaultProps,
isInvalid: true,
errorMessage: "Please enter a valid date",
},
};
export const WithErrorMessageFunction = {
render: Template,
args: {
...defaultProps,
isInvalid: true,
errorMessage: (value: ValidationResult) => {
if (value.isInvalid) {
return "Please enter a valid date";
}
},
},
};
export const IsInvalid = {
render: Template,

View File

@ -13,7 +13,7 @@ import {
startOfWeek,
today,
} from "@internationalized/date";
import {RangeValue} from "@react-types/shared";
import {RangeValue, ValidationResult} from "@react-types/shared";
import {DateValue} from "@react-types/datepicker";
import {I18nProvider, useDateFormatter, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
@ -499,7 +499,22 @@ export const WithErrorMessage = {
args: {
...defaultProps,
errorMessage: "Please enter your stay duration",
isInvalid: true,
errorMessage: "Please enter a valid date range",
},
};
export const WithErrorMessageFunction = {
render: Template,
args: {
...defaultProps,
isInvalid: true,
errorMessage: (value: ValidationResult) => {
if (value.isInvalid) {
return "Please enter a valid date range";
}
},
},
};