Sheet
Description
A primitive component for building advanced swipeable modal and non-modal overlay components such as bottom sheets, drawers, sidebars, dialogs, pages, lightboxes, toasts and more.
Built with a compound component architecture, it exposes a set of sub-components that give you full control over structure, behavior, and styling.
Anatomy
Basic
TypeScript
import { Sheet } from "@silk-hq/components";
export default () => (
<Sheet.Root>
<Sheet.Trigger />
<Sheet.Portal>
<Sheet.View>
<Sheet.Backdrop />
<Sheet.Content>
<Sheet.BleedingBackground />
<Sheet.Title />
<Sheet.Description />
</Sheet.Content>
</Sheet.View>
</Sheet.Portal>
</Sheet.Root>
);With a component id
TypeScript
import { Sheet, createComponentId } from "@silk-hq/components";
const mySheetId = createComponentId();
export default () => {
return (
<Sheet.Root componentId={mySheetId}>
<Sheet.Root>
<Sheet.Trigger />
<Sheet.Portal>
<Sheet.View>
<Sheet.Backdrop />
<Sheet.Content>
<Sheet.BleedingBackground />
<Sheet.Title />
<Sheet.Description />
<Sheet.Trigger forComponent={mySheetId} />
</Sheet.Content>
</Sheet.View>
</Sheet.Portal>
</Sheet.Root>
<Sheet.Trigger forComponent={mySheetId} />
<Sheet.Portal>
<Sheet.View forComponent={mySheetId}>
<Sheet.Backdrop />
<Sheet.Content>
<Sheet.BleedingBackground />
<Sheet.Title />
<Sheet.Description />
</Sheet.Content>
</Sheet.View>
</Sheet.Portal>
</Sheet.Root>
);
};With related components
TypeScript
import { Sheet, Island, AutoFocusTarget } from "@silk-hq/components";
export default () => (
<Sheet.Root>
<Island.Root>
<Island.Content />
</Island.Root>
<Sheet.Outlet />
<Sheet.Trigger />
<Sheet.Portal>
<Sheet.View>
<Sheet.Backdrop />
<Sheet.Content>
<Sheet.BleedingBackground />
<Sheet.Handle />
<Sheet.Trigger />
<Sheet.Title />
<Sheet.Description />
<AutoFocusTarget.Root />
</Sheet.Content>
</Sheet.View>
</Sheet.Portal>
</Sheet.Root>
);With SpecialWrapper
TypeScript
import { Sheet } from "@silk-hq/components";
export default () => (
<Sheet.Root>
<Sheet.Trigger />
<Sheet.Portal>
<Sheet.View>
<Sheet.Backdrop />
<Sheet.Content>
<Sheet.SpecialWrapper.Root>
<Sheet.SpecialWrapper.Content>
<Sheet.BleedingBackground />
<Sheet.Title />
<Sheet.Description />
</Sheet.SpecialWrapper.Content>
</Sheet.SpecialWrapper.Root>
</Sheet.Content>
</Sheet.View>
</Sheet.Portal>
</Sheet.Root>
);Sub-components
<Sheet.Root>
| Characteristic | Details |
|---|---|
| Presence | Required |
| Composition | Contains all Sheet sub-components that belong to this Sheet instance, except for <Sheet.Portal> which can be positioned outside |
| Underlying element | |
Description
The Root sub-component wraps all other Sheet sub-components that belong to the same Sheet instance (except for <Sheet.Portal> which can be used around it), as it contains logic that is shared with all of them.
Notes
If you don’t want the underlying element to affect the layout, you can apply the CSS display: contents; to it.
license
| Characteristic | Details |
|---|---|
| Presence | Required |
| Type | |
| Default | |
Description
Indicates under what license you are using the library.
Values description
| Value | Description |
|---|---|
| You declare using the library under the commercial license. |
| You declare using the library under the non-commercial license. |
Notes
The purchase of a commercial license is needed for commercial use. More information here.
asChild
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether the sub-component underlying element is the default one or the one passed as child of the sub-component.
Values description
| Value | Description |
|---|---|
| The underlying element rendered is the child. |
| The underlying element rendered is the default one. |
Notes
- If the child is a React component rendering an element:
- it must accept props and spread all received props onto the rendered element;
- in React < 19, it must use
React.forwardRef()and pass the received ref to the rendered element.
- See Composition for more information.
componentId
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the id of this Sheet. This id can then be passed to other Sheet sub-components forComponent prop to associate them with it.
forComponent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Associates this Sheet instance with the desired SheetStack instance.
Values description
| Value | Description |
|---|---|
| This Sheet is not associated with any SheetStack. |
| Associates this Sheet with the SheetStack whose id is passed. |
| Associates this Sheet with the closest ancestor SheetStack. |
sheetRole
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
| Example values | "dialog", "alertdialog", "status" |
Description
Defines the WAI-ARIA role attribute set on the <Sheet.View> underlying element.
This value is also used to define the presence of the aria-haspopup attribute on the <Sheet.Trigger> underlying element.
Notes
- If
sheetRoleis set to"alertdialog", then on<Sheet.View>:swipeDismissalcomputes tofalse;onClickOutsidecomputes to{ dismiss: false, stopOverlayPropagation: true };onEscapeKeyDowncomputes to{ dismiss: false, stopOverlayPropagation: true }.
defaultPresented
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether the Sheet is initially presented or not.
Notes
On page load, it is presented after hydration occurs when set to true.
presented
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
| Requirements | When this prop is used, passing the state setter function to the onPresentedChange is also required. |
Description
Controls the presented state of the Sheet.
Values description
| Value | Description |
|---|---|
| The presented state is uncontrolled, the Sheet will only be presented and dismissed based on user interactions handled internally (e.g. press on a <Sheet.Trigger>). |
| Will cause the Sheet to be presented if it is not currently. |
| Will cause the Sheet to be dismissed if it is currently presented. |
Notes
- This is an alternative method to the
defaultPresentedprop. - Currently Sheet doesn’t support interruption during entering & exiting, and cannot be closed when it is not frontmost in a SheetStack (i.e. a sheet is stacked on top of it). Therefore, if
presentedis set tofalseduring entering or when not frontmost in a SheetStack, or totrueduring exiting, nothing will happen, and onPresentedChange will be called with the current value ofpresentedto avoid any mismatch between the controlled state and the internal one. This limitation will be lifted in the future.
onPresentedChange
| Characteristic | Details |
|---|---|
| Presence | Required if presented is used |
| Type | |
| Default | |
Description
Setter for the state passed in the presented prop. It will be called with the presented state value as parameter when it is changed internally (e.g. press on a <Sheet.Trigger> sub-component).
Notes
This is an alternative method to the defaultPresented prop.
defaultActiveDetent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the index of the detent the Sheet should initially rest on after it gets presented.
Notes
- Detents indexes are defined as follow:
- when the Sheet is fully outside of the view, it rests on the detent with index
0; - all declared intermediate detents indexes go from
1ton-1; - when the Sheet is fully expanded inside of
<Sheet.View>, it rests on the last detent, numberedn(e.g. index1if there is no intermediate detents; index2if there is one intermediate detent).
- when the Sheet is fully outside of the view, it rests on the detent with index
- If
defaultActiveDetentis set toundefined, the initial detent the Sheet rests on is the detent with the index1.
Example
TypeScript
<Sheet.Root defaultActiveDetent={2}>...</Sheet.Root>;activeDetent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Controls the activeDetent underlying state of the Sheet.
Values description
| Value | Description |
|---|---|
| The activeDetent state is uncontrolled, it will only change based on user interactions handled internally (e.g. swipe, or press on a <Sheet.Trigger>). |
| The activeDetent state is controlled, and this value reflects the index of the detent the Sheet is resting on or traveling towards. |
Notes
- This is an alternative method to the
defaultActiveDetentprop. - Currently it is not possible to step to a detent while stepping is already occurring. So if detent is changed during that state, nothing will occur, but there will be a mismatch between detent and the actual detent the sheet is resting on. So, before updating detent, you should check whether travelStatus ≠ “stepping”. This limitation will be lifted in the future.
onActiveDetentChange
| Characteristic | Details |
|---|---|
| Presence | Required if activeDetent is used |
| Type | |
| Default | |
Description
Setter for the state passed in the activeDetent prop. It will be called with the activeDetent state value as parameter when it is changed internally (e.g. swipe, or press on a <Sheet.Trigger>).
Notes
This is an alternative method to the defaultActiveDetent prop.
<Sheet.Trigger>
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Composition | Descendant of <Sheet.Root> |
| Underlying element | |
Description
A Trigger sub-component that allows to run specific actions related to the Sheet as a result of a press event.
Example
TypeScript
const MyTrigger = () => (
<Sheet.Trigger
action={{ type: "step", direction: "down" }}
onPress={{ forceFocus: false }}
>
Step down
</Sheet.Trigger>
);asChild
See asChild on <Sheet.Root>.
forComponent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | The SheetId of the closest <Sheet.Root> ancestor. |
Description
Associates this sub-component with the desired Sheet instance.
action
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the action that will execute when the Trigger is pressed.
Values description
| Value | Description |
|---|---|
| The Sheet will be presented. |
| The Sheet will be dismissed. |
| The Sheet will step to the next detent in the upward direction, and cycle after reaching the last detent. |
| The Sheet will step to a detent: - if the direction key is used, it will step to the next detent in that direction and cycle after reaching the last detent; - if the detent key is used, it will step to the detent matching that detent index. |
onPress
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the Trigger is pressed (equivalent to clicked).
The underlying custom event has a default behavior that can be changed either by calling its changeDefault method with an option object as parameter, or by directly passing the option object to the prop.
Values description
| Value | Description |
|---|---|
| The underlying element will be focused on press in all browsers (by default Safari doesn’t do it, causing issues with focus management). This is the recommended setting. |
| The underlying element will only receive focus on press in browsers where this is the default behavior (i.e. Safari will not do it). |
| The Trigger action will be run. |
| The Trigger action will not be run. |
Example
TypeScript
<Sheet.Trigger onPress={{ forceFocus: false }}>...</Sheet.Trigger>;TypeScript
<Sheet.Trigger onPress={(event) => event.changeDefault({ forceFocus: false })}>
...
</Sheet.Trigger>;travelAnimation
See travelAnimation on <Sheet.Outlet>.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.Outlet>
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Composition | Child of the <Sheet.Root> |
| Underlying element | |
Description
A sub-component that allows to declaratively define animations for the underlying element based on the travel and stacking progress of the associated Sheet.
asChild
See asChild on <Sheet.Root>.
forComponent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | The SheetId of the closest <Sheet.Root> ancestor. |
Description
Associates this sub-component with the desired Sheet instance.
travelAnimation
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Declaratively defines animations on any CSS property of the underlying element driven by the Sheet’s travel.
Values description for each key
| Value | Description |
|---|---|
| Keyframes array syntax. As the Sheet travels from its first detent (index 0) to its last detent, the underlying element will have its related CSS property animated from the first to the second value in the array, each value in-between being interpolated linearly. |
| Function syntax. As the Sheet travels from its first detent (index 0) to its last detent, the underlying element will have its related CSS property animated based on the value returned by the function. The progress value goes from 0 to 1. |
| String syntax. As the Sheet travels, the underlying element will have its related CSS property set to the defined value. |
| The underlying element related CSS property will not be animated or set. |
Notes
- CSS properties must be written in camelcase form (e.g.
borderRadius). - All individual components of the
transformCSS property can be used separately.- List
TypeScript
| "translate" | "translateX" | "translateY" | "translateZ" | "scale" | "scaleX" | "scaleY" | "scaleZ" | "rotate" | "rotateX" | "rotateY" | "rotateZ" | "skew" | "skewX" | "skewY"
- List
- The keyframes array syntax is only supported with individual
transformproperties andopacity.- List. Note that, apart from
opacity, all of the following keys will be incorporated into a singletransformdeclaration.TypeScript
| "opacity" | "translate" | "translateX" | "translateY" | "translateZ" | "scale" | "scaleX" | "scaleY" | "scaleZ" | "rotate" | "rotateX" | "rotateY" | "rotateZ" | "skew" | "skewX" | "skewY"
- List. Note that, apart from
- Three special CSS properties related to clipping are available:
clipBoundaryaccepts only one value:"layout-viewport". This special CSS property clips the underlying element where the layout viewport is drawn. Therefore, if the element is overflowing the layout viewport, it will be cut off. You can then use apply a transformation to it likescaleand reveal its clipping.clipBorderRadiusaccepts the same value as theborderRadiusCSS property. It defines a border radius for the clip area when used in combination with theclipBoundaryspecial CSS property.clipTransformOriginaccept the same value as thetransformOriginCSS property. It defines the origin for the CSS transform applied to the element when used in combination with theclipBoundaryspecial CSS property.
- Updating
travelAnimationwon't immediately reflect visually. The new value will only apply on the next travel. This limitation will be lifted in the future. travelAnimationis short for "travel-driven animation".
Examples
TypeScript
<Sheet.Outlet
travelAnimation={{
opacity: [0, 0.5],
}}
/>;TypeScript
<Sheet.Outlet
travelAnimation={{
opacity: ({ progress }) => progress * 0.5,
}}
/>;TypeScript
<Sheet.Outlet
travelAnimation={{
backgroundColor: ({ tween }) =>
`rgb(${tween(100, 0)}, ${tween(100, 0)}, ${tween(100, 0)})`,
}}
/>;stackingAnimation
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Declaratively defines animations on any CSS property of the underlying element driven by the aggregated travel of Sheets stacked above the Sheet associated with this Outlet and belonging to the same SheetStack.
Values description for each key
| Value | Description |
|---|---|
| Keyframes array syntax. As Sheets travel and get stacked on top of the associated Sheet, the underlying element will have its related CSS property animated from the first to the second value in the array, each value in-between being interpolated linearly. |
| Function syntax. As Sheets travel and get stacked on top of the associated Sheet, the underlying element will have its related CSS property animated based on the value returned by the function. The progress value goes from 0 to n (n being the number of Sheets stacked on top of the associated Sheet). |
| String syntax. As Sheets get stacked on top of the associated Sheet, the underlying element will have its related CSS property set to the defined value. |
| The underlying element related CSS property will not be animated or set. |
Notes
- CSS properties must be written in camelcase form (e.g.
borderRadius). - All individual components of the
transformCSS property can be used separately.- List
TypeScript
| "translate" | "translateX" | "translateY" | "translateZ" | "scale" | "scaleX" | "scaleY" | "scaleZ" | "rotate" | "rotateX" | "rotateY" | "rotateZ" | "skew" | "skewX" | "skewY"
- List
- The keyframes array syntax is only supported with individual
transformproperties andopacity.- List. Note that, apart from
opacity, all of the following keys will be incorporated into a singletransformdeclaration.TypeScript
| "opacity" | "translate" | "translateX" | "translateY" | "translateZ" | "scale" | "scaleX" | "scaleY" | "scaleZ" | "rotate" | "rotateX" | "rotateY" | "rotateZ" | "skew" | "skewX" | "skewY"
- List. Note that, apart from
- Updating
stackingAnimationwon't immediately reflect visually. The new value will only apply on the next travel. This limitation will be lifted in the future. stackingAnimationis short for "stacking-driven animation".
Examples
TypeScript
<Sheet.Outlet stackingAnimation={{ translateX: ["0px", "100px"] }} />;TypeScript
<Sheet.Outlet
stackingAnimation={{ translateX: ({ progress }) => progress * 100 + "px" }}
/>;TypeScript
<Sheet.Outlet
stackingAnimation={{
backgroundColor: ({ tween }) =>
`rgb(${tween(10, 0)}, ${tween(10, 0)}, ${tween(10, 0)})`,
}}
/>;<Sheet.Portal>
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Composition | Anywhere |
| Underlying element | None |
Description
A sub-component that allows to render its child into any element, including the document.body. It is typically used to render the <Sheet.Content> in a high level element to make sure it appears above all other elements.
container
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines inside of which element the Portal’s child will be rendered.
<Sheet.View>
| Characteristic | Details |
|---|---|
| Presence | Required |
| Composition | Child of the <Sheet.Root> |
| Underlying element | |
Description
The View sub-component underlying element is the view inside of which the <Sheet.Content> underlying element can travel.
It also holds the HTML role attribute for the Sheet.
forComponent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | The SheetId of the closest <Sheet.Root> ancestor. |
Description
Associates this sub-component with the desired Sheet instance.
contentPlacement
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | "bottom" if tracks is not set, otherwise it matches the value of the tracks prop. |
Description
Defines the placement of <Sheet.Content> inside of <Sheet.View> on the travel axis. On the cross axis, it is always centered.
tracks
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | "bottom" if contentPlacement is not set, otherwise it matches the value of the contentPlacement. |
Description
Defines the track(s) <Sheet.Content> can travel on, from its last detent (index n) to its origin detent (index 0).
detents
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | string | Array<string> where string is a CSS length which does not use the % unit. |
| Default | |
Description
Defines one or several intermediate detents on which <Sheet.Content> can rest on the track between the origin detent (index 0) and the last detent (index n).
swipeTrap
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | { x: true, y: false } on Android in non-standalone mode, true otherwise. |
Description
Defines whether swipes on the specified axis or axes are trapped within <Sheet.View> or not.
When not trapped, when swiping in a direction where further travel is not possible, the swipe will propagate to the closest ancestor Sheet, scroll container, or window (triggering swipe to go back in history in browsers that support it).
Values description
| Value | Description |
|---|---|
| Traps swipe both on both the x and y axis. |
| Traps swipe on the x axis. |
| Traps swipe on the y axis. |
Notes
- Always computes to
trueifinertOutsideis set totrue. - On Android in non-standalone mode,
swipeTrapon the y axis always computes tofalsenot to prevent the browser UI from being revealed. - If
swipeOvershootis set tofalse,swipeTrapon the travel axis always computes totrue. - Safari has a bug causing swipe to always be trapped when swiping over a vertically swipeable Sheet or Scroll which is inside of a horizontally swipeable Sheet or Scroll (and vice versa). We hope to see that issue resolved quickly.
swipeOvershoot
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the behavior when the user performs a swipe that would cause <Sheet.Content> to move further than its last detent (index n).
Values description
| Value | Description |
|---|---|
| Overshoot will occur, causing <Sheet.Content> to move further than the last detent, and snap back into place when released. |
| Overshoot will not occur, <Sheet.Content> will stop right away when being swiped past the last detent. |
Notes
Overshoot only works in browsers that support elastic overscroll (i.e. Safari, and Firefox on macOS).
swipeDismissal
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | false if sheetRole is set to "alertdialog", true otherwise. |
Description
Defines whether it is possible to swipe <Sheet.Content> out of the <Sheet.View> and cause the Sheet to be dismissed.
Notes
- Always computes to
falseifsheetRoleis set to"alertdialog". - When set to
falseandswipeOvershootis set totrue, the Sheet remains swipeable but will snap back into place when a swipe occurs.
swipe
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether swiping along the travel axis over <Sheet.Content> — or <Sheet.Backdrop> if swipeable — causes the Sheet to travel.
Notes
The value can only be updated when the Sheet is resting on a detent, not while it is traveling.
nativeEdgeSwipePrevention
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether a horizontal swipe from the left edge of the screen on iOS Safari triggers the browser’s “go back” navigation gesture.
Notes
- This mechanism relies on a
28px-wide element positioned at the left edge of the screen. By default it appears above all elements inside<Sheet.View>, blocking interaction with anything underneath. If this causes issues, you can lift your elements above it by applyingposition: relative;(or any non-static positioning) and az-indexvalue greater than0. - This element will also capture click outside events, preventing dismissal if the user clicks on it, even if visually outside of
<View.Content>. - This mechanism is not foolproof — in rare cases, quick gestures may still slip through and trigger the browser’s back navigation.
- For more reliable prevention in standalone mode on iOS, we recommend avoiding the addition of new history entries. Instead, replace the current entry. This way, Safari won’t allow swiping back, as there’s no previous page in the history.
- It is not based on a web standard, so there’s no guarantee it will continue to work in the future.
enteringAnimationSettings
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the configuration for the programmatic entering travel animation.
Values description
| Value | Description |
|---|---|
| Use the "gentle" preset. |
| For Sheet with two tracks defined, picks the track on which travel occurs (e.g. the "top" track here). |
| The <Sheet.Content> underlying element will not be animated, instead it will be placed on its destination detent immediately. All other sub-components underlying elements are animated normally. |
| The animation is skipped entirely and the Sheet doesn’t go through the corresponding state. |
Notes
- Presets definitions
TypeScript
const presets = { gentle: { easing: "spring", stiffness: 560, damping: 68, mass: 1.85, }, smooth: { easing: "spring", stiffness: 580, damping: 60, mass: 1.35, }, snappy: { easing: "spring", stiffness: 350, damping: 34, mass: 0.9, }, brisk: { easing: "spring", stiffness: 350, damping: 28, mass: 0.65, }, bouncy: { easing: "spring", stiffness: 240, damping: 19, mass: 0.7, }, elastic: { easing: "spring", stiffness: 260, damping: 20, mass: 1, }, };
exitingAnimationSettings
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the configuration for the programmatic exiting travel animation.
Values description
| Value | Description |
|---|---|
| Use the "gentle" preset. |
| For Sheet with two tracks defined, picks the track on which travel occurs (e.g. the "top" track here). |
| The <Sheet.Content> underlying element will not be animated, instead it will remain on its current detent. All other sub-components underlying elements are animated normally. |
| The animation is skipped entirely and the Sheet doesn’t go through the corresponding state. |
steppingAnimationSettings
Description
Defines the configuration for the programmatic stepping travel animation.
See enteringAnimationSettings.
Notes
The track and contentMove keys do not apply here.
onTravelStatusChange
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the travel status changes.
onTravelRangeChange
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the travel range changes.
Notes
- A range is defined by a start detent and an end detent.
- The Sheet is considered to be within a range when the side of
<Sheet.Content>opposite to the dismiss direction is located between the start and end detent of that range. - When the Sheet is resting on a specific detent, the start and end detent are equal to the index of that detent.
- The range does not reflect overshoot. Therefore, if the Sheet is overshooting after the detent with index
1, its travel range will be{ start: 1, end: 1 }.
onTravel
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs on every frame when travel occurs, whether it is caused by swipe or programmatically.
Parameters description
| Value | Description |
|---|---|
| The progress value of the Sheet travel, going from 0 to 1. It is 0 when the Sheet is fully out, and 1 when it is resting on the last detent. |
| The travel range the Sheet is currently within. |
| The equivalent progress value for each detent. It is useful to make calculations and apply effects only within specific ranges. |
onTravelStart
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the Sheet starts traveling, whether it is caused by swipe or programmatically.
Notes
It runs before the first onTravel event handler call.
onTravelEnd
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs after the Sheet finishes traveling, whether it is caused by swipe or programmatically.
Notes
It runs before the last onTravel event handler call.
inertOutside
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether all interactions outside of <Sheet.View> and all associated <Island.Content> should be prevented.
Notes
- In other words, this prop defines whether the Sheet is modal or not.
- It prevents
<body>from being scrollable, as expected. As a result, scrollbars are removed, and a CSS padding is added to compensate for it. In order to adjust the position of elements usingfixedpositioning, please use the Fixed component. See Fixed. - Use the Island component to wrap any element that you want the user to be able to interact with when this prop is set to
true. See Island. - Due to a Safari bug, when this prop is set to
falseand you are not using<Sheet.Backdrop>, you need to use<Sheet.SpecialWrapper.Root>and<Sheet.SpecialWrapper.Content>inside of<Sheet.Content>, otherwise the Sheet will not be swipeable.
onPresentAutoFocus
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the auto-focus mechanism is executed when the Sheet gets presented, at the end of the entering animation if there is one.
The underlying custom event has a default behavior that can be changed either by calling its changeDefault method with an option object as parameter, or by directly passing the option object to the prop.
Values description
| Value | Description |
|---|---|
| Causes the first <AutoFocusTarget> underlying element if there is one, or the first focusable element within the <Sheet.View> to receive focus when the Sheet gets presented. |
| Prevents the auto-focus mechanism from focusing any element when the Sheet gets presented. |
Example
TypeScript
<Sheet.View onPresentAutoFocus={{ focus: false }}>...</Sheet.View>;TypeScript
<Sheet.View
onPresentAutoFocus={(event) => event.changeDefault({ focus: false })}
>
...
</Sheet.View>;onDismissAutoFocus
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the auto-focus mechanism is executed when the Sheet gets dismissed, at the end of the exiting animation if there is one.
The underlying custom event has a default behavior that can be changed either by calling its changeDefault method with an option object as parameter, or by directly passing the option object to the prop.
Values description
| Value | Description |
|---|---|
| Causes the first <AutoFocusTarget> underlying element if there is one, or the first focusable element within the <Sheet.View> to receive focus when the Sheet gets dismissed. |
| Prevents the auto-focus mechanism from focusing any element when the Sheet gets dismissed. |
Example
TypeScript
<Sheet.View onDismissAutoFocus={{ focus: false }}>...</Sheet.View>;TypeScript
<Sheet.View
onDismissAutoFocus={(event) => event.changeDefault({ focus: false })}
>
...
</Sheet.View>;onClickOutside
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when a click occurs outside of <Sheet.View> and all associated <Island.Content>.
The underlying custom event has a default behavior that can be changed either by calling its changeDefault method with an option object as parameter, or by directly passing the option object to the prop.
Values description
| Value | Description |
|---|---|
| If sheetRole is not set to "alertdialog", then the Sheet will get dismissed when a click occurs outside. |
| Inverse of true. |
| The clickoutside custom event will not propagate to overlays (i.e. Sheets) that are presented below this one. Only this Sheet will deal with the event. |
| Inverse of true. |
Notes
- Click events performed on
<Sheet.Backdrop>underlying element are considered as outside.<Sheet.View>underlying element is click-through, so click events performed directly over it are considered as outside. - This prop always computes to
{ dismiss: false, stopOverlayPropagation: true }if thesheetRoleprop is set to"alertdialog". { dismiss: false, stopOverlayPropagation: false }is useful for example in combination with theinertOutsideprop set tofalsein the case of a toast or sidebar component which may be presented on top of another Sheet. In that case you don’t want the toast or sidebar component to get dismissed when a click outside occurs, but may want the Sheet below to do so. Because theclickoutsidecustom event will be propagated to the Sheet below, it will get dismissed if itsonClickOutsideprop is set to{ dismiss: true }.
Example
TypeScript
<Sheet.View onClickOutside={{ dismiss: false }}>...</Sheet.View>;TypeScript
<Sheet.View onClickOutside={(event) => event.changeDefault({ dismiss: false })}>
...
</Sheet.View>;onEscapeKeyDown
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when the escape key is pressed.
The underlying custom event has a default behavior that can be changed either by calling its changeDefault method with an option object as parameter, or by directly passing the option object to the prop.
Values description
| Value | Description |
|---|---|
| The user-agent default action run when the escape key is pressed is prevented. (Safari macOS default action is escaping full-screen mode.) |
| Inverse of true. |
| The Sheet will get dismissed when the escape key is pressed. |
| Inverse of true. |
| The keydown event will not propagate to overlays (i.e. Sheets) that are presented below this one. Only this Sheet will deal with this event. |
| Inverse of true. |
Notes
- Always computes to
{ dismiss: false, stopOverlayPropagation: true }ifsheetRoleis set to"alertdialog". { dismiss: false, stopOverlayPropagation: false }is useful for example in combination with theinertOutsideprop set tofalsein the case of a toast or sidebar component which may be presented on top of another Sheet. In that case you don’t want the toast or sidebar component to get dismissed when the escape key is pressed, but may want the Sheet below to do so. Because the keydown event will be propagated to the Sheet below, it will get dismissed if itsonEscapeKeyDownprop is set to{ dismiss: true }.
Example
TypeScript
<Sheet.View onEscapeKeyDown={{ dismiss: false }}>...</Sheet.View>;TypeScript
<Sheet.View
onEscapeKeyDown={(event) => event.changeDefault({ dismiss: false })}
>
...
</Sheet.View>;onFocusInside
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
An event handler that runs when focus occurs inside of <Sheet.View>.
nativeFocusScrollPrevention
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether the native browser scroll into view mechanism should be prevented or not when an element inside <Sheet.View> receives focus.
When an element receives focus on mobile, the browser shifts the viewport up or down to try and keep it in view. Unfortunately, this native mechanism doesn’t work well in most situations, so we let you prevent it and properly deal with the position of the focused element.
If the focused element ends up being covered by the on-screen keyboard, we recommend using the Scroll component so it gets scrolled into view automatically.
Notes
- The prevention doesn’t work when the inputs are inside of an
<iframe>element. - When the user clicks on text present in a text input, the caret will always be put back at its previous position when set to
true. - In iOS Safari, the prevention may not be effective with password inputs whose
autoCompletehtml attribute is set to anything else than"current-password". Therefore, we strongly recommend always using this value. Safari won’t suggest a new password directly, but the user can still get a suggested password by tapping the “Password” button in the suggestion bar and asking the password manager to provide a new password. - Due to a Chrome Android bug, the prevention may not be effective when the focus is moved with the on-screen keyboard “next input” button.
- Due to a Chrome Android bug, for inputs causing the suggestion bar of the keyboard to be shown, a distance of at least 48px between the last text input and the bottom of the viewport is required to avoid a layout shift.
<Sheet.Backdrop>
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Composition | Child of <Sheet.View> |
| Underlying element | |
Description
The Backdrop sub-component prevents user interactions with the content below and can be used to dim it.
asChild
See asChild on <Sheet.Root>.
swipeable
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether swiping over the Backdrop causes the Sheet to travel.
Notes
When set to false, using the SpecialWrapper sub-component is required in Safari due to a bug.
themeColorDimming
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines whether the theme-color of the page gets dimmed using the CSS background-color and opacity of <Sheet.Backdrop>, so the Backdrop and the OS status bar blend together.
Values description
| Value | Description |
|---|---|
| Computes to true in WebKit-based browsers. When true, the theme-color gets dimmed. |
| The theme-color does not get dimmed. |
Notes
- The HTML
theme-colormeta-tag must be set, and its value declared using the hexadecimal format (e.g.#ffffff) or the RGB format (rgb(<integer>, <integer>, <integer>)). - The
<Sheet.Backdrop>underlying element CSSbackground-colorvalue must not include the alpha channel. <Sheet.Backdrop>must have atravelAnimationdeclared for itsopacity, and its value must either use the keyframes array syntax withnumbers as values (notstring), or the function syntax and return anumber.- If you need to update the
theme-colorwhile the Sheet is presented, you must use theupdateThemeColorfunction so only the underlying color gets updated, preserving the dimming.
travelAnimation
| Characteristic | Details |
|---|---|
| Default | |
See travelAnimation on <Sheet.Outlet>.
Notes
You can remove the default value by setting it to { opacity: null }.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.Content>
| Characteristic | Details |
|---|---|
| Presence | Required |
| Composition | Child of <Sheet.View> |
| Underlying element | |
Description
The Content sub-component represents the panel which contains the content of the sheet and moves during travel.
Notes
Its position is determined by the contentPlacement prop on <Sheet.View>. You cannot define its position in any other way.
asChild
See asChild on <Sheet.Root>.
travelAnimation
See travelAnimation on <Sheet.Outlet>.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.BleedingBackground>
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Composition | Descendant of <Sheet.Content> |
| Underlying element | |
Description
The BleedingBackground sub-component renders an element which is automatically sized and positioned to fully occupy the <Sheet.Content> and bleed out of it in the swipe dismissal direction so it looks like it is expanded during swipe overshoot.
The underlying element can be styled freely to customize its appearance.
Notes
As a performance optimization, the underlying element is resized during entering and exiting animations. This can cause visual shifts when using gradient or images as background when their size is based on the size of the element. To avoid such shifts, prefer sizing based on absolute values (e.g. px or svh).
asChild
See asChild on <Sheet.Root>.
travelAnimation
See travelAnimation on <Sheet.Outlet>.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.Handle>
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Composition | Descendant of <Sheet.Root> |
| Underlying element | |
Description
A Handle sub-component representing a "handle" signifier used to indicate to the user that swiping the sheet is possible.
Internally, it renders a <Sheet.Trigger> sub-component wrapping a <VisuallyHidden> component. Therefore, any textual content passed to it will only be accessible to screen-readers and visually hidden.
A ::before pseudo-element is used to expand the interactive area of the underlying Trigger.
asChild
See asChild on <Sheet.Root>.
forComponent
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | The SheetId of the closest <Sheet.Root> ancestor. |
Description
Associates this sub-component with the desired Sheet instance.
action
| Characteristic | Details |
|---|---|
| Presence | Optional |
| Type | |
| Default | |
Description
Defines the action that will execute when the Handle is pressed.
Values description
| Value | Description |
|---|---|
| The Sheet will be dismissed. |
| The Sheet will step to the next detent in the upward direction, and cycle after reaching the last detent. |
| The Sheet will step to a detent: |
- if the
directionkey is used, it will step to the next detent in that direction and cycle after reaching the last detent; - if the
detentkey is used, it will step to the detent matching that detent index. |
onPress
See onPress on <Sheet.Trigger>.
travelAnimation
See travelAnimation on <Sheet.Outlet>.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.Title>
| Characteristic | Details |
|---|---|
| Presence | Required if sheetRole is set to dialog or alertdialog |
| Composition | Descendant of <Sheet.View> |
| Underlying element | |
Description
A sub-component used to define a title for the Sheet.
The aria-labelledby HTML attribute is set automatically on <Sheet.View> underlying element.
asChild
See asChild on <Sheet.Root>.
travelAnimation
See travelAnimation on <Sheet.Outlet>.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.Description>
| Characteristic | Details |
|---|---|
| Presence | Required if sheetRole is set to dialog or alertdialog |
| Composition | Descendant of <Sheet.View> |
| Underlying element | |
Description
A sub-component used to define a title for the Sheet.
The aria-describedby HTML attribute is set automatically on <Sheet.View> underlying element.
asChild
See asChild on <Sheet.Root>.
travelAnimation
See travelAnimation on <Sheet.Outlet>.
stackingAnimation
See stackingAnimation on <Sheet.Outlet>.
<Sheet.SpecialWrapper.Root>
| Characteristic | Details |
|---|---|
| Presence | Required when using the SpecialWrapper component |
| Composition | Child of <Sheet.Content> |
| Underlying element | |
Description
This sub-component allows to workaround a bug that prevents swiping in Safari when both:
- the
inertOutsideprop on<Sheet.View>is set tofalse; - the Backdrop sub-component is not present, or it is present but its
swipeableprop is set tofalse.
Notes
- There is two limitations caused by the use this sub-component:
- The underlying element makes use of the
overflowCSS property with a value other thanvisible, causing any content overflowing its bound to be clipped. - When swiping over the underlying element in the cross axis of the Sheet, and then in the travel axis without initiating a new swipe, sheet travel will not occur.
- The underlying element makes use of the
asChild
See asChild on <Sheet.Root>.
<Sheet.SpecialWrapper.Content>
| Characteristic | Details |
|---|---|
| Presence | Required when using the SpecialWrapper component |
| Composition | Child of <Sheet.SpecialWrapper.Root> |
| Underlying element | |
Description
The Content sub-component to be used in combination with <Sheet.SpecialWrapper.Root>.
asChild
See asChild on <Sheet.Root>.