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 { TeachingPopover } from "@coreai-ds/react-components";
import { TeachingPopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { TeachingPopoverSurface } from "@coreai-ds/react-components";
import { TeachingPopoverHeader } from "@coreai-ds/react-components";
import { TeachingPopoverBody } from "@coreai-ds/react-components";
import { Image } from "@coreai-ds/react-components";
import { TeachingPopoverTitle } from "@coreai-ds/react-components";
import { TeachingPopoverFooter } from "@coreai-ds/react-components";
import * as React from 'react';

const swapImage = 'https://fabricweb.azureedge.net/fabric-website/assets/images/wireframe/image-square.png';

export const Default = (): JSXElement => (<TeachingPopover>
    <TeachingPopoverTrigger>
      <Button>TeachingPopover trigger</Button>
    </TeachingPopoverTrigger>
    <TeachingPopoverSurface>
      <TeachingPopoverHeader>Tips</TeachingPopoverHeader>
      <TeachingPopoverBody media={<Image alt="test image" fit="cover" src={swapImage}/>}>
        <TeachingPopoverTitle>Teaching Bubble Title</TeachingPopoverTitle>
        <div>This is a teaching popover body</div>
      </TeachingPopoverBody>
      <TeachingPopoverFooter primary="Learn more" secondary="Got it"/>
    </TeachingPopoverSurface>
  </TeachingPopover>);

export default Default;

Resources

Behavior and states

  • Teaching popovers live above the UI.
  • They can include multi-step learning modules and a section of animation or imagery.
  • The component size flexes with its content.
  • It lives above the UI and has many optional capabilities such has multi-stepped learning modules and a section of animation or imagery.
  • The size of the component flexes with the content to create a contextual learning experience for the user.
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.

TeachingPopover API

An extension class of Popover which defaults to withArrow and FocusTrap enabled.

interface TeachingPopoverProps {
  /**
   * A popover can appear styled with brand or inverted.
   * When not specified, the default style is used.
   */
  appearance?: "brand" | "inverted";

  /**
   * Can contain two children including `PopoverTrigger` and `PopoverSurface`.
   * Alternatively can only contain `PopoverSurface` if using a custom `target`.
   */
  children: JSXElement | [JSXElement, JSXElement];

  /**
   * Flag to close the Popover when an iframe outside a PopoverSurface is focused
   * @default true
   */
  closeOnIframeFocus?: boolean;

  /**
   * Close when scroll outside of it
   * @default false
   */
  closeOnScroll?: boolean;

  /**
   * Used to set the initial open state of the Popover in uncontrolled mode
   * @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,
   * making navigation leak from the trapped area back to the browser toolbar and vice-versa.
   * @default false
   */
  inertTrapFocus?: boolean;

  /**
   * Popovers are rendered out of DOM order on `document.body` by default, use this to render the popover in DOM order
   * @default false
   */
  inline?: boolean;

  /**
   * Must be used with the `trapFocus` prop
   * Enables older Fluent UI focus trap behavior where the user
   * cannot tab into the window outside of the document. This is now
   * non-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.
   * @deprecated this behavior is default provided now, to opt-out of it in favor of standard behavior use the `inertTrapFocus` property
   */
  legacyTrapFocus?: boolean;

  /**
   * 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;

  /**
   * Sets the delay for closing popover on mouse leave
   */
  mouseLeaveDelay?: number;

  /**
   * Call back when the component requests to change value
   * The `open` value is used as a hint when directly controlling the component
   */
  onOpenChange?: ((e: OpenPopoverEvents, data: OnOpenChangeData) => void);

  /**
   * Controls the opening of the Popover
   * @default false
   */
  open?: boolean;

  /**
   * Flag to open the Popover as a context menu. Disables all other interactions
   * @default false
   */
  openOnContext?: boolean;

  /**
   * Flag to open the Popover by hovering the trigger
   * @default false
   */
  openOnHover?: boolean;

  /**
   * Configures the position of the Popover.
   * Explore [Positioning docs](https://react.fluentui.dev/?path=/docs/concepts-developer-positioning-components--docs) for more options.
   */
  positioning?: PositioningShorthand;

  /**
   * Determines popover padding and arrow size
   * @default medium
   */
  size?: "small" | "medium" | "large";

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

  /**
   * Should trap focus
   * @default false
   */
  trapFocus?: boolean;

  /**
   * By default Popover focuses the first focusable element in PopoverSurface on open.
   * Specify `disableAutoFocus` to prevent this behavior.
   * @default false
   */
  unstable_disableAutoFocus?: boolean;

  /**
   * Display an arrow pointing to the target.
   * @default false
   */
  withArrow?: boolean;
}

TeachingPopoverBody API

Define a styled TeachingPopoverBody, using the useTeachingPopoverBody_unstable and useTeachingPopoverBodyStyles_unstable hooks.

TeachingPopoverBody is used to host content within a TeachingPopover, and provides a standardized media slot

interface TeachingPopoverBodyProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * Optional Media Content.
   */
  media?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  mediaLength?: "medium" | "short" | "tall";

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverCarousel API

Define a styled TeachingPopoverCarousel, using the useTeachingPopoverCarousel_unstable and useTeachingPopoverCarouselStyles_unstable hooks.

TeachingPopoverCarousel injects context providers that are required for TeachingPopoverCarouselCard display and navigation functionality

interface TeachingPopoverCarouselProps {
  /**
   * Localizes the string used to announce carousel page changes to screen reader users
   * Defaults to: undefined
   */
  announcement?: ((newValue: string) => string);

  as?: "div";

  children?: any;

  className?: string;

  /**
   * The initial page to display in uncontrolled mode.
   */
  defaultValue?: string | number | readonly string[];

  /**
   * Callback to notify when the final button step of a carousel has been activated.
   */
  onFinish?: EventHandler<CarouselValueChangeData>;

  /**
   * Callback to notify a page change.
   */
  onValueChange?: EventHandler<CarouselValueChangeData>;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;

  /**
   * The value of the currently active page.
   */
  value?: string;
}

TeachingPopoverCarouselCard API

Define a styled TeachingPopoverCarouselCard, using the useTeachingPopoverCarouselCard_unstable and useTeachingPopoverCarouselCardStyles_unstable hooks.

TeachingPopoverCarouselCard is the definition of a single page view within the carousel, they are shown one at a time and can be navigated through sequentially.

interface TeachingPopoverCarouselCardProps {
  as?: "div";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;

  /**
   * The value used to identify a page,
   * it should be unique and is necessary for pagination
   */
  value: string;
}

TeachingPopoverCarouselFooter API

Define a styled TeachingPopoverCarouselFooter, using the useTeachingPopoverCarouselFooter_unstable and useTeachingPopoverCarouselFooterStyles_unstable hooks.

TeachingPopoverCarouselFooter contains previous/next buttons configured for carousel navigation, and a root slot for page count and/or page index navigation.

interface TeachingPopoverCarouselFooterProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * The text to be displayed on the final step of carousel
   */
  finalStepText: string;

  /**
   * The text to be displayed on the initial step of carousel
   */
  initialStepText: string;

  /**
   * Controls whether buttons will be centered (balanced) or right aligned
   * Defaults to 'centered'.
   */
  layout?: "offset" | "centered";

  /**
   * The next button slot.
   */
  next: NonNullable<WithSlotShorthandValue<(Omit<TeachingPopoverCarouselFooterButtonSlots, "root"> & Omit<{ as?: "button" | undefined; } & Omit<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement> | null | undefined; }, "children"> & { children?: any; } & Pick<ARIAButtonProps<ARIAButtonType>, "disabled" | "disabledFocusable">, "ref"> & Omit<ButtonSlots, "root"> & { appearance?: "outline" | "subtle" | "secondary" | "primary" | "transparent" | undefined; disabledFocusable?: boolean | undefined; disabled?: boolean | undefined; iconPosition?: "before" | "after" | undefined; shape?: "circular" | "rounded" | "square" | undefined; size?: ButtonSize | undefined; } & { navType: "next" | "prev"; altText: ReactNode; }) | (Omit<TeachingPopoverCarouselFooterButtonSlots, "root"> & Omit<{ as: "a"; } & Omit<Omit<DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & { ref?: ((instance: HTMLAnchorElement | null) => void) | RefObject<HTMLAnchorElement> | null | undefined; }, "children"> & { children?: any; } & Pick<ARIAButtonProps<ARIAButtonType>, "disabled" | "disabledFocusable">, "ref"> & Omit<ButtonSlots, "root"> & { appearance?: "outline" | "subtle" | "secondary" | "primary" | "transparent" | undefined; disabledFocusable?: boolean | undefined; disabled?: boolean | undefined; iconPosition?: "before" | "after" | undefined; shape?: "circular" | "rounded" | "square" | undefined; size?: ButtonSize | undefined; } & { navType: "next" | "prev"; altText: ReactNode; })> | null>;

  /**
   * The previous button slot.
   */
  previous?: WithSlotShorthandValue<(Omit<TeachingPopoverCarouselFooterButtonSlots, "root"> & Omit<{ as?: "button"; } & Omit<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement> | null; }, "children"> & { children?: any; } & Pick<ARIAButtonProps<ARIAButtonType>, "disabled" | "disabledFocusable">, "ref"> & Omit<ButtonSlots, "root"> & { appearance?: "outline" | "subtle" | "secondary" | "primary" | "transparent" | undefined; disabledFocusable?: boolean | undefined; disabled?: boolean | undefined; iconPosition?: "before" | "after" | undefined; shape?: "circular" | "rounded" | "square" | undefined; size?: ButtonSize | undefined; } & { navType: "next" | "prev"; altText: ReactNode; }) | (Omit<TeachingPopoverCarouselFooterButtonSlots, "root"> & Omit<{ as: "a"; } & Omit<Omit<DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & { ref?: ((instance: HTMLAnchorElement | null) => void) | RefObject<HTMLAnchorElement> | null | undefined; }, "children"> & { children?: any; } & Pick<ARIAButtonProps<ARIAButtonType>, "disabled" | "disabledFocusable">, "ref"> & Omit<ButtonSlots, "root"> & { appearance?: "outline" | "subtle" | "secondary" | "primary" | "transparent" | undefined; disabledFocusable?: boolean | undefined; disabled?: boolean | undefined; iconPosition?: "before" | "after" | undefined; shape?: "circular" | "rounded" | "square" | undefined; size?: ButtonSize | undefined; } & { navType: "next" | "prev"; altText: ReactNode; })> | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverCarouselNav API

