Skip to content

Commit

Permalink
feat(Forms): add Form.InfoOverlay to display error, success (receip…
Browse files Browse the repository at this point in the history
…t), or custom messages to users (#4357)

PR
[Preview](https://eufemia-git-feat-forms-status-eufemia.vercel.app/uilib/extensions/forms/Form/InfoOverlay/).

---------

Co-authored-by: Anders <[email protected]>
  • Loading branch information
tujoworker and langz authored Dec 6, 2024
1 parent e6e08b2 commit 9dd8402
Show file tree
Hide file tree
Showing 19 changed files with 1,098 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@dnb/eufemia/src'
import { Provider } from '@dnb/eufemia/src/shared'

export const GlobalStatusError = () => (
export const GlobalInfoOverlayError = () => (
<ComponentBox data-visual-test="global-status">
<GlobalStatus
title="Custom Title"
Expand Down Expand Up @@ -66,7 +66,7 @@ export const GlobalStatusWarning = () => (
</ComponentBox>
)

export const GlobalStatusSuccess = () => (
export const GlobalInfoOverlaySuccess = () => (
<ComponentBox>
<GlobalStatus
state="success"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ showTabs: true
---

import {
GlobalStatusError,
GlobalInfoOverlayError,
GlobalStatusInfo,
GlobalStatusWarning,
GlobalStatusSuccess,
GlobalInfoOverlaySuccess,
GlobalStatusUpdate,
GlobalStatusCoupling,
GlobalStatusAddRemoveItems,
Expand All @@ -19,7 +19,7 @@ import {

**NB:** Keep in mind, the `items` are handled automatically by all form components! This is just an example of how to define the content manually.

<GlobalStatusError />
<GlobalInfoOverlayError />

### GlobalStatus displaying info status

Expand All @@ -31,7 +31,7 @@ import {

### GlobalStatus displaying success status

<GlobalStatusSuccess />
<GlobalInfoOverlaySuccess />

### To showcase the automated coupling between **FormStatus** and **GlobalStatus**

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: 'InfoOverlay'
description: '`Form.InfoOverlay` is used to display an informational message that fully covers the available space.'
showTabs: true
tabs:
- title: Info
key: '/info'
- title: Demos
key: '/demos'
- title: Properties
key: '/properties'
breadcrumb:
- text: Forms
href: /uilib/extensions/forms/
- text: Form
href: /uilib/extensions/forms/Form/
- text: InfoOverlay
href: /uilib/extensions/forms/Form/InfoOverlay
---

import Info from 'Docs/uilib/extensions/forms/Form/InfoOverlay/info'
import Demos from 'Docs/uilib/extensions/forms/Form/InfoOverlay/demos'

<Info />
<Demos />
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import ComponentBox from '../../../../../../shared/tags/ComponentBox'
import { createRequest } from '../SubmitIndicator/Examples'
import { Field, Form, Wizard } from '@dnb/eufemia/src/extensions/forms'
import { Button } from '@dnb/eufemia/src'

const request = createRequest()

export const ErrorMessage = () => {
return (
<ComponentBox scope={{ request }}>
{() => {
// myFormId can be anything, as long as it's a unique instance
const myFormId = () => null

return (
<Form.Handler
id={myFormId}
onSubmit={async () => {
await request(1000) // Simulate a request

Form.InfoOverlay.setContent(myFormId, 'error')
}}
>
<Form.InfoOverlay>
<Form.Card>
<Field.Email />
<Form.ButtonRow>
<Form.SubmitButton variant="send" />
<Button
variant="secondary"
onClick={() => {
Form.InfoOverlay.setContent(myFormId, 'error')
}}
>
Show error
</Button>
</Form.ButtonRow>
</Form.Card>
</Form.InfoOverlay>
</Form.Handler>
)
}}
</ComponentBox>
)
}

export const SuccessMessage = () => {
return (
<ComponentBox scope={{ request }}>
{() => {
// myFormId can be anything, as long as it's a unique instance
const myFormId = () => null

return (
<Form.Handler
id={myFormId}
onSubmit={async () => {
await request(1000) // Simulate a request

Form.InfoOverlay.setContent(myFormId, 'success')
}}
>
<Form.InfoOverlay>
<Form.Card>
<Field.Email />
<Form.SubmitButton variant="send" />
</Form.Card>
</Form.InfoOverlay>
</Form.Handler>
)
}}
</ComponentBox>
)
}

export const WithAWizard = () => {
const request = createRequest()
return (
<ComponentBox scope={{ request }}>
{() => {
// myFormId can be anything, as long as it's a unique instance
const myFormId = () => null

return (
<Form.Handler
id={myFormId}
onSubmit={async () => {
await request(1000)
Form.InfoOverlay.setContent(myFormId, 'success')
}}
>
<Form.InfoOverlay>
<Wizard.Container
onStepChange={async () => {
await request(1000)
}}
>
<Wizard.Step title="Step 1">
<Form.Card>
<Field.String
path="/someInfo"
label="Some information"
/>
</Form.Card>
<Wizard.NextButton />
</Wizard.Step>
<Wizard.Step title="Step 2">
<Form.Card>
<Field.String path="/more" label="More information" />
</Form.Card>
<Form.SubmitButton variant="send" />
</Wizard.Step>
</Wizard.Container>
</Form.InfoOverlay>
</Form.Handler>
)
}}
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
showTabs: true
hideInMenu: true
---

import * as Examples from './Examples'

## Demos

### Error message

<Examples.ErrorMessage />

### Success message

<Examples.SuccessMessage />

### With a Wizard

<Examples.WithAWizard />
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
showTabs: true
hideInMenu: true
---

## Description

`Form.InfoOverlay` is used to display an informational message that fully covers the available space. It can show a custom message or content, a `success` message as a receipt, or an `error` message to indicate an issue.

## Usage

By default the given children will be shown.

```tsx
import { Form } from '@dnb/eufemia/extensions/forms'

render(
<Form.Handler>
<Form.InfoOverlay>visible content</Form.InfoOverlay>
</Form.Handler>,
)
```

## Display a message

There are two ways to display a message:

- Using the `Form.InfoOverlay.setContent` method.
- Using the `content` prop.

### Using the `Form.InfoOverlay.setContent` method

You can show the success or error message by using the `Form.InfoOverlay.setContent` method:

```tsx
Form.InfoOverlay.setContent(myId, <>info content</>)
// or
Form.InfoOverlay.setContent(myId, 'success')
// or
Form.InfoOverlay.setContent(myId, 'error')
```

And render the component with an `id` prop:

```tsx
<Form.InfoOverlay id={myId}>content</Form.InfoOverlay>
```

You can call it whenever you need to show the success message. Here is an example of how to use it.

**Note:** the `id` prop is inherited from the `Form.Handler` component in this example.

```tsx
import { Form } from '@dnb/eufemia/extensions/forms'

// myFormId can be anything, as long as it's a unique instance
const myFormId = () => null

render(
<Form.Handler
id={myFormId}
onSubmit={async () => {
// 1. Send the request

// 2. Show the success message
Form.InfoOverlay.setContent(myFormId, 'success')
}}
>
<Form.InfoOverlay>fallback content</Form.InfoOverlay>
</Form.Handler>,
)
```

### Using the `content` prop

You can show the success or error message by using the `content` prop:

```tsx
<Form.InfoOverlay content={<>info content</>}>fallback content</Form.InfoOverlay>
<Form.InfoOverlay content="success">fallback content</Form.InfoOverlay>
<Form.InfoOverlay content="error">fallback content</Form.InfoOverlay>
```

## Customization of the `success` and `error` messages

You can customize the `success` and `error` messages by using the `success` and `error` props.

```tsx
<Form.InfoOverlay
success={{
title: 'Custom title',
description: 'Custom description',
buttonText: 'Custom button text',
buttonHref: 'http://custom',
buttonClickHandler: () => {},
}}
error={{
title: 'Custom title',
description: 'Custom description',
cancelButton: 'Custom cancel',
retryButton: 'Custom retry',
retryingText: 'Custom retrying text',
}}
>
fallback content
</Form.InfoOverlay>
```

## Accessibility

The component will manage focus handling, which is important for screen readers and users using keyboard navigation.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
showTabs: true
hideInMenu: true
---

import TranslationsTable from 'dnb-design-system-portal/src/shared/parts/TranslationsTable'
import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import {
InfoOverlaySuccessProperties,
InfoOverlayErrorProperties,
} from '@dnb/eufemia/src/extensions/forms/Form/InfoOverlay/InfoOverlayDocs'

## Properties

### Error

<PropertiesTable props={InfoOverlayErrorProperties} />

### Success

<PropertiesTable props={InfoOverlaySuccessProperties} />

## Translations

<TranslationsTable
localeKey={['InfoOverlayError', 'InfoOverlaySuccess']}
/>
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export type HeightAnimationProps = {

export type HeightAnimationAllProps = HeightAnimationProps &
SpacingProps &
Omit<React.HTMLProps<HTMLElement>, 'ref'>
Omit<React.HTMLProps<HTMLElement>, 'ref' | 'onAnimationEnd'>

function HeightAnimation({
open = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default function FormElement(props: Props) {
key={key}
state={key}
id={`${id}-form-status-${key}`}
className="dnb-forms-status"
className="dnb-forms-form__status-message"
show={Boolean(value)}
no_animation={false}
shellSpace={{ top: 'small' }}
Expand Down
Loading

0 comments on commit 9dd8402

Please sign in to comment.