From c7133f2a3a053269d5aa89a270b1bdae7a82107c Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 25 Mar 2024 17:35:49 -0700 Subject: [PATCH 1/2] Update FieldError so it doesnt render anything if isInvalid is controlled but no error message is provided --- .../react-aria-components/src/FieldError.tsx | 6 ++++- .../stories/TextField.stories.tsx | 26 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/react-aria-components/src/FieldError.tsx b/packages/react-aria-components/src/FieldError.tsx index a2df7238cc5..1e64f6c7124 100644 --- a/packages/react-aria-components/src/FieldError.tsx +++ b/packages/react-aria-components/src/FieldError.tsx @@ -40,9 +40,13 @@ const FieldErrorInner = forwardRef((props: FieldErrorProps, ref: ForwardedRef; }); diff --git a/packages/react-aria-components/stories/TextField.stories.tsx b/packages/react-aria-components/stories/TextField.stories.tsx index e5eb26ee354..cf510617d0d 100644 --- a/packages/react-aria-components/stories/TextField.stories.tsx +++ b/packages/react-aria-components/stories/TextField.stories.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {Input, Label, TextField} from 'react-aria-components'; +import {Button, FieldError, Form, Input, Label, TextField} from 'react-aria-components'; import React from 'react'; export default { @@ -25,3 +25,27 @@ export const TextfieldExample = () => { ); }; + +export const FormExample = (args) => { + return ( +
+ + + + + + + +
+ ); +}; + +FormExample.story = { + argTypes: { + isInvalid: { + control: { + type: 'boolean' + } + } + } +}; From 3a49b3fe7c7e05bdbfe996edf6a903fb086c3a94 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Tue, 26 Mar 2024 16:57:51 -0700 Subject: [PATCH 2/2] adding test and updating story --- .../react-aria-components/example/index.css | 9 ++++++++ .../stories/TextField.stories.tsx | 15 +++++++++---- .../test/TextField.test.js | 22 +++++++++++++++++-- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/packages/react-aria-components/example/index.css b/packages/react-aria-components/example/index.css index 74c4762fa3e..64e6c5c6557 100644 --- a/packages/react-aria-components/example/index.css +++ b/packages/react-aria-components/example/index.css @@ -453,3 +453,12 @@ html { opacity: 0.4; } } + +.textfieldExample { + display: flex; + flex-direction: column; + + .errorMessage { + padding-bottom: 10px; + } +} diff --git a/packages/react-aria-components/stories/TextField.stories.tsx b/packages/react-aria-components/stories/TextField.stories.tsx index cf510617d0d..1fa6a1609a9 100644 --- a/packages/react-aria-components/stories/TextField.stories.tsx +++ b/packages/react-aria-components/stories/TextField.stories.tsx @@ -11,7 +11,9 @@ */ import {Button, FieldError, Form, Input, Label, TextField} from 'react-aria-components'; +import {classNames} from '@react-spectrum/utils'; import React from 'react'; +import styles from '../example/index.css'; export default { title: 'React Aria Components' @@ -26,13 +28,13 @@ export const TextfieldExample = () => { ); }; -export const FormExample = (args) => { +export const TextFieldSubmitExample = (args) => { return (
- + - + @@ -40,12 +42,17 @@ export const FormExample = (args) => { ); }; -FormExample.story = { +TextFieldSubmitExample.story = { argTypes: { isInvalid: { control: { type: 'boolean' } } + }, + parameters: { + description: { + data: 'Non controlled isInvalid should render the default error message (aka just hit submit and see that it appears). Controlled isInvalid=true should not render the error message div (aka no padding should appear between the input and the buttons).' + } } }; diff --git a/packages/react-aria-components/test/TextField.test.js b/packages/react-aria-components/test/TextField.test.js index f0f3bf26b06..52298c66fea 100644 --- a/packages/react-aria-components/test/TextField.test.js +++ b/packages/react-aria-components/test/TextField.test.js @@ -116,7 +116,7 @@ describe('TextField', () => { ); let input = getByRole('textbox'); - + expect(input.closest('.react-aria-TextField')).not.toHaveAttribute('data-readonly'); rerender(); expect(input.closest('.react-aria-TextField')).toHaveAttribute('data-readonly'); @@ -128,7 +128,7 @@ describe('TextField', () => { ); let input = getByRole('textbox'); - + expect(input.closest('.react-aria-TextField')).not.toHaveAttribute('data-required'); rerender(); expect(input.closest('.react-aria-TextField')).toHaveAttribute('data-required'); @@ -176,6 +176,24 @@ describe('TextField', () => { expect(input.closest('.react-aria-TextField')).not.toHaveAttribute('data-invalid'); }); + it('should not render the field error div if no error is provided and isInvalid is true', async () => { + let Component = component; + let {getByRole} = render( + + + + + + + + ); + + let input = getByRole('textbox'); + expect(input).toHaveAttribute('aria-invalid'); + expect(input).toHaveAttribute('data-invalid'); + expect(input).not.toHaveAttribute('aria-describedby'); + }); + it('supports customizing validation errors', async () => { let Component = component; let {getByRole, getByTestId} = render(