-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(many): add new form field error msg style + add asterisk for req…
…uired fields
- Loading branch information
Showing
44 changed files
with
615 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
--- | ||
title: Form Errors | ||
category: Guides | ||
order: 7 | ||
--- | ||
|
||
# Adding Error Messages to Form Components | ||
|
||
InstUI offers a range of form elements and all of them have a similar API to handle error/hint/success messages. These components use the `messages` prop with the following type definition: | ||
|
||
```ts | ||
--- | ||
type: code | ||
--- | ||
type FormMessages = { | ||
type: | ||
| 'newError' | ||
| 'error' | ||
| 'hint' | ||
| 'success' | ||
| 'screenreader-only' | ||
text: React.ReactNode | ||
}[] | ||
``` | ||
So a basic example would look something like this: | ||
```ts | ||
--- | ||
type: example | ||
--- | ||
const PasswordExample = () => { | ||
const [password, setPassword] = useState('') | ||
const messages = password.length < 6 | ||
? [{type: 'newError', text: 'Password have to be at least 6 characters long!'}] | ||
: [] | ||
return ( | ||
<TextInput | ||
renderLabel="Password" | ||
type="password" | ||
messages={messages} | ||
onChange={(event, value) => { setPassword(value) }} | ||
/> | ||
) | ||
} | ||
|
||
render(<PasswordExample/>) | ||
``` | ||
|
||
However you might have noticed from the type definition that a message can be `error` and `newError` type. This is due to compatibility reasons. `error` is the older type and does not meet accessibility requirements, `newError` (hance the name) is the newer and more accessible format. | ||
|
||
We wanted to allow users to start using the new format without making it mandatory, but after the introductory period `newError` will be deprecated and `error` type will be changed to look and behave the same way. | ||
|
||
With this update we also introduced the "required asterisk" which will display an `*` character next to field labels that are required. This update is not opt-in and will apply to **all** InstUI form components so if you we relying on a custom solution for this feature before, you need to remove that to avoid having double asterisks. | ||
|
||
Here are examples with different form components: | ||
|
||
```ts | ||
--- | ||
type: example | ||
--- | ||
const Example = () => { | ||
const [showError, setShowError] = useState(true) | ||
const [showNewError, setShowNewError] = useState(true) | ||
const [showLongError, setShowLongError] = useState(false) | ||
const [isRequired, setIsRequired] = useState(true) | ||
|
||
const messages = showError | ||
? [{type: showNewError ? 'newError' : 'error', text: showLongError ? 'Long error. Lorem ipsum dolor sit amet consectetur adipisicing elit. Dignissimos voluptas, esse commodi eos facilis voluptatibus harum exercitationem. Et magni est consectetur, eveniet veniam unde! Molestiae labore libero sapiente ad ratione.' : 'Short error message'}] | ||
: [] | ||
|
||
const handleSettingsChange = (v) => { | ||
setShowError(v.includes('showError')) | ||
setShowNewError(v.includes('showNewError')) | ||
setShowLongError(v.includes('showLongError')) | ||
setIsRequired(v.includes('isRequired')) | ||
} | ||
|
||
return ( | ||
<div> | ||
<CheckboxGroup | ||
name="errorOptions" | ||
description="Error message options" | ||
onChange={handleSettingsChange} | ||
defaultValue={['showError', 'showNewError', 'isRequired']} | ||
> | ||
<Checkbox label="Show error message" value="showError"/> | ||
<Checkbox label="Use the new error type" value="showNewError" /> | ||
<Checkbox label="Use long message" value="showLongError" /> | ||
<Checkbox label="Make fields required" value="isRequired" /> | ||
</CheckboxGroup> | ||
<div style={{display: 'flex', gap: '2rem', marginTop: '3rem', flexDirection: 'column'}}> | ||
|
||
<TextInput renderLabel="TextInput" messages={messages} isRequired={isRequired}/> | ||
|
||
<NumberInput renderLabel="NumberInput" messages={messages} isRequired={isRequired}/> | ||
|
||
<TextArea messages={messages} label="TextArea" required={isRequired}/> | ||
|
||
<Checkbox label="Checkbox" isRequired={isRequired} messages={messages}/> | ||
|
||
<Checkbox label={`Checkbox (variant="toggle")`} variant="toggle" isRequired={isRequired} messages={messages}/> | ||
|
||
<CheckboxGroup | ||
name="CheckboxGroup" | ||
messages={messages} | ||
description="CheckboxGroup" | ||
> | ||
<Checkbox label="Checkbox 1" value="checkbox1"/> | ||
<Checkbox label="Checkbox 2" value="checkbox2"/> | ||
<Checkbox label="Checkbox 3" value="checkbox3"/> | ||
</CheckboxGroup> | ||
|
||
<RadioInputGroup name="radioInputGroup" description="RadioInputGroup" messages={messages} isRequired={isRequired}> | ||
<RadioInput | ||
label="RadioInput 1" | ||
value="radioInput1" | ||
/> | ||
<RadioInput | ||
label="RadioInput 2" | ||
value="radioInput2" | ||
/> | ||
<RadioInput | ||
label="RadioInput 3" | ||
value="radioInput3" | ||
/> | ||
</RadioInputGroup> | ||
|
||
<FileDrop messages={messages} renderLabel="FileDrop" /> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
render(<Example/>) | ||
``` |
101 changes: 101 additions & 0 deletions
101
packages/__examples__/.storybook/stories/FormErrors.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2015 - present Instructure, Inc. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in all | ||
* copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
* SOFTWARE. | ||
*/ | ||
|
||
import React from 'react' | ||
import { | ||
TextInput, | ||
TextArea, | ||
NumberInput, | ||
Checkbox, | ||
CheckboxGroup, | ||
RadioInput, | ||
RadioInputGroup, | ||
FileDrop, | ||
} from '@instructure/ui' | ||
|
||
function FormErrors() { | ||
const renderForms = ({messages, isRequired}) => { | ||
return ( | ||
<div style={{display: 'flex', gap: '2rem', marginTop: '3rem', flexDirection: 'column'}}> | ||
<TextInput renderLabel="TextInput" messages={messages} isRequired={isRequired}/> | ||
<NumberInput renderLabel="NumberInput" messages={messages} isRequired={isRequired}/> | ||
<TextArea messages={messages} label="TextArea" required={isRequired}/> | ||
<Checkbox label="Checkbox" isRequired={isRequired} messages={messages}/> | ||
<Checkbox label={`Checkbox (variant="toggle")`} variant="toggle" isRequired={isRequired} messages={messages}/> | ||
<CheckboxGroup | ||
name="CheckboxGroup" | ||
messages={messages} | ||
description="CheckboxGroup" | ||
> | ||
<Checkbox label="Checkbox 1" value="checkbox1"/> | ||
<Checkbox label="Checkbox 2" value="checkbox2"/> | ||
<Checkbox label="Checkbox 3" value="checkbox3"/> | ||
</CheckboxGroup> | ||
<RadioInputGroup name="radioInputGroup" description="RadioInputGroup" messages={messages} isRequired={isRequired}> | ||
<RadioInput | ||
label="RadioInput 1" | ||
value="radioInput1" | ||
/> | ||
<RadioInput | ||
label="RadioInput 2" | ||
value="radioInput2" | ||
/> | ||
<RadioInput | ||
label="RadioInput 3" | ||
value="radioInput3" | ||
/> | ||
</RadioInputGroup> | ||
<FileDrop messages={messages} renderLabel="FileDrop" /> | ||
</div> | ||
) | ||
} | ||
|
||
const exampleMessage = [{ type: 'newError', text: 'Long error. Lorem ipsum dolor sit amet consectetur adipisicing elit. Dignissimos voluptas, esse commodi eos facilis voluptatibus harum exercitationem. Et magni est consectetur, eveniet veniam unde! Molestiae labore libero sapiente ad ratione.' }] | ||
|
||
const formOptions = [ | ||
{ | ||
messages: exampleMessage, | ||
isRequired: true | ||
}, | ||
{ | ||
messages: exampleMessage, | ||
isRequired: false | ||
}, | ||
{ | ||
messages: [], | ||
isRequired: true | ||
}, | ||
{ | ||
messages: [], | ||
isRequired: false | ||
}, | ||
] | ||
return ( | ||
<div> | ||
{formOptions.map((option) => renderForms(option))} | ||
</div> | ||
) | ||
} | ||
|
||
export default FormErrors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.