import { Button, Notification } from 'grommet'; import { AccessibilitySection, BestPracticeGroup, Example, StyleTable, } from '../../../layouts'; import { ActionLabels, ActionLabelTitle, DoubleConfirmationAnatomy, DoubleConfirmationBestPractice, ConfigurationForm, LayerAnatomy, LayerExample, LayerCenterExample, LayerNotificationExample, LayerSideDrawerExample, LayerStickyExample, LayerStickyScrollExample, ActionableLayerClose, InformationalLayerClose, LayerTypes, } from '../../../examples'; import { Checkmark } from '@hpe-design/icons-grommet';
<Example componentName="Layer" docs="https://v2.grommet.io/layer?theme=hpe#props" code="https://raw.githubusercontent.com/grommet/hpe-design-system/master/apps/docs/src/examples/components/layer/LayerExample.js" figma="https://www.figma.com/design/HDckqS2MWhINfC8EIQPMV1/HPE-Design-System-Components-V2?m=auto&node-id=2567-534&t=6zfWJlYNDdZ4YwHx-1" grommetSource="https://github.com/grommet/grommet/blob/master/src/js/components/Layer/Layer.js"
[Placeholder for confirming next steps example]
[Placeholder for confirming destructive deletion example]
[Placeholder for adding a new record example]
[Placeholder for filtering data example]
[Placeholder for completing a multi-step process example]
Basic anatomy and spacing that apply to all layer types.
| Label | Region | Purpose | Required | Notes |
|---|---|---|---|---|
| 1 | Header | Identifies the layer. | -- | |
| 1a | Title | A short, descriptive title identifying the layer. | Implemented as a Heading level 2. | |
| 1b | Subtitle | Any additional context or information about the layer. | Optional | -- |
| 2 | Body | Any additional content. | Optional | -- |
| 3 | Footer | Contains layer actions. | Optional | The ordering and alignment of footer actions depends on the type of layer. |
<StyleTable data={[ { label: 4, property: 'pad', value: 'medium', }, { label: 5, property: 'gap', value: 'medium', }, { label: 6, property: 'round', value: 'small', }, { label: 7, property: 'elevation', value: 'large', }, ]} />
Different use cases and content warrant different layer types. Learn more about each type below.
Depending on whether a layer is informational or actionable, the elements and interactions that close a layer differ.
Informational layers do not require any actions from the user, and therefore do not contain any actions.
The following should cause an informational layer to close:
- Clicking the close icon button the layer's header.
- Clicking outside of the layer,
onClickOutside. - Pressing the Escape key,
onEsc.
Learn more about the specifics of informational center layers, informational side drawer layers, and informational fullscreen layers.
Actionable layers require the user to either accept or apply the action prompt in the layer or cancel the action.
The following should cause an actionable layer to close:
- Clicking the close icon button in the layer's header.
- Note: Actionable center layers should not include a close button in the layer's header. Center layers generally present confirmations, therefor the user should intentionally choose between accepting or cancelling the layer's action prompt.
- Clicking the cancel button in the layer's footer.
- Pressing the Escape key,
onEsc. - Clicking an affirmative action such as "save" or "apply."
Clicks outside of an actionable layer, onClickOutside, should not close the layer. Actionable layers present an 'apply' or 'do not apply' choice for which a user should make an intentional choice. Clicks outside of layer do not indicate intent and therefore should not close the layer.
Use of a double confirmation may be desirable as part of the layer's closing behavior in some instances. See more detail about when to use double confirmation.
Learn more about the specifics of actionable center layers, actionable side drawer layers, and actionable fullscreen layers.
When closing out of an actionable layer containing editable or configurable information, the behavior should err on preventing a user's unintentional loss of work by presenting a double confirmation.
A double confirmation should be shown when data has been edited or changed and the user closes the layer by using the close icon button, cancel button, or Escape key; a double confirmation is not needed upon affirmative actions like 'save' or 'apply'.
| Layer state | Confirmation type | Notes |
|---|---|---|
| User has not input or changed any data. | No confirmation | The user will not lose anything if the layer closes immediately. |
| User has input or changed data. | Double confirmation | The double confirmation should show when the user clicks the "X" or Cancel button, or presses the Escape key. This short confirmation ensures that user's work won't unintentionally be lost. |
A double confirmation appears as a center modal. This placement puts the confirmation at the center of the user's attention, reinforcing the importance of the dialog's prompt and minimizing distractions from other page content.
| Label | Region | Purpose | Required | Notes |
|---|---|---|---|---|
| 1a | Title | Explains that data will be discarded when the user closes the layer. | -- | |
| 1b | Subtitle | To clarify that changes will not be saved. | -- | |
| 2 | **Footer ** | Contains two actions: "Cancel" and "Discard" | The actions should be right-aligned with primary action on the right, to align with center layer guidance. |
The example below demonstrates how a double confirmation is only used if the layer's content has been changed or edited. A double confirmation is not used if no changes have been made. This behavior errs on preventing unintentional loss of work that a user has done.
First, click "Add application" then click the close button in the layer header. Notice how the layer immediately closes.
Next, click "Add application" again and this time type something into the "Title" input. Now, click the close button. Notice how a double confirmation appears.
<Example docs="https://v2.grommet.io/layer?theme=hpe#props" code="https://raw.githubusercontent.com/grommet/hpe-design-system/master/apps/docs/src/examples/components/layer/ConfigurationForm.js" height={{ min: 'xsmall' }} template showResponsiveControls={[]}
While layer is the component that drives the layout, elevation, positioning on the screen, modal vs. non-modal effects the behavior to dismiss the layer and interactivity of outside content.
Modal is a specific HTML behavior that excludes interaction with outside elements until it is dismissed.
Non-modal means that the outside content can still be interacted with while the layer is open.
When a layer is modal, a translucent overlay appears behind the layer and covers the rest of the page content to block the user from interacting with the page until the layer is closed.
Actionable layers should always be modal to ensure user focus is on the layer content and required actions. Modal is the default behavior of a layer.
When a layer is non-modal, there is no translucent overlay that covers the page content, and the page can still be interacted with.
Informational layers can be non-modal. To implement, apply modal={false} to the layer.
If a layer contains footer actions, the primary action should be labeled using verb + noun format (e.g., "Apply filters").
The noun may be omitted from actions labels beyond the primary action if the action is clear and unambiguous (e.g. "Reset" instead of "Reset filters").
When in doubt, follow the verb + noun convention to ensure clarity. See button labeling guidance for more details.
The primary action verb should match the verb in the layer's title.
- Layer headings should be semantically correct.
- Treat a Layer as if it were a stand alone page, with the exception that the first heading within a Layer should be an
h2or<Heading level={2} />. - All subsequent headings should follow typical semantic heading structure.
It is critical that users of assisstive technologies are informed when a layer opens and closes. The approach to implementation differs. depending on if a layer is modal or non-modal.
For modal layers, use AnnounceContext to ensure it is clear that the layer has opened or closed.
There should be an announcement:
- When the layer opens.
- When the layer closes, specifying if the prompt has been accepted or cancelled.
// Announce on mount
const announce = useContext(AnnounceContext);
useEffect(() => {
announce(`[Insert layer title] modal opened.`, 'assertive');
}, [announce]);
// An announce on the Cancel button clarifies that
// the layer has been closed and the layer's prompt
// has been cancelled.
<Button
label="Cancel"
onClick={() => {
announce(`${title} modal cancelled and closed.`, 'assertive');
onClose();
}}
/>
When using a Layer with modal={false}, it is critical that the focus is moved to the "Close" button inside the Layer. Give the close button an a11yTitle that provides the user with context that they are in a Layer.
For example, implementation of this "Close" button for a Layer would be:
<Button
a11yTitle={`You are in a layer containing a form to add new hosts.
To close this layer, press Enter.`}
icon={<Close />}
onClick={() => setShowLayer(false)}
autoFocus
/>