Skip to main content

V1Flyout

Static component with child elements that displays from the right or bottom side of the window and overlays all other content until it is closed.

github
View source code
V1 components are not compatible with the flattenTokens hook or the DefaultPropsProvider, nor can they be themed using component-level design tokens.
A future redesign will deliver V2 versions of these components and make them compatible with these features.
import { V1Flyout } from '@uhg-abyss/web/ui/Flyout';
      () => {
      return (
      <React.Fragment>
      <Text asElement="p" css={{ 'abyss-text-root': { margin: '0 0 10px' } }}>
      V1Flyout example starts on the right of the screen. See 'V1Flyout
      Label'.
      </Text>
      <Text asElement="p" css={{ 'abyss-text-root': { margin: '0 0 10px' } }}>
      This V1Flyout can be opened with the access key 'F'; the underlined 'F'
      in the label is to indicate this.
      </Text>
      <Text asElement="p" css={{ 'abyss-text-root': { margin: '0 0 10px' } }}>
      Press Ctrl + Option + F on Mac (Chrome/Safari) or Alt + F on Windows
      (Chrome).
      </Text>
      <Text asElement="p" css={{ 'abyss-text-root': { margin: '0 0 10px' } }}>
      See the Access Key section below for more details, including a full list
      of shortcuts.
      </Text>
      <V1Flyout
      position="right"
      label="V1Flyout Label"
      indent="60%"
      variant="filled"
      >
      <styled.div
      css={{
      padding: '$web.semantic.spacing.scale.md',
      }}
      >
      <Text
      asElement="p"
      css={{ 'abyss-text-root': { margin: '0 0 10px' } }}
      >
      Here is the V1Flyout content from the sandbox example.
      </Text>
      </styled.div>
      </V1Flyout>
      </React.Fragment>
      );
      };

      Access key​

      The accessKey prop sets a keyboard shortcut to open the V1Flyout from anywhere on the page. This is recommended for accessibility purposes, for users who navigate with the keyboard.

      By default, accessKey is set to the first character of the label prop, assuming a label is provided. As a visual indicator, the first character of the label is underlined and bolded to show the access key. To disable this, use the disableUnderlineAccessKey prop.

      If a custom access key is set via the prop, no character is underlined/bolded in the label.

      To disable the accessKey entirely, set the prop to an empty string.

      The value must consist of a single printable character. This forms part of a keyboard shortcut, which varies depending on the browser and operating system.

      For Chrome and Safari on Mac, the shortcut is Ctrl + Option + key. For Chrome on Windows, the shortcut is Alt + key.

      See the MDN Web Docsopens in a new window for more information, including browser-specific shortcuts.

      Button only​

      The primary function of the V1Flyout component, as the title suggests, is to expand a small V1Flyout drawer via a sticky button.

      Additionally, the V1Flyout component can be used as a button, to do something like open a modal or a link. This is achieved by passing the buttonOnly prop.

      Use the onClick prop to customize the action of the button, such as to open a modal.

      To use the button as a link, see the href prop.

      Variant​

      The variant prop offers two color/styling options for the button - 'filled' and 'outlined'.

      'filled' is designed for the classic flyout scenario where a small drawer can expand out.

      'outlined' is a secondary style, and is useful for actions such as going to an external feedback form via the onClick callback. It can technically be used in the same way as the filled variant, too. For example, if there are 2 different Flyouts on the same page, one can be filled and the other outlined.

      Positioning​

      Use the position prop to change where the V1Flyout is anchored on the screen. Options include 'right' or 'bottom' The default position is 'right'.

      The indent prop offsets the V1Flyout from its anchored edge. This prop accepts values like pixels ('px') or percentages ('%') to represent the offset distance. The default indent is '35%'.

      • With position="right", increasing the indent value moves the V1Flyout vertically, away from the bottom of the screen.
      • For position="bottom", increasing the indent values moves the V1Flyout horizontally away from the right side of the screen.

      <V1Flyout> can be anchored to either the right side or bottom of a screen, as specified by the required position prop.

      Further customization of the <V1Flyout> position can be made with the indent prop. If the position is 'bottom', the indent specifies how far up from the bottom of the screen the <V1Flyout> is positioned. If the position is 'right', the indent specifies how far up from the right the <V1Flyout> is positioned.

      indent examples include '30px' or '50%'.

      href​

      The href prop allows the V1Flyout to act as a link. When the V1Flyout is clicked, the user is redirected to the specified URL.

      See the ButtonOnly example for a use case.

      Height and width​

      The height and width props set the size of the V1Flyout's opened content drawer.

      The Abyss design team has specified a recommended height and width:

      • height should be between 208px and 320px (default: 208px)
      • width should be between 400px and 504px (default: 400px)

      When the variant is 'filled', and the position is 'right', the height of the button is fixed to match the height of the opened menu. Otherwise, the button is sized dynamically.

      Icon​

      An icon can be added to the left side of the V1Flyout button by passing an Icon or IconSymbol component to the icon prop.

      The left icon is customizable. The right icon is reserved for a chevron icon that can be toggled on or off with the showArrowIcon prop - see below.

      For examples, see Positioning or Variant.

      Show arrow icon​

      The showArrowIcon prop displays a chevron icon on the right side of the V1Flyout button. This is useful for indicating that the button expands a drawer.

      Overflow scrolling​

      When the V1Flyout is expanded, the V1Flyout content is scrollable if the content exceeds the height of the V1Flyout.

      Content focus​

      The contentFocus prop allows the V1Flyout content container to receive focus when the V1Flyout is expanded. Then, keyboard users can use the tab key to navigate to the content.

      This is intended to be used if the contents of the V1Flyout overflow. Otherwise, it adds an unnecessary tab stop.

      If there are interactive elements placed within the V1Flyout content, these will already appear in the tab order, regardless of the contentFocus prop. For example, form controls (<input>, <textarea>, <select>), Links (<a>), and Buttons (<button>) appear in the tab order by default.

      Responsiveness​

      When the screen hits a breakpoint of 744px or smaller, to ensure visibility of the component, we instead display the expanded form as a full-screen ModalDialog.

      V1Flyout Props​

      Name
      Type
      DefaultA11yDescription
      accessKey
      string | undefined
      the first character of the button label
      Sets the access key to open the Flyout with a keyboard shortcut.
      This string value must consist of a single printable character (which includes accented and other characters that can be generated by the keyboard).

      The way to utilize the access key depends on the browser and operating system.
      For example, on Mac with Chrome or Safari, the key combination is 'Control + Option + key'.
      buttonOnly
      boolean | undefined
      false
      This prop disables the primary functionality of the Flyout, which is to expand a Flyout menu.
      If true, the sticky button will just be, well, a button.
      The button can then be assigned a custom onClick function, for example, to open a link, or a modal.
      children
      string | number | bigint | boolean | ReactElement<any, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...> | null | undefined
      Element displayed when the Flyout is expanded. (i.e. the content of the opened Flyout)
      className
      string | undefined
      CSS class name to apply to each element within the component
      color
      string | undefined
      '$web.semantic.color.surface.interactive.standards.rest.default.primary'
      The color of the FlyoutButton. Can be a CSS color string or a token. By default it uses the primary1 token from the theme.
      contentFocus
      boolean | undefined
      false
      If true, the content of the Flyout will be focusable. In other words, it can be accessed by keyboard navigation using the tab button.
      css
      CSSProperties | Partial<Record<"abyss-flyout-root-container" | "abyss-flyout-body-button" | "abyss-flyout-button" | "abyss-flyout-content", CSSProperties>> | undefined
      Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation
      See CSS Prop Styling for more information
      data-testid
      string | undefined
      Suffix used to create a unique ID used for automated testing
      See Component Testing for more information
      disableUnderlineAccessKey
      boolean | undefined
      false
      Underlines and bolds the first character of the Flyout to indicate the access key.
      height
      string | number | undefined
      '208px'
      Sets the height of the expanded Flyout menu. Can be a CSS string or a number. The min height is 208px, and the max is 320px.
      hiddenFrom
      Breakpoint | undefined
      When defined, the component is hidden once the screen width reaches the specified breakpoint.
      href
      string | undefined
      The href attribute for the FlyoutButton. If provided, the button will be rendered as an <a> element.
      To be used in conjunction with buttonOnly={true}.
      icon
      Element | null | undefined
      null
      The icon element to be displayed to the left of the label on the FlyoutButton. Can be an instance of Icon or IconSymbol, or null.
      indent
      string | undefined
      '25%'
      Sets the placement of Flyout component along the edge of the page. Can be a CSS string such as percent or px.
      label
      string | undefined
      ''
      The label text of the FlyoutButton; this is its accessible name for screen readers.
      onClick
      ((isExpanded?: boolean | undefined) => void) | undefined
      () => {}
      A custom onClick function to be called when the FlyoutButton is clicked. It receives the current expanded state as a parameter.
      This makes the most sense to use with the buttonOnly prop set to true, allowing the button's onClick to be fully customized.
      Otherwise, the onClick will both toggle the Flyout and call this function.

      if buttonOnly is false, isExpanded will be provided as a parameter to the onClick function.
      if buttonOnly is true, isExpanded will always be false.
      position
      "right" | "bottom" | undefined
      'right'
      The position of the Flyout. Can be either 'right' or 'bottom'.
      showArrowIcon
      boolean | undefined
      true
      Determines if the arrow icon is shown on the FlyoutButton, to the right of the label.
      The arrow icon is intended to indicate that the button will open a menu when clicked.

      Default is true, but if using buttonOnly to disable opening the Flyout menu, it may make sense to set this to false.
      slotProps
      FlyoutSlotPropsMap | undefined
      Props to pass to individual internal slots of the component. To target
      slots inside sub-components (e.g. the trigger button or the content
      drawer), nest the sub-component's slotProps under the parent slot key:
      slotProps={{ 'flyout-button': { slotProps: { '<inner-key>': {...} } } }}
      See slotProps for more information
      variant
      "filled" | "outlined" | undefined
      'filled'
      The variant of the Flyout. Can be either 'filled' or 'outlined'.
      visibleFrom
      Breakpoint | undefined
      When defined, the component is hidden until the screen width reaches the specified breakpoint.
      width
      string | number | undefined
      '400px'
      Sets the width of the expanded Flyout menu. Can be a CSS string or a number. The min width is 400px, and the max is 504px.

      V1Flyout Classes​

      Class NameDescription
      .abyss-flyout-body-buttonSkip-link-style button inserted at the start of the DOM to open the Flyout
      .abyss-flyout-buttonThe button which opens/closes the Flyout menu
      .abyss-flyout-contentThe content drawer shown when the Flyout is expanded
      .abyss-flyout-root-containerFixed-position container for the Flyout button and content

      The V1Flyout component is composed of two parts: a "sticky" button positioned on the side of the browser window and modal drawer (dialog) that displayed when activated. When collapsed or displayed, the V1Flyout button and modal overlay the main content.

      Communicating sticky button presence and keyboard access​

      Since the button is sticky, repositioned to the sides of browser window, and added to the end of the HTML. As result many users, especially those using screen readers, may not realize the button even exists. Keyboard users, if they know the button exists, would have difficulty accessing it in the focus order since is at the end of HTML <body>.

      To address both issues, skip links are added to the very top of the page and (ideally) before any "skip to main content" option. Screen reader users are informed of these options at the start of the page. Minor changes for some browsers were made to help avoid known conflicts (See BrAT Accesskey Variations below).

      Accesskey keyboard shortcut​

      The skip link also includes the keyboard shortcut to access the V1Flyout. This uses the standard HTML accesskey which should be familiar to them and their variations (See BrAT Accesskey Variations below). By default, the first letter of V1Flyout.Label becomes the shortcut key. By default, it is also underlined in the sticky button as a reminder for sighted users. These settings can be overridden (See the Access Key section in the Overview tab).

      Closing V1Flyout returns to previous location​

      Like modal dialogs, closing a V1Flyout (should) return the focus to whatever element had it when it was opened. V1Flyout implements this so focus returns to the element that had it when closed. Flyouts can be closed using Escape, pressing Enter on the flyout button, or pressing the flyout accesskey combination again.

      WAI-ARIA dialog pattern​

      The closest WAI-ARIA design pattern is the Dialog (Modal) Patternopens in a new window and Modal Dialog Exampleopens in a new window. WAI-ARIA currently (WAI-AIRA 1.1 as of 8/1/2024) has no equivalent to the sticky button and its keyboard access. The design and implementation used were created to address the issue covered above.

      BrAT Accesskey Variations​
      • Windows browsers (Chrome, Edge, Firefox) and screen readers (NVDA, JAWS)

        • Minor accesskey variation: Addition of Shift key

          Windows accesskey for Chrome and Edge relies on Alt alone. This can cause conflicts accessing some characters Chromium browsers use for their keyboard shortcuts.

          Firefox browser's accesskey implementation requires using Alt + Shift. Using Alt + Shift with the character addresses the issue with letter keys and works the same in all three browsers. This is why the skip links at the top of the page include Shift on Chromium browsers even though they may not be necessary.

          Example: On this page, the sandbox example uses accesskey="F" to access the "V1Flyout Label" example on the right side of this window. Using Edge and Chrome Alt + F opens the File menu. Using Alt + Shift + F accesses V1Flyout Label as intended.

      • MacOS browsers (Safari, Chrome) and screen readers (VoiceOver)

        • VoiceOver conflict with browser accesskey default
          • MacOS uses Control + Option and this is shown in the skip link in Safari and Chrome browsers.
          • VoiceOver uses Control + Option as its modifier keys creating a conflict when used in the browsers (discussed below)

        • Safari
          • Keyboard without VoiceOver: Control + Option + Letter (default)
          • Keyboard with VoiceOver: Control + Letter ONLY
            • Apple modifies Safari's HTML accesskey implementation to use only Control when VoiceOver is running
            • Using modified accesskey using Control + [letter] works as described above including resetting focus to originally focused element using Escape, accesskey, and flyout button
            • Note: Once activated, the Control-only accesskey modification is persistent even if VoiceOver is turned off. Restart Safari without VoiceOver to reset accesskey to Control + Option.

        • Chrome
          • Keyboard without VoiceOver: Control + Option + Letter (default)
          • Keyboard with VoiceOver: accesskey "effectively disabled"
            • Unlike Safari, the HTML accesskey modifier combination remains Control + Option
            • To use this accesskey combination requires using VoiceOver pass-through mode using Control + Option + Tab
              • Then use normal Control + Option accesskey combination to open flyout. Operation then works as described resetting focus to originally focused element using Escape, accesskey, and flyout button
            • Example: To access the V1Flyout Label example requires pressing Control + Option + Tab, then Control + Option + F

      • For more information about accesskey BrAT implementations see: Accesskey Accessibility Demo (pauljadam.com)opens in a new window

      Keyboard Interactions​

      KeyDescription
      EnterExecutes the V1Flyout button trigger to expand or close (when focus is on button)
      SpaceExecutes the V1Flyout button trigger to expand or close (when focus is on button)
      EscCloses the V1Flyout
      TabMoves focus to V1Flyout content window when using contentFocus or to focusable element when present in content
      Table of Contents