Define a styled TeachingPopoverCarouselNav, using the useTeachingPopoverCarouselNav_unstable and useTeachingPopoverCarouselNavStyles_unstable hooks.

TeachingPopoverCarouselNav provides an index-based pagination list to jump to any page within the carousel.

interface TeachingPopoverCarouselNavProps {
  as?: "div";

  children: NavButtonRenderFunction;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverCarouselNavButton API

TeachingPopoverCarouselNavButton is a button to jump to a single page within TeachingPopoverCarousel

It's value is injected via context and must be wrapped with a ValueIdContextProvider (automatically handled via TeachingPopoverCarouselNav)

interface TeachingPopoverCarouselNavButtonProps {
  as?: "a" | "button";

  children?: any;

  className?: string;

  disabled?: boolean;

  /**
   * When set, allows the button to be focusable even when it has been disabled.
   * This is used in scenarios where it is important to keep a consistent tab order
   * for screen reader and keyboard users. The primary example of this
   * pattern is when the disabled button is in a menu or a commandbar and is seldom used for standalone buttons.
   * @default false
   */
  disabledFocusable?: boolean;

  ref?: Ref<HTMLAnchorElement | HTMLButtonElement>;

  style?: CSSProperties;
}

TeachingPopoverCarouselPageCount API

TeachingPopoverCarouselPageCount is a simple interface for rendering based on current and total page count

The child render function will provide both current and total page numbers for customization.

interface TeachingPopoverCarouselPageCountProps {
  as?: "div";

