@momentum-ui/react-collaboration
Version:
Cisco Momentum UI Framework for React Collaboration Applications
271 lines (231 loc) • 7.64 kB
text/typescript
import type { AriaRole, CSSProperties, ReactElement, ReactNode } from 'react';
import type { Instance, LifecycleHooks } from 'tippy.js';
import type { TippyProps } from '@tippyjs/react';
import type { Color } from '../ModalContainer/ModalContainer.types';
import { ButtonCircleProps } from '../ButtonCircle';
// variant - based on Figma mockups:
export type VariantType = 'small' | 'medium';
export type BoundaryType = 'parent' | 'viewport' | 'window' | HTMLElement;
export type CloseButtonPlacement = 'top-left' | 'top-right' | 'none';
export type CloseButtonProps = ButtonCircleProps & { 'aria-label': string };
export type PlacementType = TippyProps['placement'];
export type TriggerType = TippyProps['trigger'];
export type PositioningStrategy = TippyProps['popperOptions']['strategy'];
export type AppendToType = TippyProps['appendTo'];
export type CustomTippyPopoverProperties = { shouldFocusTrigger?: boolean };
/**
* Popover instance interface abstracted from Tippy.js
*/
export type PopoverInstance = Instance & CustomTippyPopoverProperties;
export type PopoverCommonStyleProps = {
/**
* Variant of the Popover - can be either small or medium
*
* @default `small`
*/
variant?: VariantType;
/**
* Color of the Container
*/
color?: Color;
/**
* Whether the arrow should be shown
*
* @default true
*/
showArrow?: boolean;
/**
* Delay in ms once a trigger event is fired before the Popover shows or hides.
*
* [`showDelay`, `hideDelay`]
*
* @default 0
*/
delay?: [number, number];
/**
* Placement of the Popover
*
* Possible values: `top`, `top-start`, `top-end`, `right`, `right-start`, `right-end`, `bottom`, `bottom-start`, `bottom-end`,
* `left`, `left-start`, `left-end`, `auto`, `auto-start`, `auto-end`
*
* @default `bottom`
*/
placement?: PlacementType;
/**
* Overflow Boundary of Popover
*
* Possible values: `scrollParent`, `viewport`, `window`, or any `HTMLElement`
*
* @default `scollParent`
*/
boundary?: BoundaryType;
/**
* Whether the popover should hide when Esc is pressed
*
* @default true
*/
hideOnEsc?: boolean;
/**
* Whether the popover should hide when focus leaves from within the Popover
*
* @default false
*/
hideOnBlur?: boolean;
/**
* Used when provided by a select which renders a popover. This is used to ensure only one popover is open at a time.
*/
singleOpenGroupId?: string;
/**
* Manual control of if the Popover contains child elements that may be open, and not nested within the
* Popover. it's possible the focus may shift to something that in the DOM is not actually within the Popover,
* but appears to be and therefore, do not blur it.
*
* @default false
*/
isChildPopoverOpen?: boolean;
/**
* Whether or not an invisible backdrop is added behind the popover. A backdrop, when added, will hide the
* popover when you click outside of it, preventing multiple popovers from opening at once.
*
* @default true
*/
addBackdrop?: boolean;
/**
* The z-index of the tippy popover. If not supplied, tippy will default to 9999
*/
zIndex?: number;
};
export type PopoverCloseButtonProps =
| {
/**
* Position of the close button
* @default `none`
*/
closeButtonPlacement?: 'none';
/**
* Props that are passed down to the close button. Required if close button exists.
*/
closeButtonProps?: CloseButtonProps;
}
| {
/**
* Position of the close button
* @default `none`
*/
closeButtonPlacement: Exclude<CloseButtonPlacement, 'none'>;
/**
* Props that are passed down to the close button. Required if close button exists.
*/
closeButtonProps: CloseButtonProps;
};
export type Props = PopoverCommonStyleProps &
PopoverCloseButtonProps &
Partial<LifecycleHooks> & {
/**
* Child components of this Popover (what will be shown within the Popover)
*/
children: ReactNode;
/**
* Determines the events that cause the Popover to show. Multiple event names should be separated by spaces.
* For example to allow both click and hover, use `click mouseenter` as the trigger.
*
* Possible event names: `click`, `mouseenter`, `focusin`, `manual` (to programmatically trigger the popover)
*
* @default `click`
*/
trigger?: TriggerType;
/**
* The component which triggers the Popover
*/
triggerComponent: ReactElement;
/**
* Determines if the Popover has interactive content inside of it,
* so that it can be hovered over and clicked inside without hiding.
*
* @default false
*/
interactive?: boolean;
/**
* setInstance - this function should be passed in when the instance
* of the popover should be available on the parent of the Popover.
*
* With the instance of the popover the parent component can `show()` or `hide()` the Popover programmatically.
*
* setInstance is the setter function of a useState hook
*/
setInstance?: React.Dispatch<React.SetStateAction<PopoverInstance | undefined>>;
/**
* Custom class for overriding this component's CSS.
*/
className?: string;
/**
* Custom id for overriding this component's CSS.
*/
id?: string;
/**
* Custom style for overriding this component's CSS.
*/
style?: CSSProperties;
/**
* Determines if the component will focus back on the trigger when the Popover is hidden.
* @default `false`
*/
focusBackOnTrigger?: boolean;
/**
* Describes the positioning strategy to use.
* @default `absolute`
*/
strategy?: PositioningStrategy;
/**
* The offset distance (in px) from the reference.
* @default 'undefined'
*/
offsetDistance?: number;
/**
* The offset skidding (in px) along the reference.
* @default 'undefined'
*/
offsetSkidding?: number;
/**
* The element used to focus on when the popover opens
* See PopoverWithFirstFocus in storybook for example usage
* @default 'undefined'
*/
firstFocusElement?: HTMLElement;
/**
* Whether to auto focus the first focusable element in the focus scope of the Popover on mount.
*
* Example: set to false if the Popover Content itself wants to handle the auto focusing (i.e. MenuTrigger)
*
* Defaults: true
*/
autoFocus?: boolean;
/**
* Role of the popover content
*/
role?: AriaRole;
/**
* The element to append the popover to.
*/
appendTo?: AppendToType;
/**
* Whether to allow the trigger event to continue to propagate after the Popover is triggered.
*/
continuePropagationOnTrigger?: boolean;
/**
* aria-labelledby for an interactive popover only, defaults to the trigger component id.
* Used in nested cases where the triggerComponent isn't the actual button.
*/
'aria-labelledby'?: string;
/**
* aria-label for an interactive popover only. By default, it will be labelled by the triggerComponent.
* Only required in the unusual circumstance where the popover label cannot match the trigger.
*/
'aria-label'?: string;
/**
* If true, the focus lock will be disabled for the Popover content.
* This is useful when you want to handle focus lock mechanism yourself, and to avoid having multiple focus locks.
* @default `false`
*/
disableFocusLock?: boolean;
};