Skip to content

Commit

Permalink
feat(Popover): allow focus upon popover panel open (#1782)
Browse files Browse the repository at this point in the history
- expose the `focus` option from HeadlessUI's .Panel API
- add test with `play` to trigger the behavio for a snapshot
  • Loading branch information
booc0mtaco authored Oct 12, 2023
1 parent 971f189 commit 76ddbc6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
29 changes: 29 additions & 0 deletions src/components/Popover/Popover.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React from 'react';
import { Popover } from './Popover';
import type { PopoverProps } from './Popover';
import Button from '../Button';
import Hr from '../Hr';

export default {
title: 'Components/Popover',
Expand Down Expand Up @@ -147,3 +148,31 @@ export const LeftEnd: StoryObj<PopoverProps> = {
},
...Default,
};

export const FocusClickableElement: StoryObj<PopoverProps> = {
play: async ({ canvasElement }) => {
// We want to test visual regression for the Popover.Content as well as the button,
// but don't want the drawer open initally outside Chromatic.
if (isChromatic()) {
const canvas = within(canvasElement);
const filtersTrigger = await canvas.findByRole('button');
await userEvent.click(filtersTrigger);
}
},
render: (args) => {
return (
<Popover {...args}>
<Popover.Button as={Button} data-testid="popover-trigger-button">
Open Popover
</Popover.Button>
<Popover.Content data-testid="popover-content" focus>
<div className="fpo m-2 p-6">
Popover Content goes here
<Hr />
<Button>Focus on me upon open</Button>
</div>
</Popover.Content>
</Popover>
);
},
};
24 changes: 12 additions & 12 deletions src/components/Popover/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const PopoverButton = (props: PopoverButtonProps) => {
return <HeadlessPopover.Button {...props} ref={setReferenceElement} />;
};

export type PopoverContentProps = {
export type PopoverContentProps = ExtractProps<typeof HeadlessPopover.Panel> & {
/**
* Custom classname for additional styles for the arrow.
*/
Expand All @@ -100,17 +100,17 @@ export type PopoverContentProps = {
*/
className?: string;
} & RenderProps<{
/**
* Render prop indicating popover open status.
*/
open: boolean;
/**
* Render prop that closes popover when called.
*/
close: (
focusableElement?: HTMLElement | React.RefObject<HTMLElement>,
) => void;
}>;
/**
* Render prop indicating popover open status.
*/
open: boolean;
/**
* Render prop that closes popover when called.
*/
close: (
focusableElement?: HTMLElement | React.RefObject<HTMLElement>,
) => void;
}>;

/**
* A floating container that can be resized to fit content inside
Expand Down
25 changes: 25 additions & 0 deletions src/components/Popover/__snapshots__/Popover.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,31 @@ exports[`<Popover /> Default story renders snapshot 1`] = `
</div>
`;

exports[`<Popover /> FocusClickableElement story renders snapshot 1`] = `
<div
data-headlessui-state="open"
>
<button
aria-controls="headlessui-popover-panel-:r23:"
aria-expanded="true"
class="clickable-style clickable-style--lg clickable-style--secondary clickable-style--brand button button--secondary"
data-headlessui-state="open"
data-testid="popover-trigger-button"
id="headlessui-popover-button-:r21:"
type="button"
>
Open Popover
</button>
<button
aria-hidden="true"
data-headlessui-focus-guard="true"
id="headlessui-focus-sentinel-:r22:"
style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px;"
type="button"
/>
</div>
`;

exports[`<Popover /> Left story renders snapshot 1`] = `
<div
data-headlessui-state="open"
Expand Down

0 comments on commit 76ddbc6

Please sign in to comment.