  children: TeachingPopoverCarouselPageCountRenderFunction;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverFooter API

Define a styled TeachingPopoverFooter, using the useTeachingPopoverFooter_unstable and useTeachingPopoverFooterStyles_unstable hooks.

TeachingPopoverFooter will provide both a secondary and primary button for the TeachingPopover, and handle Popover functionality such as closing the popup.

Users must provide the localized text for each button within the footer via slots.

interface TeachingPopoverFooterProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * Enables stylization to a horizontal or vertical stack of button layouts.
   * Defaults to horizontal
   */
  footerLayout?: "horizontal" | "vertical";

  /**
   * The primary button slot.
   */
  primary: NonNullable<WithSlotShorthandValue<ButtonProps & RefAttributes<HTMLAnchorElement | HTMLButtonElement>> | null>;

  ref?: Ref<HTMLDivElement>;

  /**
   * The secondary button slot.
   */
  secondary?: WithSlotShorthandValue<ButtonProps & RefAttributes<HTMLAnchorElement | HTMLButtonElement>> | null;

  style?: CSSProperties;
}

TeachingPopoverHeader API

Define a styled TeachingPopoverHeader, using the useTeachingPopoverHeader_unstable and useTeachingPopoverHeaderStyles_unstable hooks.

TeachingPopoverHeader is an info subtitle located at the top of the popover, it provides a dismiss button by default (can be nulled) and an info-tip icon that can be overridden or removed, subtitle displayed will be the children elements of TeachingPopoverHeader.

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

  children?: any;

  className?: string;

  /**
   * The component to be used as close button in heading
   */
  dismissButton?: WithSlotShorthandValue<{ as?: "button"; } & Omit<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * Initial icon slot rendered before children content in heading.
   */
  icon?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverSurface API

TeachingPopoverSurface component renders react children in a positioned box

TeachingPopoverSurface is a direct extension of PopoverSurface, with it's own styling context hooks available.

interface TeachingPopoverSurfaceProps {
  as?: "div";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverTitle API

Define a styled TeachingPopoverTitle, using the useTeachingPopoverTitle_unstable and useTeachingPopoverTitleStyles_unstable hooks.

TeachingPopoverTitle is similar to TeachingPopoverHeader, but it is intended to be placed within a TeachingPopoverBody TeachingPopoverTitle can also optionally render a dismiss button, however this should only be enabled when there is no TeachingPopoverHeader/dismiss.

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

  children?: any;

  className?: string;

  /**
   * An alternate close button path if not placed in the TeachingPopoverHeader
   */
  dismissButton?: WithSlotShorthandValue<{ as?: "button"; } & Omit<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

TeachingPopoverTrigger API

Direct extension of PopoverTrigger - Wraps a trigger element as an only child and adds the necessary event handling to open a teaching bubble.

interface TeachingPopoverTriggerProps {
  children?: ReactElement<any, string | JSXElementConstructor<any>> | ((props: PopoverTriggerChildProps<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.

Appearance Brand

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 { TeachingPopover } from "@coreai-ds/react-components";
import { TeachingPopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { TeachingPopoverSurface } from "@coreai-ds/react-components";
import { TeachingPopoverHeader } from "@coreai-ds/react-components";
import { TeachingPopoverBody } from "@coreai-ds/react-components";
import { Image } from "@coreai-ds/react-components";
import { TeachingPopoverTitle } from "@coreai-ds/react-components";
import { TeachingPopoverFooter } from "@coreai-ds/react-components";
import * as React from 'react';

const swapImage = 'https://fabricweb.azureedge.net/fabric-website/assets/images/wireframe/image-square.png';

export const AppearanceBrand = (): JSXElement => (<TeachingPopover appearance="brand">
    <TeachingPopoverTrigger>
      <Button>TeachingPopover trigger</Button>
    </TeachingPopoverTrigger>
    <TeachingPopoverSurface>
      <TeachingPopoverHeader>Tips</TeachingPopoverHeader>
      <TeachingPopoverBody media={<Image alt="test image" fit="cover" src={swapImage}/>}>
        <TeachingPopoverTitle>Teaching Bubble Title</TeachingPopoverTitle>
        <div>This is a teaching popover body</div>
      </TeachingPopoverBody>
      <TeachingPopoverFooter primary="Learn more" secondary="Got it"/>
    </TeachingPopoverSurface>
  </TeachingPopover>);

export default AppearanceBrand;