Non Modal Dialog Primitive
An unstyled and accessible base upon which to build a non-modal dialog.
const NonModalDialogExample = () => {const nonModalDialog = useNonModalDialogPrimitiveState();return (<><NonModalDialogDisclosurePrimitive {...nonModalDialog}>✊ Action</NonModalDialogDisclosurePrimitive><NonModalDialogPrimitive {...nonModalDialog} aria-label="Welcome" style={{backgroundColor: '#000', zIndex:10}}><NonModalDialogArrowPrimitive {...nonModalDialog} /><span style={{color: '#fff'}}>Black Lives Matter. We stand with the Black community</span></NonModalDialogPrimitive></>);};render(<NonModalDialogExample />)
The non-modal dialog primitive is an unstyled functional version of a non-modal dialog. Our Popover is built on top of this primitive.
The purpose of providing these unstyled primitives is to cater for instances when the styled Popover provided by Paste doesn’t meet the requirements needed to solve a unique or individual customer problem. At that point you are welcome to fall back to this functional primitive to roll your own styled non-modal dialog while still providing a functional and accessible experience to your customers. However, we strongly recommend reviewing your design proposal with the Design Systems team before doing so.
This primitive should be used to compose all custom non-modal dialogs or popoovers to ensure accessibility and upgrade paths.
Before you roll your own non-modal dialogs...
We strongly suggest that all components built on top of this primitive get reviewed by the Design Systems team and go through the UX Review process to ensure an excellent experience for our customers.
const NonModalDialogExample = () => {const nonModalDialog = useNonModalDialogPrimitiveState();return (<><NonModalDialogDisclosurePrimitive {...nonModalDialog}>✊ Action</NonModalDialogDisclosurePrimitive><NonModalDialogPrimitive {...nonModalDialog} aria-label="Welcome" style={{backgroundColor: '#000', zIndex:10}}><NonModalDialogArrowPrimitive {...nonModalDialog} /><span style={{color: '#fff'}}>Black Lives Matter. We stand with the Black community</span></NonModalDialogPrimitive></>);};render(<NonModalDialogExample />)
const RightPlacementExample = () => {const nonModalDialog = useNonModalDialogPrimitiveState({placement: 'right'});return (<><NonModalDialogDisclosurePrimitive {...nonModalDialog}>Open non-modal dialog</NonModalDialogDisclosurePrimitive><NonModalDialogPrimitive {...nonModalDialog} aria-label="Welcome" style={{backgroundColor: '#000', zIndex:10}}><NonModalDialogArrowPrimitive {...nonModalDialog} /><span style={{color: '#fff'}}>Welcome to Paste!</span></NonModalDialogPrimitive></>);};render(<RightPlacementExample />)
const GutterExample = () => {const nonModalDialog = useNonModalDialogPrimitiveState({gutter: 0});return (<><NonModalDialogDisclosurePrimitive {...nonModalDialog}>Open non-modal dialog</NonModalDialogDisclosurePrimitive><NonModalDialogPrimitive {...nonModalDialog} aria-label="Welcome" style={{backgroundColor: '#000', zIndex:10}}><span style={{color: '#fff'}}>Welcome to Paste!</span></NonModalDialogPrimitive></>);};render(<GutterExample />)
The Non-Modal Dialog primitive can be styled using Paste components and tokens.
By using the as
prop, we can change the underlying element and combine it with another component. In the
example below we're combiningthe NonModalDialogDisclosurePrimitive
with the Button component.
We're also using the as
prop on the NonModalDialogPrimitive
to create a styled Box
with Paste
token background color, border radius, and spacing values.
Because the non-modal dialog lives outside of the main body
tag, we need to provide the base Paste styles using
StyledBase
from our theme package. This gives the Text
primitive the appropriate font stack and sizing.
const StyledNonModalDialog = React.forwardRef(({children, ...props}, ref) => (<Box backgroundColor="colorBackgroundBodyInverse" borderRadius="borderRadius20" padding="space30" ref={ref} {...props}>{children}</Box>));const StyledExample = () => {const theme = useTheme();const nonModalDialog = useNonModalDialogPrimitiveState({placement: 'right'});return (<><NonModalDialogDisclosurePrimitive {...nonModalDialog} as={Button} variant="secondary">Open non-modal dialog</NonModalDialogDisclosurePrimitive><NonModalDialogPrimitive {...nonModalDialog} aria-label="Welcome" as={StyledNonModalDialog}><StyledBase><Text color="colorTextInverse">Welcome to Paste!</Text></StyledBase></NonModalDialogPrimitive></>);};render(<StyledExample />)
This package is a wrapper around the Reakit Popover. If you’re wondering why we wrapped that package into our own, we reasoned that it would be best for our consumers’ developer experience. For example:
- If we want to migrate the underlying nuts and bolts in the future, Twilio products that depend on this primitive would need to replace all occurrences of
import … from ‘x-package’
toimport … from ‘@some-new/package’
. By wrapping it in@twilio-paste/x-primitive
, this refactor can be avoided. The only change would be a version bump in the ‘package.json` file for the primitive. - We can more strictly enforce semver and backwards compatibility than some of our dependencies.
- We can control when to provide an update and which versions we allow, to help reduce potential bugs our consumers may face.
- We can control which APIs we expose. For example, we may chose to enable or disable usage of certain undocumented APIs.
yarn add @twilio-paste/non-modal-dialog-primitive - or - yarn add @twilio-paste/core
This props list is a scoped version of the properties available from the Reakit Popover package.
baseId?: string
Sets the ID that will serve as a base for all the items IDs.
gutter?: string
Sets the offset between the reference and the popover on the main axis.
placement?: "auto-start" | "auto" | "auto-end" | "top-start...
Sets the placement of popover in relation to the NonModalDialogDisclosurePrimitive
. Available options include:
- auto-start
- auto-end
- auto
- top-start
- top-end
- top
- bottom-start
- bottom-end
- bottom
- right-start
- right-end
- right
- left-start
- left-end
- left
visible?: boolean
Whether the dialog is visible or not.
animated?: number | boolean
If true, animating will be set to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, stopAnimation will be called only after the same number of milliseconds have passed.
modal?: boolean
Sets the modal state.
- Non-modal: preventBodyScroll doesn't work and focus is free.
- Modal: preventBodyScroll is automatically enabled, focus is trapped within the dialog and the dialog is rendered within a Portal.
hideOnEsc?: boolean | undefined
If enabled, the user can hide the dialog by pressing Escape.
hideOnClickOutside?: boolean | undefined
If enabled, the user can hide the dialog by clicking outside it.
size?: string | number | undefined
The size of the arrow
fill?: string
Sets the fill color of the arrow svg path
stroke?: string
Sets the stroke color of the arrow svg path
disabled boolean | undefined
Sets the disclosure to disabled.
focusable boolean | undefined
Sets the disclosure to be focusable or not.
Changelog
e238ce11a
#3618 Thanks @SiTaggart! - [Non-modal dialog primitive] Updated dev depenedencies to include typescript and tsx for running build scripts
f1121febc
#3514 Thanks @TheSisb! - [Non-modal Dialog Primitive] Fix to always use a portal when rendering, even when using the state hook.
733709127
#3395 Thanks @SiTaggart! - Modified the compile target of our JavaScript bundles fromnode
tobrowser
to minimize the risk of clashing with RequireJS. This is marked as a major out of an abundance of caution. You shouldn't need to do anything but we wanted you to be aware of the change on the off chance it has unintended consequences
- Updated dependencies [
733709127
]:- @twilio-paste/reakit-library@2.0.0
- Updated dependencies [
3c89fd83d
]:- @twilio-paste/reakit-library@1.0.0
a4c9e70b0
#2763 Thanks @shleewhite! - Update ESLint rules, which changed some formatting.
ae9dd50f
#2466 Thanks @TheSisb! - [All packages] Update our ESBuild version and remove minification of identifiers in our production builds.
12a5e83e
#2449 Thanks @shleewhite! - Made a slight improvement to the TypeScript typings of several packages for better interoperability.
73c596919
#2269 Thanks @SiTaggart! - Fixed a regression with the compilation script that caused incompatible ESM module importing of JSON files.
c867e3f48
#2237 Thanks @SiTaggart! - Updated a build dependency (esbuild) which changes the output of our builds slightly, without materially changing anything about the code.
b7675915
#1985 Thanks @TheSisb! - For debugging purposes we now ship afilename.debug.js
unminified version of each component or library in Paste.
ed5c0a49c
#1965 Thanks @shleewhite! - Upgrade Paste to use React 17 by default, but maintain React 16 support for consumers.
355a5509
#1606 Thanks @richbachman! - [NonModalDialogPrimitive] exportedPopoverStateReturn
asNonModalDialogPrimitiveStateReturn
.
0eded1fd
#1319 Thanks @SiTaggart! - Change internal dependencies to have minor range matching on version numbers
ac38757f
#1228 Thanks @SiTaggart! - Bump status of the component to production
a12acb61
#1158 Thanks @richbachman! - Pinned all twilio-paste package versions in order to keep them in sync with core when they are updated by changesets.
All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.
0.3.1 (2021-01-25)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.11 (2021-01-15)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.10 (2021-01-14)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.9 (2020-10-23)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.8 (2020-10-13)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.7 (2020-09-22)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.6 (2020-09-15)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.5 (2020-09-03)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.4 (2020-07-01)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.3 (2020-07-01)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.2 (2020-06-25)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
0.2.1 (2020-06-25)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
- non-modal-dialog-primitive: export custom arrow and props (bd62148)
0.1.1 (2020-06-10)
Note: Version bump only for package @twilio-paste/non-modal-dialog-primitive
- non-modal-dialog-primitive: add non-modal primitive package (3252a57)