Workday Canvas

Bottom Sheet

A modal view pinned to the bottom of the screen that contains a scoped task or information related to a parent screen.

Sources
Figma

Anatomy

The basic elements of the bottom sheet

  1. Sheet Container: Holds sheet content.
  2. Grabber (Conditional): Appears only when the sheet is resizable.
  3. Scrim Overlay: iOS modal dimming.

Variations

All sheets are modal as they block interaction with the parent view until dismissed.

Content Size

Opens to varying heights based on their content. This size is meant to be used for supplemental information or scoped tasks such as requesting a single piece of information from the user.

Image of a content sized sheet

Large Size

Opens to a fixed size that fills most of the screen. The parent page should scale behind the sheet. This size should be used when it’s useful to see more information at once.

Image of a full size bottom sheet.

Medium Resizable

Opens to half the screen height and grows to its full height when scrolling content. A grabber is displayed to indicate resizability. These sheets should be used to focus user attention on the most important content or actions first.

Image of a half size bottom sheet

Usage Guidance

Bottom sheets are flexible containers that can hold many layout and content types.

  • Use the appropriate sheet size for the task at hand. In general, use a Large or Content sized sheet if it’s useful to see content all at once. To show the most relevant content first, use a Medium resizable sheet.
  • Bottom sheets can be nested. On iOS, nested sheets are stacked on top of their parent sheet. Dismissing the nested sheet should take users back to the original sheet.
  • Allow for scrolling if sheet content exceeds the viewport. Keep bottom sheet headers sticky to the top of the viewport if scrolling is enabled.
  • While bottom sheets support gesture-based dismissal, consider providing alternative ways to dismiss the sheet using visual affordances. For example, a ‘Cancel’ text button placed in the header, or a Close Icon for read-only information.
  • If data will be lost, consider confirming dismissal through a Dialog.

When to Use

  • To break down larger, complex tasks into more manageable pieces.
  • To focus attention on a smaller, scooped task in a larger context.
  • To show actions a user can take on a parent page, if a Menu is too small to hold those actions.
  • To show additional content that supplements a larger context.

When To Use Something Else

  • Use a full page view for primary content.
  • Use a full-screen modal for complex or immersive information like media or articles.
  • Use a Dialog to notify users to take action, or to confirm an action with the user.
  • Use a Menu to present actions in a non-modal view, in close proximity to where the user tapped.
  • Use a Snackbar to provide lightweight feedback validation in response to a user action.

Usage Examples

Informational Sheets

Shows supplemental content about the parent page. Use a Large or Content Size sheet. A close system icon is used to dismiss.

An iOS informational sheet

Action Sheets

Shows a list of actions users can take on the parent page. Use these instead of Menus when more room is needed to accommodate actions, longer labels, or icons. Don’t use an explicit button for dismissal - taking an action or swiping down on the sheet should dismiss it.

Image of an sheet with a list of actions.

Inputs or selections

Provides a focused view for simple forms or selections. Use a Large Size sheet when presenting multiple inputs, folders, or search. Otherwise, use a Content Size sheet. Selecting, confirming selection, or gesture-based dismissals should close the sheet.

Image of a sheet with selection options.

Behaviors

Sheet transitions should generally follow platform guidance.

Opening and Closing a Sheet

Bottom sheets should open by moving upwards from the bottom screen, and close by moving out of the viewport.

Nested Sheets

Sheets can be nested. Nested sheets are stacked on top of a parent page. Dismissing the nested sheet should navigate users back to the original sheet.

Transitioning Between Sheets

  • If all steps in a flow are large sized sheets, use the same sheet and transition the content. Avoid opening and closing multiple bottom sheets.
  • When transitioning between different sized sheets, the sheet container should resize to fit the content in the next sheet. Do not resize the sheet until the size of the content is known.

Gestures

Scrolling

Bottom sheets can be scrollable if content exceeds sheet height.

Image of a scrollable sheet.

Auto-resize

Bottom sheets should automatically resize to accommodate keyboards and persist until the keyboard is dismissed.

Image of a bottom sheet resizing to accommodate an iOS keyboard.

Dismissal

To dismiss a bottom sheet, users can swipe or drag downwards on the grabber, tap an affordance for dismissal, or tap the modal mask to dismiss. For accessibility, the modal mask is focusable with a screen reader for closing the sheet.

Image of different dismiss options for the bottom sheet.

API Guidelines

ContentSized Sheet Definition

contentSizeSheet(isSwipeDismissable:isTapDismissable:prefersGrabberVisible:isPresented:onDismiss:_:)

Methods

public func contentSizeSheet<ContentView: View>( isSwipeDismissable: Bool = true, isTapDismissable: Bool = true, prefersGrabberVisible: Bool = true, isPresented: Binding<Bool>, onDismiss: (() -> Void)? = nil, @ViewBuilder _ contentView: @escaping () -> ContentView ) -> some View

Creates a sheet that sizes itself to the content.

Parameters

NameDescription
isSwipeDismissableWhether the sheet can be dismissed by dragging down from the top grabber to the bottom of the screen. If false, the sheet can only be dismissed programatically, like with a button that sets isPresented to false.
prefersGrabberVisibleWhether the sheet shows a grabber at the top.
isPresentedBinding that determines if the sheet is displayed.
onDismissAction to perform when the sheet goes away.
contentViewView that appears in the sheet.

DetentableSheet Definition

detentableSheet( isPresented: isSwipeDismissable: prefersGrabberVisible: prefersScrollingExpandsWhenScrolledToEdge: detents:selectedDetentPosition: onDismiss: contentView: )

Methods

public func detentableSheet<ContentView: View>( isPresented: Binding<Bool>, isSwipeDismissable: Bool = false, prefersGrabberVisible: Bool = true, prefersScrollingExpandsWhenScrolledToEdge: Bool = true, detents: Set<DetentPosition> = [.middle, .top], selectedDetentPosition: Binding<DetentPosition?>, onDismiss: (() -> Void)?, @ViewBuilder contentView: @escaping () -> ContentView ) -> some View

Modifies an existing view to have a DetentableSheet that can appear based on the settings of certain bound properties.

Parameters

NameDescription
isSwipeDismissableWhether swiping down dismisses the sheet.
prefersGrabberVisibleWhether the sheet has a visible grabber.
prefersScrollingExpandsWhenScrolledToEdgeWhether scrolling a ScrollView inside the sheet’s content should expand the sheet vertically if it’s at DetentPosition.middle and detents includes DetentPosition.top.
detentsThe set of available detents for this sheet. The empty set gets treated identically to a set with just DetentPosition.top, however this behavior might change in the future, so it’s best to always be explicit about which detents are supported.
isPresentedWhether the sheet is visible now.
selectedDetentPositionThe current DetentPosition occupied by the view. If nil, the sheet doesn’t currently appear on the screen. The value of this property defaults to DetentPositoin.top if isPresented gets set to true; this can be overridden by setting the value of this property to something else right after setting isPresented to true.
onDismissAction to run when the sheet is dismissed.
contentViewThe view inside the sheet when presented.

Accessibility Guidelines

Coming soon!

Content Guidelines

Coming soon!

Can't Find What You Need?

Check out our FAQ section which may help you find the information you're looking for. For further information, contact the #ask-canvas-design or #ask-canvas-kitchannels on Slack.

On this Page: