Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Forms): add Form.InfoOverlay to display error, success (receipt), or custom messages to users #4357

Merged
merged 6 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading