diff --git a/src/Popover/Popover.test.jsx b/src/Popover/Popover.test.tsx
similarity index 100%
rename from src/Popover/Popover.test.jsx
rename to src/Popover/Popover.test.tsx
diff --git a/src/Popover/index.jsx b/src/Popover/index.jsx
deleted file mode 100644
index 07be9806a00..00000000000
--- a/src/Popover/index.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import BasePopover from 'react-bootstrap/Popover';
-import BasePopoverTitle from 'react-bootstrap/PopoverTitle';
-import BasePopoverContent from 'react-bootstrap/PopoverContent';
-
-const PLACEMENT_VARIANTS = [
- 'auto',
- 'top',
- 'bottom',
- 'left',
- 'right',
-];
-
-const Popover = React.forwardRef(({
- children,
- variant,
- ...props
-}, ref) => (
-
- {children}
-
-));
-
-function PopoverTitle(props) {
- return ;
-}
-function PopoverContent(props) {
- return ;
-}
-
-const commonPropTypes = {
- /** Specifies the base element */
- as: PropTypes.elementType,
- /** Overrides underlying component base CSS class name */
- bsPrefix: PropTypes.string,
-};
-
-PopoverTitle.propTypes = commonPropTypes;
-PopoverContent.propTypes = commonPropTypes;
-
-Popover.propTypes = {
- ...BasePopover.propTypes,
- /** An html id attribute, necessary for accessibility. */
- id: PropTypes.string.isRequired,
- /**
- * Sets the direction the Popover is positioned towards.
- *
- * This is generally provided by the `Overlay` component positioning the popover.
- */
- placement: PropTypes.oneOf(PLACEMENT_VARIANTS),
- /**
- * When this prop is set, it creates a `Popover` with
- * a `Popover.Title` inside passing the children directly to it.
- */
- title: PropTypes.string,
- /**
- * An `Overlay` injected set of props for positioning the popover arrow.
- *
- * This is generally provided by the `Overlay` component positioning the popover.
- */
- arrowProps: PropTypes.shape({
- ref: PropTypes.oneOfType([
- PropTypes.func,
- PropTypes.shape({ current: PropTypes.element }),
- ]),
- style: PropTypes.shape({}),
- }),
- /**
- * When this prop is set, it creates a `Popover` with
- * a `Popover.Content` inside passing the children directly to it.
- */
- content: PropTypes.bool,
- /** A `Popper.js` config object passed to the the underlying popper instance. */
- popper: PropTypes.shape({}),
- /** Whether the `Overlay` is shown. */
- show: PropTypes.bool,
- /** Specifies the content of the `Overlay` */
- children: PropTypes.node,
- /** Specifies class name to append to the base element */
- className: PropTypes.string,
- /** The visual style of the `Overlay` */
- variant: PropTypes.string,
-};
-
-Popover.defaultProps = {
- ...BasePopover.defaultProps,
- placement: 'right',
- title: undefined,
- arrowProps: undefined,
- content: undefined,
- popper: undefined,
- show: undefined,
- children: undefined,
- className: undefined,
- variant: undefined,
-};
-
-PopoverTitle.defaultProps = {
- as: 'div',
- bsPrefix: 'popover-header',
-};
-
-PopoverContent.defaultProps = {
- as: 'div',
- bsPrefix: 'popover-body',
-};
-
-Popover.Title = PopoverTitle;
-Popover.Content = PopoverContent;
-
-export { PopoverTitle, PopoverContent };
-export default Popover;
diff --git a/src/Popover/index.tsx b/src/Popover/index.tsx
new file mode 100644
index 00000000000..d1a30d0d8bd
--- /dev/null
+++ b/src/Popover/index.tsx
@@ -0,0 +1,119 @@
+import React from 'react';
+import classNames from 'classnames';
+import BasePopover from 'react-bootstrap/Popover';
+import BasePopoverTitle from 'react-bootstrap/PopoverTitle';
+import BasePopoverContent from 'react-bootstrap/PopoverContent';
+import { ArrowProps } from 'react-bootstrap/esm/Overlay';
+
+type PlacementVariant = 'auto' | 'top' | 'bottom' | 'left' | 'right';
+
+interface PopoverProps {
+ /** An html id attribute, necessary for accessibility. */
+ id: string;
+ /**
+ * Sets the direction the Popover is positioned towards.
+ *
+ * This is generally provided by the `Overlay` component positioning the popover.
+ */
+ placement?: PlacementVariant;
+ /**
+ * When this prop is set, it creates a `Popover` with
+ * a `Popover.Title` inside passing the children directly to it.
+ */
+ title?: string;
+ /**
+ * An `Overlay` injected set of props for positioning the popover arrow.
+ *
+ * This is generally provided by the `Overlay` component positioning the popover.
+ */
+ arrowProps?: ArrowProps;
+ /**
+ * When this prop is set, it creates a `Popover` with
+ * a `Popover.Content` inside passing the children directly to it.
+ */
+ content?: boolean;
+ /** A `Popper.js` config object passed to the the underlying popper instance. */
+ popper?: Record;
+ /** Whether the `Overlay` is shown. */
+ show?: boolean;
+ /** Specifies the content of the `Overlay` */
+ children?: React.ReactNode;
+ /** Specifies class name to append to the base element */
+ className?: string;
+ /** The visual style of the `Overlay` */
+ variant?: string;
+ /** Specifies the base element */
+ as?: React.ElementType;
+ /** Overrides underlying component base CSS class name */
+ bsPrefix?: string;
+}
+
+interface PopoverSubcomponentProps {
+ /** Specifies the base element */
+ as?: React.ElementType;
+ /** Overrides underlying component base CSS class name */
+ bsPrefix?: string;
+ /** Specifies class name to append to the base element */
+ className?: string;
+ /** Specifies the content of the component */
+ children?: React.ReactNode;
+}
+
+const Popover = React.forwardRef(({
+ children,
+ variant,
+ placement = 'right',
+ title,
+ arrowProps,
+ content,
+ popper,
+ show,
+ className,
+ ...props
+}, ref) => (
+
+ {children}
+
+));
+
+function PopoverTitle({
+ as = 'div',
+ bsPrefix = 'popover-header',
+ ...props
+}: PopoverSubcomponentProps) {
+ return ;
+}
+
+function PopoverContent({
+ as = 'div',
+ bsPrefix = 'popover-body',
+ ...props
+}: PopoverSubcomponentProps) {
+ return ;
+}
+
+Popover.displayName = 'Popover';
+PopoverTitle.displayName = 'Popover.Title';
+PopoverContent.displayName = 'Popover.Content';
+
+// Create the compound component with proper typing
+const PopoverWithSubcomponents = Object.assign(Popover, {
+ Title: PopoverTitle,
+ Content: PopoverContent,
+}) as typeof Popover & {
+ Title: typeof PopoverTitle;
+ Content: typeof PopoverContent;
+};
+
+export { PopoverTitle, PopoverContent };
+export default PopoverWithSubcomponents;
diff --git a/src/index.ts b/src/index.ts
index 7e11e26a8c4..614f730f72b 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -42,6 +42,7 @@ export { default as ModalContext } from './Modal/ModalContext';
export { default as ModalDialog } from './Modal/ModalDialog';
export { default as ModalLayer } from './Modal/ModalLayer';
export { default as Overlay, OverlayTrigger } from './Overlay';
+export { default as Popover, PopoverTitle, PopoverContent } from './Popover';
export { default as Portal } from './Modal/Portal';
export { default as Spinner } from './Spinner';
export { default as Stack } from './Stack';
@@ -146,8 +147,6 @@ export {
// @ts-ignore: has yet to be converted to TypeScript
} from './Pagination';
// @ts-ignore: has yet to be converted to TypeScript
-export { default as Popover, PopoverTitle, PopoverContent } from './Popover';
-// @ts-ignore: has yet to be converted to TypeScript
export { default as ProgressBar } from './ProgressBar';
// @ts-ignore: has yet to be converted to TypeScript
export { default as ProductTour } from './ProductTour';