Default

Loading interactive example. Full source is available below.

View example source
Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const Default = (): JSXElement => {
    return (<Dialog>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>
          <DialogContent>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam exercitationem cumque
            repellendus eaque est dolor eius expedita nulla ullam? Tenetur reprehenderit aut
            voluptatum impedit voluptates in natus iure cumque eaque?
          </DialogContent>
          <DialogActions>
            <Button appearance="primary">Do Something</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default Default;

Resources

Best practices

Do

  • Use an action button to act on the entire contents of a dialog.
  • Use a toast notification to confirm the result of the dialog’s action.
  • Keep the text short and interactions to a minimum.
  • Try to avoid scrolling content.
  • Always have the dialog hug content vertically.

Don't

  • Use tabs or expanded sections in a dialog that overload the interface.
  • Launch another dialog from within a dialog.

Behavior and states

  • A modal dialog can be dismissed by selecting outside the container, using the Esc key, or selecting a footer button.
  • A non-modal dialog can be dismissed with its Close button, the Esc key, or a footer button, but not by selecting outside the dialog.
  • Alert dialogs can only be dismissed by selecting one of the available buttons in the footer.
  • Headers and footers remain persistent while overflow body content scrolls behind.
  • A checkbox can be included in a modal dialog, but this is a cumbersome interaction, so use it sparingly.
  • A required checkbox is used to request more explicit confirmation or consent to something, for example, when there is a legal or privacy obligation to do so.
  • In such cases, the primary action button is disabled until the checkbox is selected.
  • An optional checkbox can be used to give people a way to prevent the dialog from reappearing every time they perform the same action.
  • For this purpose, use “Don’t show this message again” as the checkbox label, and don’t disable the action buttons.

Forms in dialogs

Select With Form in the example menu to see controls, submit handling, and dialog actions together. Use the Field guidance for labels, hints, and validation.

API referenceGenerated CoreAI prop and type summaries

API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. ? means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

Dialog API

The Dialog root level component serves as an interface for interaction with all possible behaviors exposed. It provides context down the hierarchy to children compound components to allow functionality. This component expects to receive as children either a DialogSurface or a DialogTrigger and a DialogSurface (or some component that will eventually render one of those compound components) in this specific order

interface DialogProps {
  /**
   * Can contain two children including `DialogTrigger` and `DialogSurface`.
   * Alternatively can only contain `DialogSurface` if using trigger outside dialog, or controlling state.
   */
  children: JSXElement | [JSXElement, JSXElement];

  /**
   * Default value for the uncontrolled open state of the dialog.
   * @default false
   */
  defaultOpen?: boolean;

  /**
   * Enables standard behavior according to the [HTML dialog spec](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal)
   * where the focus trap involves setting outside elements inert.
   * @default false
   */
  inertTrapFocus?: boolean;

  /**
   * Dialog variations.
   *
   * `modal`: When this type of dialog is open, the rest of the page is dimmed out and cannot be interacted with.
   * The tab sequence is kept within the dialog and moving the focus outside
   * the dialog will imply closing it. This is the default type of the component.
   *
   * `non-modal`: When a non-modal dialog is open, the rest of the page is not dimmed out
   * and users can interact with the rest of the page.
   * This also implies that the tab focus can move outside the dialog when it reaches the last focusable element.
   *
   * `alert`: is a special type of modal dialogs that interrupts the user's workflow
   * to communicate an important message or ask for a decision.
   * Unlike a typical modal dialog, the user must take an action through the options given to dismiss the dialog,
   * and it cannot be dismissed through the dimmed background.
   * @default modal
   */
  modalType?: "alert" | "modal" | "non-modal";

  /**
   * Callback fired when the component changes value from open state.
   */
  onOpenChange?: DialogOpenChangeEventHandler;

  /**
   * Controls the open state of the dialog
   * @default false
   */
  open?: boolean;

  /**
   * For more information refer to the [Motion docs page](https://react.fluentui.dev/?path=/docs/motion-motion-slot--docs).
   */
  surfaceMotion?: PresenceMotionSlotProps<ScaleParams> | null;

  /**
   * Decides whether the dialog should be removed from the DOM tree when it is closed.
   * This can be useful when dealing with components that may contain state that should not
   * be reset when the dialog is closed.
   * @default true
   */
  unmountOnClose?: boolean;
}

DialogActions API

DialogActions is a container for the actions of the dialog. Apart from styling, this component does not have other behavior.

interface DialogActionsProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * Makes the actions expand the entire width of the DialogBody
   * @default false
   */
  fluid?: boolean;

  /**
   * defines the position on the dialog grid of the actions
   * @default 'end'
   */
  position?: "start" | "end";

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

DialogSurface API

DialogSurface component represents the visual part of a Dialog as a whole, it contains everything that should be visible.

interface DialogSurfaceProps {
  as?: "div";

  /**
   * Dimmed background of dialog.
   * The default backdrop is rendered as a `<div>` with styling.
   * This slot expects a `<div>` element which will replace the default backdrop.
   * The backdrop should have `aria-hidden="true"`.
   *
   * Accepts an `appearance` prop to control backdrop visibility:
   * - `'dimmed'`: Always shows a dimmed backdrop, regardless of nesting.
   * - `'transparent'`: Always shows a transparent backdrop.
   */
  backdrop?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; } & { appearance?: "transparent" | "dimmed" | undefined; }> | null | undefined;

  /**
   * For more information refer to the [Motion docs page](https://react.fluentui.dev/?path=/docs/motion-motion-slot--docs).
   */
  backdropMotion?: PresenceMotionSlotProps<FadeParams> | null;

  children?: any;

  className?: string;

  /**
   * Where the portal children are mounted on DOM
   * @default a new element on document.body without any styling
   */
  mountNode?: HTMLElement | { element?: HTMLElement | null; className?: string; } | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

DialogTitle API

The DialogTitle component expects to have a title/header and when Dialog is non-modal a close (X icon) button is provided through action slot by default.

interface DialogTitleProps {
  /**
   * By default a Dialog with modalType='non-modal' will have a close button action
   */
  action?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  as?: "div" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

DialogTrigger API

A non-visual component that wraps its child and configures them to be the trigger that will open or close a Dialog. This component should only accept one child.

This component sole purpose is to avoid opting out of the internal controlled open state of a Dialog Besides being a trigger that opens/close a dialog through context this component doesn't do much, making it basically unnecessary in cases where the trigger is outside of the Dialog component.

interface DialogTriggerProps {
  /**
   * Explicitly declare if the trigger is responsible for opening or
   * closing a Dialog visibility state.
   *
   * If `DialogTrigger` is outside `DialogSurface` then it'll be `open` by default
   *
   * If `DialogTrigger` is inside `DialogSurface` then it'll be `close` by default
   */
  action?: "open" | "close";

  children?: ReactElement<any, string | JSXElementConstructor<any>> | ((props: DialogTriggerChildProps<ARIAButtonType, {}>) => ReactElement<any, string | JSXElementConstructor<any>> | null) | null;

  /**
   * Disables internal trigger mechanism that ensures a child provided will be a compliant ARIA button.
   * @default false
   */
  disableButtonEnhancement?: boolean;
}

Implementation

CoreAI 0.12.0; Fluent 9.74.9.

Setup and dependencies.

Import components from @coreai-ds/react-components. CoreAI guidance above takes precedence over API demonstration examples.

Actions

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { CheckboxOnChangeData } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { Checkbox } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

export const Actions = (): JSXElement => {
    const [checked, setChecked] = React.useState(false);
    const handleChange = (ev: React.ChangeEvent<HTMLInputElement>, data: CheckboxOnChangeData) => {
        setChecked(Boolean(data.checked));
    };
    return (<Dialog modalType="non-modal">
      <DialogTrigger disableButtonEnhancement>
        <Button>Open campaign dialog</Button>
      </DialogTrigger>
      <DialogSurface aria-describedby={undefined}>
        <DialogBody>
          <DialogTitle>Delete this campaign?</DialogTitle>
          <DialogContent>
            <p>
              You're about to delete the campaign group "Campaign name that goes up to two lines". This will also delete
              all associated campaign resources, including the overview page, files, publications, conversations, and so
              forth. Please back up any content you need before proceeding.
            </p>
            <Checkbox checked={checked} onChange={handleChange} label="Yes, delete this campaign and all its associated resources"/>
          </DialogContent>
          <DialogActions>
            <DialogTrigger disableButtonEnhancement>
              <Button disabled={!checked} appearance="primary">
                Delete
              </Button>
            </DialogTrigger>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Cancel</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default Actions;

Alert

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const Alert = (): JSXElement => {
    return (<Dialog modalType="alert">
      <DialogTrigger disableButtonEnhancement>
        <Button>Open Alert dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Alert dialog title</DialogTitle>
          <DialogContent>
            This dialog cannot be dismissed by clicking on the backdrop. Close button should be pressed to dismiss this
            Alert, or `Escape` keydown.
          </DialogContent>
          <DialogActions>
            <Button appearance="primary">Do Something</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default Alert;

Backdrop Appearance

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useRestoreFocusTarget } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { OverlayDrawer } from "@coreai-ds/react-components";
import { DrawerHeader } from "@coreai-ds/react-components";
import { DrawerHeaderTitle } from "@coreai-ds/react-components";
import { Dismiss24Regular } from "@fluentui/react-icons";
import { DrawerBody } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    field: {
        display: 'grid',
        gridRowGap: tokens.spacingVerticalS,
        marginBottom: tokens.spacingVerticalL,
    },
});

type BackdropAppearanceOption = 'dimmed' | 'transparent';

export const BackdropAppearance = (): JSXElement => {
    const styles = useStyles();
    const labelId = useId('backdrop-appearance-label');
    const [drawerOpen, setDrawerOpen] = React.useState(false);
    const [backdropAppearance, setBackdropAppearance] = React.useState<BackdropAppearanceOption>();
    const backdropProp = backdropAppearance ? { appearance: backdropAppearance } : undefined;
    const restoreFocusTargetAttribute = useRestoreFocusTarget();
    return (<>
      <Button appearance="primary" onClick={() => setDrawerOpen(true)} {...restoreFocusTargetAttribute}>
        Open Drawer
      </Button>

      <OverlayDrawer open={drawerOpen} onOpenChange={(_, { open }) => setDrawerOpen(open)}>
        <DrawerHeader>
          <DrawerHeaderTitle action={<Button appearance="subtle" aria-label="Close" icon={<Dismiss24Regular />} onClick={() => setDrawerOpen(false)}/>}>
            Drawer
          </DrawerHeaderTitle>
        </DrawerHeader>

        <DrawerBody>
          <div className={styles.field}>
            <Label id={labelId}>Backdrop appearance</Label>
            <RadioGroup value={backdropAppearance} onChange={(_, data) => setBackdropAppearance(data.value as BackdropAppearanceOption)} aria-labelledby={labelId}>
              <Radio value="dimmed" label="Dimmed"/>
              <Radio value="transparent" label="Transparent"/>
            </RadioGroup>
          </div>

          <Dialog>
            <DialogTrigger disableButtonEnhancement>
              <Button>Open Dialog</Button>
            </DialogTrigger>
            <DialogSurface backdrop={backdropProp}>
              <DialogBody>
                <DialogTitle>Dialog</DialogTitle>
                <DialogContent>
                  This Dialog is rendered inside an OverlayDrawer, which internally uses Dialog. By default, nested
                  dialogs have a backdrop applied based on inner context. Use the <code>backdrop</code> prop to override
                  this behavior.
                </DialogContent>
                <DialogActions>
                  <DialogTrigger disableButtonEnhancement>
                    <Button appearance="primary">Close</Button>
                  </DialogTrigger>
                </DialogActions>
              </DialogBody>
            </DialogSurface>
          </Dialog>
        </DrawerBody>
      </OverlayDrawer>
    </>);
};

export default BackdropAppearance;

Change Focus

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

export const ChangeFocus = (): JSXElement => {
    const buttonRef = React.useRef<HTMLButtonElement>(null);
    const [open, setOpen] = React.useState(false);
    React.useEffect(() => {
        if (open && buttonRef.current) {
            buttonRef.current.focus();
        }
    }, [open]);
    return (<Dialog open={open} onOpenChange={(event, data) => setOpen(data.open)}>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>
          <DialogContent>This dialog focus on the second button instead of the first</DialogContent>
          <DialogActions position="start">
            <Button appearance="outline">Third Action</Button>
          </DialogActions>
          <DialogActions position="end">
            <Button appearance="primary">Do Something</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button ref={buttonRef} appearance="secondary">
                Close
              </Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default ChangeFocus;

Confirmation

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const Confirmation = (): JSXElement => {
    const dialogId = useId('dialog-');
    return (<Dialog>
      <DialogTrigger disableButtonEnhancement>
        <Button>Delete file</Button>
      </DialogTrigger>
      <DialogSurface aria-labelledby={`${dialogId}-title`} aria-describedby={`${dialogId}-content`}>
        <DialogBody>
          <DialogTitle id={`${dialogId}-title`}>Delete dialogSpec_final_FINAL_v3.jpg</DialogTitle>
          <DialogContent id={`${dialogId}-content`}>
            This action is permanent. Are you sure you want to continue?
          </DialogContent>
          <DialogActions>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="primary">Delete file</Button>
            </DialogTrigger>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Cancel</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default Confirmation;

Controlling Open And Close

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

export const ControllingOpenAndClose = (): JSXElement => {
    const [open, setOpen] = React.useState(false);
    return (<Dialog open={open} onOpenChange={(event, data) => setOpen(data.open)}>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>
          <DialogContent>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam exercitationem cumque repellendus eaque
            est dolor eius expedita nulla ullam? Tenetur reprehenderit aut voluptatum impedit voluptates in natus iure
            cumque eaque?
          </DialogContent>
          <DialogActions>
            <Button appearance="primary">Do Something</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default ControllingOpenAndClose;

Custom Trigger

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import * as React from 'react';
import type { DialogTriggerChildProps } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

const CustomDialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerChildProps>((props, ref) => {
    return (<Button {...props} ref={ref}>
      Custom Trigger
    </Button>);
});

export const CustomTrigger = (): JSXElement => {
    return (<Dialog>
      <DialogTrigger disableButtonEnhancement>
        <CustomDialogTrigger />
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>
          <DialogContent>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam exercitationem cumque repellendus eaque
            est dolor eius expedita nulla ullam? Tenetur reprehenderit aut voluptatum impedit voluptates in natus iure
            cumque eaque?
          </DialogContent>
          <DialogActions>
            <Button appearance="primary">Do Something</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default CustomTrigger;

Fluid Actions

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const FluidActions = (): JSXElement => {
    return (<Dialog>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>
          <DialogContent>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam exercitationem cumque repellendus eaque
            est dolor eius expedita nulla ullam? Tenetur reprehenderit aut voluptatum impedit voluptates in natus iure
            cumque eaque?
          </DialogContent>
          <DialogActions fluid>
            <Button appearance="primary">Do Something</Button>
            <Button appearance="secondary">Something Else</Button>
            <Button appearance="secondary">Something Else</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default FluidActions;

Keep Rendered In The DOM

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const KeepRenderedInTheDOM = (): JSXElement => {
    return (<Dialog unmountOnClose={false}>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>

      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>

          <DialogContent>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
              dolore magna aliqua. Nisl pretium fusce id velit ut tortor. Leo vel fringilla est ullamcorper. Eget est
              lorem ipsum dolor sit amet consectetur adipiscing elit. In mollis nunc sed id semper risus in hendrerit
              gravida. Ullamcorper sit amet risus nullam eget felis eget. Dolor sed viverra ipsum nunc aliquet bibendum.
              Facilisi morbi tempus iaculis urna id volutpat. Porta non pulvinar neque laoreet suspendisse. Nunc id
              cursus metus aliquam eleifend mi in. A iaculis at erat pellentesque adipiscing commodo. Proin nibh nisl
              condimentum id. In hac habitasse platea dictumst vestibulum rhoncus est. Non tellus orci ac auctor augue
              mauris augue neque. Enim nulla aliquet porttitor lacus luctus accumsan tortor. Nascetur ridiculus mus
              mauris vitae ultricies leo integer. Ullamcorper eget nulla facilisi etiam dignissim. Leo in vitae turpis
              massa sed elementum tempus egestas sed.
            </p>

            <p>
              Ut enim blandit volutpat maecenas volutpat. Venenatis urna cursus eget nunc scelerisque viverra mauris.
              Neque aliquam vestibulum morbi blandit. Porttitor eget dolor morbi non. Nisi quis eleifend quam adipiscing
              vitae. Aliquam ultrices sagittis orci a scelerisque purus semper. Interdum varius sit amet mattis
              vulputate enim nulla aliquet. Ut sem viverra aliquet eget sit amet tellus cras. Sit amet tellus cras
              adipiscing enim eu turpis egestas. Amet cursus sit amet dictum sit amet justo donec enim. Neque gravida in
              fermentum et sollicitudin ac. Arcu cursus euismod quis viverra nibh cras pulvinar mattis nunc. Ultrices
              eros in cursus turpis massa tincidunt dui. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio
              pellentesque diam volutpat commodo sed egestas. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper.
              Ipsum nunc aliquet bibendum enim. Faucibus ornare suspendisse sed nisi lacus sed. Sapien nec sagittis
              aliquam malesuada bibendum arcu vitae elementum. Metus vulputate eu scelerisque felis imperdiet.
            </p>

            <p>
              Consequat interdum varius sit amet mattis vulputate enim. Amet cursus sit amet dictum sit amet justo. Eget
              aliquet nibh praesent tristique magna sit. Ut consequat semper viverra nam libero justo. Pharetra massa
              massa ultricies mi. Sem viverra aliquet eget sit amet. Pulvinar mattis nunc sed blandit libero volutpat
              sed. Pharetra diam sit amet nisl suscipit adipiscing bibendum. Consectetur adipiscing elit ut aliquam.
              Volutpat diam ut venenatis tellus in metus vulputate. Scelerisque in dictum non consectetur a erat.
              Venenatis lectus magna fringilla urna porttitor rhoncus. Vitae congue mauris rhoncus aenean vel elit.
              Neque laoreet suspendisse interdum consectetur. Ultrices gravida dictum fusce ut placerat orci. Bibendum
              ut tristique et egestas quis ipsum suspendisse. Mattis rhoncus urna neque viverra justo nec ultrices dui.
              Elit duis tristique sollicitudin nibh sit amet.
            </p>

            <p>
              At risus viverra adipiscing at. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit.
              Nunc vel risus commodo viverra maecenas. Sit amet est placerat in egestas erat imperdiet sed euismod.
              Turpis egestas maecenas pharetra convallis posuere. Egestas tellus rutrum tellus pellentesque eu tincidunt
              tortor aliquam. Dolor sit amet consectetur adipiscing elit. Aliquam purus sit amet luctus venenatis lectus
              magna fringilla. Scelerisque fermentum dui faucibus in ornare quam viverra. Egestas maecenas pharetra
              convallis posuere morbi leo urna. A diam sollicitudin tempor id eu nisl nunc. Lectus sit amet est
              placerat.
            </p>

            <p>
              Mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. At tellus at urna condimentum
              mattis pellentesque id nibh. Dui faucibus in ornare quam. Tincidunt id aliquet risus feugiat in ante metus
              dictum. Adipiscing commodo elit at imperdiet dui. Dolor sed viverra ipsum nunc. Sodales neque sodales ut
              etiam sit amet nisl. Hendrerit dolor magna eget est lorem ipsum dolor sit amet. Mattis molestie a iaculis
              at erat pellentesque adipiscing. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla.
              Fringilla urna porttitor rhoncus dolor purus.
            </p>

            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
              dolore magna aliqua. Nisl pretium fusce id velit ut tortor. Leo vel fringilla est ullamcorper. Eget est
              lorem ipsum dolor sit amet consectetur adipiscing elit. In mollis nunc sed id semper risus in hendrerit
              gravida. Ullamcorper sit amet risus nullam eget felis eget. Dolor sed viverra ipsum nunc aliquet bibendum.
              Facilisi morbi tempus iaculis urna id volutpat. Porta non pulvinar neque laoreet suspendisse. Nunc id
              cursus metus aliquam eleifend mi in. A iaculis at erat pellentesque adipiscing commodo. Proin nibh nisl
              condimentum id. In hac habitasse platea dictumst vestibulum rhoncus est. Non tellus orci ac auctor augue
              mauris augue neque. Enim nulla aliquet porttitor lacus luctus accumsan tortor. Nascetur ridiculus mus
              mauris vitae ultricies leo integer. Ullamcorper eget nulla facilisi etiam dignissim. Leo in vitae turpis
              massa sed elementum tempus egestas sed.
            </p>

            <p>
              Ut enim blandit volutpat maecenas volutpat. Venenatis urna cursus eget nunc scelerisque viverra mauris.
              Neque aliquam vestibulum morbi blandit. Porttitor eget dolor morbi non. Nisi quis eleifend quam adipiscing
              vitae. Aliquam ultrices sagittis orci a scelerisque purus semper. Interdum varius sit amet mattis
              vulputate enim nulla aliquet. Ut sem viverra aliquet eget sit amet tellus cras. Sit amet tellus cras
              adipiscing enim eu turpis egestas. Amet cursus sit amet dictum sit amet justo donec enim. Neque gravida in
              fermentum et sollicitudin ac. Arcu cursus euismod quis viverra nibh cras pulvinar mattis nunc. Ultrices
              eros in cursus turpis massa tincidunt dui. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio
              pellentesque diam volutpat commodo sed egestas. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper.
              Ipsum nunc aliquet bibendum enim. Faucibus ornare suspendisse sed nisi lacus sed. Sapien nec sagittis
              aliquam malesuada bibendum arcu vitae elementum. Metus vulputate eu scelerisque felis imperdiet.
            </p>

            <p>
              Consequat interdum varius sit amet mattis vulputate enim. Amet cursus sit amet dictum sit amet justo. Eget
              aliquet nibh praesent tristique magna sit. Ut consequat semper viverra nam libero justo. Pharetra massa
              massa ultricies mi. Sem viverra aliquet eget sit amet. Pulvinar mattis nunc sed blandit libero volutpat
              sed. Pharetra diam sit amet nisl suscipit adipiscing bibendum. Consectetur adipiscing elit ut aliquam.
              Volutpat diam ut venenatis tellus in metus vulputate. Scelerisque in dictum non consectetur a erat.
              Venenatis lectus magna fringilla urna porttitor rhoncus. Vitae congue mauris rhoncus aenean vel elit.
              Neque laoreet suspendisse interdum consectetur. Ultrices gravida dictum fusce ut placerat orci. Bibendum
              ut tristique et egestas quis ipsum suspendisse. Mattis rhoncus urna neque viverra justo nec ultrices dui.
              Elit duis tristique sollicitudin nibh sit amet.
            </p>
          </DialogContent>

          <DialogActions>
            <Button appearance="primary">Do Something</Button>

            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default KeepRenderedInTheDOM;

Motion Custom

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { motionTokens } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import { Switch } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    controls: {
        display: 'flex',
        flexDirection: 'column',
        gap: tokens.spacingVerticalS,
        marginBottom: tokens.spacingVerticalL,
        padding: tokens.spacingVerticalM,
        border: `${tokens.strokeWidthThicker} solid ${tokens.colorNeutralForeground3}`,
        borderRadius: tokens.borderRadiusMedium,
    },
});

export const MotionCustom = (): JSXElement => {
    const classes = useStyles();
    const [duration, setDuration] = React.useState(600);
    const [outScale, setOutScale] = React.useState(0.5);
    const [animateOpacity, setAnimateOpacity] = React.useState(true);
    const [backdropDuration, setBackdropDuration] = React.useState(300);
    const easing = motionTokens.curveDecelerateMid;
    return (<>
      <div className={classes.controls}>
        <Field label={`Surface duration: ${duration}ms`}>
          <Slider min={100} max={2000} step={50} value={duration} onChange={(_, data) => setDuration(data.value)}/>
        </Field>
        <Field label={`Surface outScale: ${outScale.toFixed(2)}`}>
          <Slider min={0} max={1} step={0.05} value={outScale} onChange={(_, data) => setOutScale(data.value)}/>
        </Field>
        <Field label={`Backdrop duration: ${backdropDuration}ms`}>
          <Slider min={0} max={1000} step={50} value={backdropDuration} onChange={(_, data) => setBackdropDuration(data.value)}/>
        </Field>
        <Switch label="Surface animateOpacity" checked={animateOpacity} onChange={(_, data) => setAnimateOpacity(data.checked)}/>
      </div>

      <Dialog surfaceMotion={{ duration, outScale, easing, animateOpacity }}>
        <DialogTrigger disableButtonEnhancement>
          <Button>Open Dialog</Button>
        </DialogTrigger>
        <DialogSurface backdropMotion={{ duration: backdropDuration }}>
          <DialogBody>
            <DialogTitle>Dialog with custom motion params</DialogTitle>
            <DialogContent>
              This dialog's surface animation is driven by direct <code>surfaceMotion</code> params (`duration`,
              `outScale`, `easing`, `animateOpacity`). Its backdrop fade is tuned independently via{' '}
              <code>backdropMotion</code> (`duration`).
            </DialogContent>
            <DialogActions>
              <DialogTrigger disableButtonEnhancement>
                <Button appearance="secondary">Close</Button>
              </DialogTrigger>
            </DialogActions>
          </DialogBody>
        </DialogSurface>
      </Dialog>
    </>);
};

export default MotionCustom;

No Focusable Element

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import * as React from 'react';

export const NoFocusableElement = (): JSXElement => {
    return (<>
      <Dialog>
        <DialogTrigger disableButtonEnhancement>
          <Button>Open modal dialog</Button>
        </DialogTrigger>
        <DialogSurface>
          <DialogBody>
            <DialogTitle>Dialog Title</DialogTitle>
            <DialogContent>
              <p>⛔️ A Dialog without focusable elements is not recommended!</p>
              <p>✅ Escape key works</p>
              <p>✅ Backdrop click still works to ensure this modal can be closed</p>
            </DialogContent>
          </DialogBody>
        </DialogSurface>
      </Dialog>
      <Dialog modalType="non-modal">
        <DialogTrigger disableButtonEnhancement>
          <Button>Open non-modal dialog</Button>
        </DialogTrigger>
        <DialogSurface>
          <DialogBody>
            <DialogTitle action={null}>Dialog Title</DialogTitle>
            <DialogContent>
              <p>⛔️ A modal Dialog without focusable elements is not recommended!</p>
              <p>✅ Escape key works</p>
            </DialogContent>
          </DialogBody>
        </DialogSurface>
      </Dialog>
    </>);
};

export default NoFocusableElement;

Non Modal

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import * as React from 'react';

export const NonModal = (): JSXElement => {
    return (<Dialog modalType="non-modal">
      <DialogTrigger disableButtonEnhancement>
        <Button>Open non-modal dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Non-modal dialog title</DialogTitle>
          <DialogContent>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aliquid, explicabo repudiandae impedit doloribus
            laborum quidem maxime dolores perspiciatis non ipsam, nostrum commodi quis autem sequi, incidunt cum?
            Consequuntur, repellendus nostrum?
          </DialogContent>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default NonModal;

Scrolling Long Content

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const ScrollingLongContent = (): JSXElement => {
    return (<Dialog>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Dialog title</DialogTitle>
          <DialogContent>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
              dolore magna aliqua. Nisl pretium fusce id velit ut tortor. Leo vel fringilla est ullamcorper. Eget est
              lorem ipsum dolor sit amet consectetur adipiscing elit. In mollis nunc sed id semper risus in hendrerit
              gravida. Ullamcorper sit amet risus nullam eget felis eget. Dolor sed viverra ipsum nunc aliquet bibendum.
              Facilisi morbi tempus iaculis urna id volutpat. Porta non pulvinar neque laoreet suspendisse. Nunc id
              cursus metus aliquam eleifend mi in. A iaculis at erat pellentesque adipiscing commodo. Proin nibh nisl
              condimentum id. In hac habitasse platea dictumst vestibulum rhoncus est. Non tellus orci ac auctor augue
              mauris augue neque. Enim nulla aliquet porttitor lacus luctus accumsan tortor. Nascetur ridiculus mus
              mauris vitae ultricies leo integer. Ullamcorper eget nulla facilisi etiam dignissim. Leo in vitae turpis
              massa sed elementum tempus egestas sed.
            </p>
            <p>
              Ut enim blandit volutpat maecenas volutpat. Venenatis urna cursus eget nunc scelerisque viverra mauris.
              Neque aliquam vestibulum morbi blandit. Porttitor eget dolor morbi non. Nisi quis eleifend quam adipiscing
              vitae. Aliquam ultrices sagittis orci a scelerisque purus semper. Interdum varius sit amet mattis
              vulputate enim nulla aliquet. Ut sem viverra aliquet eget sit amet tellus cras. Sit amet tellus cras
              adipiscing enim eu turpis egestas. Amet cursus sit amet dictum sit amet justo donec enim. Neque gravida in
              fermentum et sollicitudin ac. Arcu cursus euismod quis viverra nibh cras pulvinar mattis nunc. Ultrices
              eros in cursus turpis massa tincidunt dui. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio
              pellentesque diam volutpat commodo sed egestas. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper.
              Ipsum nunc aliquet bibendum enim. Faucibus ornare suspendisse sed nisi lacus sed. Sapien nec sagittis
              aliquam malesuada bibendum arcu vitae elementum. Metus vulputate eu scelerisque felis imperdiet.
            </p>
            <p>
              Consequat interdum varius sit amet mattis vulputate enim. Amet cursus sit amet dictum sit amet justo. Eget
              aliquet nibh praesent tristique magna sit. Ut consequat semper viverra nam libero justo. Pharetra massa
              massa ultricies mi. Sem viverra aliquet eget sit amet. Pulvinar mattis nunc sed blandit libero volutpat
              sed. Pharetra diam sit amet nisl suscipit adipiscing bibendum. Consectetur adipiscing elit ut aliquam.
              Volutpat diam ut venenatis tellus in metus vulputate. Scelerisque in dictum non consectetur a erat.
              Venenatis lectus magna fringilla urna porttitor rhoncus. Vitae congue mauris rhoncus aenean vel elit.
              Neque laoreet suspendisse interdum consectetur. Ultrices gravida dictum fusce ut placerat orci. Bibendum
              ut tristique et egestas quis ipsum suspendisse. Mattis rhoncus urna neque viverra justo nec ultrices dui.
              Elit duis tristique sollicitudin nibh sit amet.
            </p>
            <p>
              At risus viverra adipiscing at. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit.
              Nunc vel risus commodo viverra maecenas. Sit amet est placerat in egestas erat imperdiet sed euismod.
              Turpis egestas maecenas pharetra convallis posuere. Egestas tellus rutrum tellus pellentesque eu tincidunt
              tortor aliquam. Dolor sit amet consectetur adipiscing elit. Aliquam purus sit amet luctus venenatis lectus
              magna fringilla. Scelerisque fermentum dui faucibus in ornare quam viverra. Egestas maecenas pharetra
              convallis posuere morbi leo urna. A diam sollicitudin tempor id eu nisl nunc. Lectus sit amet est
              placerat.
            </p>
            <p>
              Mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. At tellus at urna condimentum
              mattis pellentesque id nibh. Dui faucibus in ornare quam. Tincidunt id aliquet risus feugiat in ante metus
              dictum. Adipiscing commodo elit at imperdiet dui. Dolor sed viverra ipsum nunc. Sodales neque sodales ut
              etiam sit amet nisl. Hendrerit dolor magna eget est lorem ipsum dolor sit amet. Mattis molestie a iaculis
              at erat pellentesque adipiscing. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla.
              Fringilla urna porttitor rhoncus dolor purus.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
              dolore magna aliqua. Nisl pretium fusce id velit ut tortor. Leo vel fringilla est ullamcorper. Eget est
              lorem ipsum dolor sit amet consectetur adipiscing elit. In mollis nunc sed id semper risus in hendrerit
              gravida. Ullamcorper sit amet risus nullam eget felis eget. Dolor sed viverra ipsum nunc aliquet bibendum.
              Facilisi morbi tempus iaculis urna id volutpat. Porta non pulvinar neque laoreet suspendisse. Nunc id
              cursus metus aliquam eleifend mi in. A iaculis at erat pellentesque adipiscing commodo. Proin nibh nisl
              condimentum id. In hac habitasse platea dictumst vestibulum rhoncus est. Non tellus orci ac auctor augue
              mauris augue neque. Enim nulla aliquet porttitor lacus luctus accumsan tortor. Nascetur ridiculus mus
              mauris vitae ultricies leo integer. Ullamcorper eget nulla facilisi etiam dignissim. Leo in vitae turpis
              massa sed elementum tempus egestas sed.
            </p>
            <p>
              Ut enim blandit volutpat maecenas volutpat. Venenatis urna cursus eget nunc scelerisque viverra mauris.
              Neque aliquam vestibulum morbi blandit. Porttitor eget dolor morbi non. Nisi quis eleifend quam adipiscing
              vitae. Aliquam ultrices sagittis orci a scelerisque purus semper. Interdum varius sit amet mattis
              vulputate enim nulla aliquet. Ut sem viverra aliquet eget sit amet tellus cras. Sit amet tellus cras
              adipiscing enim eu turpis egestas. Amet cursus sit amet dictum sit amet justo donec enim. Neque gravida in
              fermentum et sollicitudin ac. Arcu cursus euismod quis viverra nibh cras pulvinar mattis nunc. Ultrices
              eros in cursus turpis massa tincidunt dui. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio
              pellentesque diam volutpat commodo sed egestas. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper.
              Ipsum nunc aliquet bibendum enim. Faucibus ornare suspendisse sed nisi lacus sed. Sapien nec sagittis
              aliquam malesuada bibendum arcu vitae elementum. Metus vulputate eu scelerisque felis imperdiet.
            </p>
            <p>
              Consequat interdum varius sit amet mattis vulputate enim. Amet cursus sit amet dictum sit amet justo. Eget
              aliquet nibh praesent tristique magna sit. Ut consequat semper viverra nam libero justo. Pharetra massa
              massa ultricies mi. Sem viverra aliquet eget sit amet. Pulvinar mattis nunc sed blandit libero volutpat
              sed. Pharetra diam sit amet nisl suscipit adipiscing bibendum. Consectetur adipiscing elit ut aliquam.
              Volutpat diam ut venenatis tellus in metus vulputate. Scelerisque in dictum non consectetur a erat.
              Venenatis lectus magna fringilla urna porttitor rhoncus. Vitae congue mauris rhoncus aenean vel elit.
              Neque laoreet suspendisse interdum consectetur. Ultrices gravida dictum fusce ut placerat orci. Bibendum
              ut tristique et egestas quis ipsum suspendisse. Mattis rhoncus urna neque viverra justo nec ultrices dui.
              Elit duis tristique sollicitudin nibh sit amet.
            </p>
            <p>
              At risus viverra adipiscing at. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit.
              Nunc vel risus commodo viverra maecenas. Sit amet est placerat in egestas erat imperdiet sed euismod.
              Turpis egestas maecenas pharetra convallis posuere. Egestas tellus rutrum tellus pellentesque eu tincidunt
              tortor aliquam. Dolor sit amet consectetur adipiscing elit. Aliquam purus sit amet luctus venenatis lectus
              magna fringilla. Scelerisque fermentum dui faucibus in ornare quam viverra. Egestas maecenas pharetra
              convallis posuere morbi leo urna. A diam sollicitudin tempor id eu nisl nunc. Lectus sit amet est
              placerat.
            </p>
            <p>
              Mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. At tellus at urna condimentum
              mattis pellentesque id nibh. Dui faucibus in ornare quam. Tincidunt id aliquet risus feugiat in ante metus
              dictum. Adipiscing commodo elit at imperdiet dui. Dolor sed viverra ipsum nunc. Sodales neque sodales ut
              etiam sit amet nisl. Hendrerit dolor magna eget est lorem ipsum dolor sit amet. Mattis molestie a iaculis
              at erat pellentesque adipiscing. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla.
              Fringilla urna porttitor rhoncus dolor purus.
            </p>
          </DialogContent>
          <DialogActions>
            <Button appearance="primary">Do Something</Button>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="secondary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default ScrollingLongContent;

Title Custom Action

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { Dismiss24Regular } from "@fluentui/react-icons";
import { DialogContent } from "@coreai-ds/react-components";
import * as React from 'react';

export const TitleCustomAction = (): JSXElement => {
    return (<Dialog>
      <DialogTrigger disableButtonEnhancement>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle action={<DialogTrigger action="close">
                <Button appearance="subtle" aria-label="close" icon={<Dismiss24Regular />}/>
              </DialogTrigger>}>
            Dialog title
          </DialogTitle>
          <DialogContent>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aliquid, explicabo repudiandae impedit doloribus
            laborum quidem maxime dolores perspiciatis non ipsam, nostrum commodi quis autem sequi, incidunt cum?
            Consequuntur, repellendus nostrum?
          </DialogContent>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default TitleCustomAction;

Title No Action

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import * as React from 'react';

export const TitleNoAction = (): JSXElement => {
    return (<Dialog modalType="non-modal">
      <DialogTrigger disableButtonEnhancement>
        <Button>Open non-modal dialog</Button>
      </DialogTrigger>
      <DialogSurface>
        <DialogBody>
          <DialogTitle action={null}>Non-modal dialog title without an action</DialogTitle>
          <DialogContent>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aliquid, explicabo repudiandae impedit doloribus
            laborum quidem maxime dolores perspiciatis non ipsam, nostrum commodi quis autem sequi, incidunt cum?
            Consequuntur, repellendus nostrum?
          </DialogContent>
          <DialogActions>
            <DialogTrigger disableButtonEnhancement>
              <Button appearance="primary">Close</Button>
            </DialogTrigger>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>);
};

export default TitleNoAction;

Trigger Outside Dialog

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { useRestoreFocusTarget } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Dialog } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";

export const TriggerOutsideDialog = (): JSXElement => {
    const [open, setOpen] = React.useState(false);
    const restoreFocusTargetAttribute = useRestoreFocusTarget();
    return (<>
      <Button 
    // restoreFocusTargetAttribute ensures that focus is restored to this button when the dialog closes
    {...restoreFocusTargetAttribute} onClick={() => {
            // it is the user responsibility to open the dialog
            setOpen(true);
        }}>
        Open Dialog
      </Button>

      <Dialog 
    // this controls the dialog open state
    open={open} onOpenChange={(event, data) => {
            // it is the users responsibility to react accordingly to the open state change
            setOpen(data.open);
        }}>
        <DialogSurface>
          <DialogBody>
            <DialogTitle>Dialog title</DialogTitle>
            <DialogContent>
              Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam exercitationem cumque repellendus eaque
              est dolor eius expedita nulla ullam? Tenetur reprehenderit aut voluptatum impedit voluptates in natus iure
              cumque eaque?
            </DialogContent>

            <DialogActions>
              <Button appearance="primary">Do Something</Button>
              {/* DialogTrigger inside of a Dialog still works properly */}
              <DialogTrigger disableButtonEnhancement>
                <Button appearance="secondary">Close</Button>
              </DialogTrigger>
            </DialogActions>
          </DialogBody>
        </DialogSurface>
      </Dialog>
    </>);
};

export default TriggerOutsideDialog;

With Form

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { Dialog } from "@coreai-ds/react-components";
import { DialogTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DialogSurface } from "@coreai-ds/react-components";
import { DialogBody } from "@coreai-ds/react-components";
import { DialogTitle } from "@coreai-ds/react-components";
import { DialogContent } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { DialogActions } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    content: {
        display: 'flex',
        flexDirection: 'column',
        rowGap: '10px',
    },
});

export const WithForm = (): JSXElement => {
    const styles = useStyles();
    const handleSubmit = (ev: React.FormEvent) => {
        ev.preventDefault();
        alert('form submitted!');
    };
    return (<Dialog modalType="non-modal">
      <DialogTrigger disableButtonEnhancement>
        <Button>Open formulary dialog</Button>
      </DialogTrigger>
      <DialogSurface aria-describedby={undefined}>
        <form onSubmit={handleSubmit}>
          <DialogBody>
            <DialogTitle>Dialog title</DialogTitle>
            <DialogContent className={styles.content}>
              <Label required htmlFor={'email-input'}>
                Email input
              </Label>
              <Input required type="email" id={'email-input'}/>
              <Label required htmlFor={'password-input'}>
                Password input
              </Label>
              <Input required type="password" id={'password-input'}/>
            </DialogContent>
            <DialogActions>
              <Button type="submit" appearance="primary">
                Submit
              </Button>
              <DialogTrigger disableButtonEnhancement>
                <Button appearance="secondary">Close</Button>
              </DialogTrigger>
            </DialogActions>
          </DialogBody>
        </form>
      </DialogSurface>
    </Dialog>);
};

export default WithForm;