Sheet
The Sheet component is a container that acts as a supplementary view, providing access to important contextual information. It can be used to display additional content or functionality in mobile views replacing Modal from desktop.
Available from eds-core/1.10.0
Quick Start
- Installation
npm install @adaptavant/eds-core
- Import
import { Sheet } from '@adaptavant/eds-core';
Basic Usage
All Sheet_Primitives come with default styling for spacing and overflow scroll behavior, which can be customized using Style APIs (className, classNames, style, styles) if needed.
Only Sheet_Primitives like SheetTitle, SheetContent, and SheetFooter are accepted as direct children; passing any other child will result in an error.
Note: There is a default 500 milliseconds delay for the sheet animation.
const [openSheet, setOpenSheet] = React.useState(false);
function onSheetOpen() {
setOpenSheet(true);
console.log("sheet opened");
document.querySelector("body").style.overflow = "hidden";
}
function onSheetClose() {
setOpenSheet(false);
console.log("sheet close");
document.querySelector("body").style.overflow = "unset";
}
return (
<React.Fragment>
<Button onClick={onSheetOpen}>Open Sheet</Button>
<Sheet
descriptionId="sheet-description"
onClose={onSheetClose}
open={openSheet}
titleId="sheet-title"
>
<SheetHeader
closeButtonProps={{
label: "Sheet Close Button",
onClick: onSheetClose,
}}
>
<Heading as="h2" className="text-heading-16" id="sheet-title">
Title of sheet
</Heading>
<Text className="text-body-14">
Sub header of the sheet if needed can be added as aria describedby
</Text>
</SheetHeader>
<SheetContent className="gap-2 flex flex-col">
<Text className="text-body-16">
Slot for any content You can decide or partiction what goes inside
these slots, below you can see content or forms for example.
</Text>
<Text className="text-body-14" id="sheet-description">
Body of Sheet - announced as aria describedby
</Text>
<Field label="Name">
<TextInput defaultValue="Test 123123" />
</Field>
</SheetContent>
<SheetFooter>
<Text className="mr-auto text-body-12 text-secondary">
This portion also a slot
</Text>
<Button onClick={onSheetClose} variant="neutralTertiary">
Cancel
</Button>
<Button onClick={onSheetClose}>Save</Button>
</SheetFooter>
</Sheet>
</React.Fragment>
);
Placement
The placement
prop determines the position of the Sheet component relative to its trigger element. This prop allows for flexible layout options, enabling the Sheet to be displayed from various directions:
'left'
: Positions the Sheet to the left of the trigger element.'right'
: Positions the Sheet to the right of the trigger element.'top'
: Positions the Sheet above the trigger element.'bottom'
: Positions the Sheet below the trigger element (default).
Note: Choose the appropriate placement can enhance user experience by optimizing visibility and accessibility based on the layout of the surrounding components.
const [openSheet, setOpenSheet] = React.useState(false);
function onSheetOpen() {
setOpenSheet(true);
console.log('sheet opened');
document.querySelector('body').style.overflow = 'hidden';
}
function onSheetClose() {
setOpenSheet(false);
console.log('sheet close');
document.querySelector('body').style.overflow = 'unset';
}
return (
<React.Fragment>
<Button onClick={onSheetOpen}>Open Sheet</Button>
<Sheet
className="top-[60px]" // Adjusts sheet position to account for the fixed header on the docs page
descriptionId="sheet-description"
onClose={onSheetClose}
open={openSheet}
titleId="sheet-title"
placement="top"
>
<SheetHeader closeButtonProps={{
label: "Sheet Close Button",
onClick: onSheetClose,
}}>
<Heading as="h2" className="text-heading-16" id="sheet-title">
Title of sheet
</Heading>
<Text className="text-body-14">
Sub header of the sheet if needed can be added as aria describedby
</Text>
</SheetHeader>
<SheetContent className="gap-2 flex flex-col">
<Text className="text-body-16">
Slot for any content You can decide or partiction what goes inside
these slots, below you can see content or forms for example.
</Text>
<Text className="text-body-14" id="sheet-description">
Body of Sheet - announced as aria describedby
</Text>
<Field label="Name">
<TextInput defaultValue="Test 123123" />
</Field>
</SheetContent>
<SheetFooter>
<Text className="mr-auto text-body-12 text-secondary">
This portion also a slot
</Text>
<Button onClick={onSheetClose} variant="neutralTertiary">
Cancel
</Button>
<Button onClick={onSheetClose}>Save</Button>
</SheetFooter>
</Sheet>
</React.Fragment>
);
Style API
Our design system components include style props that allow you to easily customize different parts of each component to match your design needs.
Please refer to the Style API documentation for more insights.
Sheet parts
|
Stylable Parts | Description |
---|---|
sheetWrapper | The inner wrapper of the sheet, typically used for controlling the layout or the sheet content's alignment and size. |
SheetHeader parts
|
Stylable Parts | Description |
---|---|
closeButton | The button element used to close the sheet, typically placed at the top-right corner of the header. |
Usage guidelines
Do
- Display contextual information: Do use the sheet for displaying contextual actions or additional information that enhances the main page without disrupting the user’s flow (e.g., clicking on a table row).
- Use for subtasks: Do use the sheet to handle subtasks that are too complex for a popover but should remain within the context of the main task.
- Maintain user context: Do allow users to maintain context by letting them interact with secondary functions without leaving the current page, such as linking external resources or batch updating.
- Ensure screen space awareness: Do consider screen real estate, especially when multiple sheets or side panels are present. Overlapping or overwhelming users with shrinking page content should be avoided.
Don’t
- Avoid nested drawers: Don’t open one drawer from within another. Only one sheet should be open at a time to avoid confusion and complexity.
- Don’t use for complex forms or complex interactions: Don’t use a sheet for complex forms instead, move the content to a dedicated page for better clarity.
Best practices
Do
Swap modals for sheets on mobile: Use sheets instead of modals on mobile devices to reduce excessive padding and maximize space for content.
Don’t
Don’t use modals on mobile: Avoid using modals with large paddings that take up too much screen space, as sheets offer a more efficient layout.
Do
Prioritize popular choices: Arrange the most important actions from top to bottom, making the most commonly used options easier to access.
Don’t
Don’t bury important actions: Avoid placing critical or frequently used options lower in the list, where they may be harder to find.
Do
Ensure clear header and close actions: Do always include a clear, descriptive header and provide "Done" and "Close" actions to help users understand the sheet's purpose and exit it easily.
Don’t
Don't limit options: Allow users to make choices and avoid restricting them to a single action by providing only one option.
Do
Consider content complexity: Use a sheet size that matches the complexity of the content. For most scenarios, a medium-sized sheet is ideal to balance information and usability.
Don’t
Don’t use oversized sheets for simple tasks: Avoid using large sheets when the content is minimal or straightforward. Opt for smaller components like popovers or dropdowns in such cases.
Do
Ensure screen space awareness: Consider the available screen real estate, especially when multiple components are present.
Don’t
Don’t overload the interface: Avoid displaying too many components at once, as it can shrink content areas and confuse users by overcrowding the page. Avoid crowding the screen and overwhelming users.