-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LG-4445: add renderMode and top layer #2482
Changes from 5 commits
c353b06
e64d457
a2fd4b4
a71f177
557fb83
bee293b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
import { HTMLElementProps } from '@leafygreen-ui/lib'; | ||
import { PopoverProps } from '@leafygreen-ui/popover'; | ||
import { PortalControlProps } from '@leafygreen-ui/popover'; | ||
|
||
export type DatePickerMenuProps = PortalControlProps & | ||
Omit<PopoverProps, 'children'> & | ||
export type DatePickerMenuProps = Omit< | ||
PopoverProps, | ||
'children' | 'renderMode' | 'usePortal' | ||
> & | ||
HTMLElementProps<'div'>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,68 +15,117 @@ type TransitionLifecycleCallbacks = Pick< | |
'onEnter' | 'onEntering' | 'onEntered' | 'onExit' | 'onExiting' | 'onExited' | ||
>; | ||
|
||
type PortalControlProps = | ||
| { | ||
/** | ||
* Specifies that the popover content should be rendered at the end of the DOM, | ||
* rather than in the DOM tree. | ||
* | ||
* default: `true` | ||
*/ | ||
usePortal?: true; | ||
|
||
/** | ||
* When usePortal is `true`, specifies a class name to apply to the root element of the portal. | ||
*/ | ||
portalClassName?: string; | ||
|
||
/** | ||
* When usePortal is `true`, specifies an element to portal within. The default behavior is to generate a div at the end of the document to render within. | ||
*/ | ||
portalContainer?: HTMLElement | null; | ||
|
||
/** | ||
* A ref for the portal element | ||
*/ | ||
portalRef?: React.MutableRefObject<HTMLElement | null>; | ||
|
||
/** | ||
* When usePortal is `true`, specifies the scrollable element to position relative to. | ||
*/ | ||
scrollContainer?: HTMLElement | null; | ||
} | ||
| { | ||
/** | ||
* Specifies that the popover content should be rendered at the end of the DOM, | ||
* rather than in the DOM tree. | ||
* | ||
* default: `true` | ||
*/ | ||
usePortal: false; | ||
|
||
/** | ||
* When usePortal is `true`, specifies a class name to apply to the root element of the portal. | ||
*/ | ||
portalClassName?: undefined; | ||
|
||
/** | ||
* When usePortal is `true`, specifies an element to portal within. The default behavior is to generate a div at the end of the document to render within. | ||
*/ | ||
portalContainer?: null; | ||
|
||
/** | ||
* A ref for the portal element | ||
*/ | ||
portalRef?: undefined; | ||
|
||
/** | ||
* When usePortal is `true`, specifies the scrollable element to position relative to. | ||
*/ | ||
scrollContainer?: null; | ||
}; | ||
export const DismissMode = { | ||
Auto: 'auto', | ||
Manual: 'manual', | ||
} as const; | ||
export type DismissMode = (typeof DismissMode)[keyof typeof DismissMode]; | ||
|
||
/** Local implementation of web-native `ToggleEvent` until we use typescript v5 */ | ||
export interface ToggleEvent extends Event { | ||
type: 'toggle'; | ||
newState: 'open' | 'closed'; | ||
oldState: 'open' | 'closed'; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these types should all live in the popover package There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are they duplicated here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a comment at the top of the file about this. The types can't be shared/imported because of a circular dependency between |
||
|
||
/** @deprecated - use {@link RenderTopLayerProps} */ | ||
interface RenderInlineProps { | ||
/** | ||
* Popover element will render inline with the reference element | ||
*/ | ||
renderMode: 'inline'; | ||
|
||
/** Not used in this `renderMode` */ | ||
dismissMode?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
onToggle?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
portalClassName?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
portalContainer?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
portalRef?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
scrollContainer?: never; | ||
} | ||
|
||
/** @deprecated - use {@link RenderTopLayerProps} */ | ||
interface RenderPortalProps { | ||
/** | ||
* Popover element will render in a provided `portalContainer` or in a new div appended to the body | ||
*/ | ||
renderMode?: 'portal'; | ||
|
||
/** Not used in this `renderMode` */ | ||
dismissMode?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
onToggle?: never; | ||
|
||
/** | ||
* Specifies a class name to apply to the portal element | ||
*/ | ||
portalClassName?: string; | ||
|
||
/** | ||
* Specifies an element to portal within. If not provided, a div is generated at the end of the body | ||
*/ | ||
portalContainer?: HTMLElement | null; | ||
|
||
/** | ||
* Passes a ref to forward to the portal element | ||
*/ | ||
portalRef?: React.MutableRefObject<HTMLElement | null>; | ||
|
||
/** | ||
* Specifies the scrollable element to position relative to | ||
*/ | ||
scrollContainer?: HTMLElement | null; | ||
} | ||
|
||
interface RenderTopLayerProps { | ||
/** | ||
* Popover element will render in the top layer | ||
*/ | ||
renderMode?: 'top-layer'; | ||
|
||
/** | ||
* Options to control how the popover element is dismissed | ||
* - `'auto'` will automatically handle dismissal on backdrop click or key press, ensuring only one popover is visible at a time | ||
* - `'manual'` will require that the consumer handle dismissal manually | ||
*/ | ||
dismissMode?: DismissMode; | ||
|
||
/** | ||
* A callback function that is called when the popover is toggled | ||
*/ | ||
onToggle?: (e: ToggleEvent) => void; | ||
|
||
/** Not used in this `renderMode` */ | ||
portalClassName?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
portalContainer?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
portalRef?: never; | ||
|
||
/** Not used in this `renderMode` */ | ||
scrollContainer?: never; | ||
} | ||
|
||
export type PopoverRenderModeProps = | ||
| RenderInlineProps | ||
| RenderPortalProps | ||
| RenderTopLayerProps; | ||
|
||
export type PopoverProviderProps = TransitionLifecycleCallbacks & | ||
PortalControlProps & { | ||
PopoverRenderModeProps & { | ||
/** | ||
* Specifies the amount of spacing (in pixels) between the trigger element and the Popover content. | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shaneeza What was the initial reasoning for having PopoverContext live in
leafygreen-provider
instead of within thepopover
package?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fwiw, I did try moving
PopoverContext
into the popover package while I was consolidatingPortalContext
andPopoverContext
. Since the consolidatedPopoverProvider
is included in the global LG provider and the@leafygreen-ui/leafygreen-provider
, we can't movePopoverContext
into popover without introducing a circular dependency