diff --git a/.changeset/witty-avocados-play.md b/.changeset/witty-avocados-play.md
new file mode 100644
index 0000000000..d0dcac4850
--- /dev/null
+++ b/.changeset/witty-avocados-play.md
@@ -0,0 +1,11 @@
+---
+'@twilio-paste/popover': minor
+'@twilio-paste/core': minor
+---
+
+[Popover] Add new props:
+
+- initialFocusRef: focuses a ref when the Popover opens
+- width: sets the width of the Popover, up to size50.
+
+Update styles to align with new Paste Twilio theme
diff --git a/packages/paste-core/components/popover/__tests__/index.spec.tsx b/packages/paste-core/components/popover/__tests__/index.spec.tsx
index a446304501..ae5f829e59 100644
--- a/packages/paste-core/components/popover/__tests__/index.spec.tsx
+++ b/packages/paste-core/components/popover/__tests__/index.spec.tsx
@@ -5,7 +5,7 @@ import {Theme} from '@twilio-paste/theme';
import {CustomizationProvider} from '@twilio-paste/customization';
import {Text} from '@twilio-paste/text';
-import {PopoverTop, StateHookExample, BadgePopover} from '../stories/index.stories';
+import {PopoverTop, StateHookExample, BadgePopover, InitialFocus} from '../stories/index.stories';
import {Popover, PopoverContainer, PopoverButton} from '../src';
describe('Popover', () => {
@@ -39,6 +39,38 @@ describe('Popover', () => {
expect(renderedPopover.getAttribute('role')).toEqual('dialog');
});
+ it('should focus the close button when the popover opens', async () => {
+ render(
+
+
+
+ );
+
+ const renderedPopoverButton = screen.getByRole('button');
+
+ await waitFor(() => {
+ userEvent.click(renderedPopoverButton);
+ });
+
+ expect(document.activeElement).toEqual(screen.getByRole('button', {name: 'Close popover'}));
+ });
+
+ it('should focus the initialFocusRef when the popver opens', async () => {
+ render(
+
+
+
+ );
+
+ const renderedPopoverButton = screen.getByRole('button');
+
+ await waitFor(() => {
+ userEvent.click(renderedPopoverButton);
+ });
+
+ expect(document.activeElement).toEqual(screen.getByRole('button', {name: 'Click me'}));
+ });
+
it('should render a popover and show/hide on external button click', async () => {
render(
diff --git a/packages/paste-core/components/popover/package.json b/packages/paste-core/components/popover/package.json
index eb303012f4..0157d9298f 100644
--- a/packages/paste-core/components/popover/package.json
+++ b/packages/paste-core/components/popover/package.json
@@ -3,7 +3,7 @@
"version": "10.0.2",
"category": "interaction",
"status": "production",
- "description": "A Popover is a page overlay triggered by a click that displays additional interactive content.",
+ "description": "A Popover is a page overlay triggered by a button that displays additional interactive content.",
"author": "Twilio Inc.",
"license": "MIT",
"main:dev": "src/index.tsx",
diff --git a/packages/paste-core/components/popover/src/Popover.tsx b/packages/paste-core/components/popover/src/Popover.tsx
index ce50c1abd9..ea51b1a5cc 100644
--- a/packages/paste-core/components/popover/src/Popover.tsx
+++ b/packages/paste-core/components/popover/src/Popover.tsx
@@ -7,20 +7,22 @@ import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon';
import {StyledBase} from '@twilio-paste/theme';
import {NonModalDialogPrimitive} from '@twilio-paste/non-modal-dialog-primitive';
import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only';
+import type {ResponsiveValue} from '@twilio-paste/styling-library';
import {PopoverArrow} from './PopoverArrow';
import {PopoverContext} from './PopoverContext';
-const StyledPopover = React.forwardRef(({style, ...props}, ref) => {
+const StyledPopover = React.forwardRef(({style, width, ...props}, ref) => {
return (
(({style, ...pro
StyledPopover.displayName = 'StyledPopover';
+type WidthOptions = 'size10' | 'size20' | 'size30' | 'size40' | 'size50';
+
export interface PopoverProps extends Pick {
'aria-label': string;
children: React.ReactNode;
i18nDismissLabel?: string;
+ width?: ResponsiveValue;
+ initialFocusRef?: React.RefObject;
}
const Popover = React.forwardRef(
- ({children, element = 'POPOVER', i18nDismissLabel = 'Close popover', ...props}, ref) => {
+ ({children, element = 'POPOVER', i18nDismissLabel = 'Close popover', initialFocusRef, ...props}, ref) => {
const popover = React.useContext(PopoverContext);
+
+ React.useEffect(() => {
+ if (popover.visible && initialFocusRef) {
+ initialFocusRef.current?.focus();
+ }
+ }, [popover.visible, initialFocusRef]);
+
return (
{/* import Paste Theme Based Styles due to portal positioning. */}
-
-
+
+