mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
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:
parent
3da81494c3
commit
df0126f93f
6
.changeset/spicy-islands-drum.md
Normal file
6
.changeset/spicy-islands-drum.md
Normal 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
|
||||
@ -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,
|
||||
};
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
};
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
};
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
};
|
||||
19
apps/docs/content/components/time-input/error-message.ts
Normal file
19
apps/docs/content/components/time-input/error-message.ts
Normal 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,
|
||||
};
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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} />
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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) => {
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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";
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user