Skip to content

Commit

Permalink
fixup: ensure menu is labeled
Browse files Browse the repository at this point in the history
  • Loading branch information
mcous committed Nov 29, 2023
1 parent 4906e5f commit 504a728
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const handleChange = (nextIsOpen: boolean) => (isOpen = nextIsOpen);

<FloatingMenu
{isOpen}
label="cool menu"
onChange={handleChange}
>
<span slot="control">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('<FloatingMenu> component', () => {
it('should open and close a menu when the control is clicked', async () => {
render(Subject);

const control = screen.getByRole('button', { name: /open/iu });
const control = screen.getByRole('button', { name: /cool menu/iu });
let menu = screen.queryByRole('menu');
let item = screen.queryByRole('menuitem');

Expand All @@ -41,7 +41,7 @@ describe('<FloatingMenu> component', () => {
it('should pass aria props to the control', async () => {
render(Subject);

const control = screen.getByRole('button', { name: /open/iu });
const control = screen.getByRole('button', { name: /cool menu/iu });

expect(control).toHaveAttribute('aria-haspopup', 'menu');
expect(control).toHaveAttribute('aria-expanded', 'false');
Expand All @@ -50,14 +50,15 @@ describe('<FloatingMenu> component', () => {
const menu = screen.getByRole('menu');

expect(menu).toHaveAttribute('id', expect.any(String));
expect(menu).toHaveAccessibleName(/cool menu/iu);
expect(control).toHaveAttribute('aria-controls', menu.id);
expect(control).toHaveAttribute('aria-expanded', 'true');
});

it('should close the menu if escape is pressed', async () => {
render(Subject);

const control = screen.getByRole('button', { name: /open/iu });
const control = screen.getByRole('button', { name: /cool menu/iu });

await user.click(control);
await user.keyboard('{Escape}');
Expand All @@ -69,7 +70,7 @@ describe('<FloatingMenu> component', () => {
it('should close the menu on click outside', async () => {
render(Subject);

const control = screen.getByRole('button', { name: /open/iu });
const control = screen.getByRole('button', { name: /cool menu/iu });
const outside = screen.getByTestId('outside-element');

await user.click(control);
Expand All @@ -82,7 +83,7 @@ describe('<FloatingMenu> component', () => {
it('should pass a close menu handler to the items', async () => {
render(Subject);

const control = screen.getByRole('button', { name: /open/iu });
const control = screen.getByRole('button', { name: /cool menu/iu });
await user.click(control);

const item = screen.getByRole('menuitem');
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/lib/context-menu/context-menu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,21 @@ import cx from 'classnames';
/** ID attribute of the menu element. */
export let id: string;
/** Accessible label of the menu. */
export let label: string | undefined = undefined;
/** ID of the element ID that labels the menu. */
export let labeledBy: string | undefined = undefined;
/** Additional CSS classes to pass to the menu. */
let extraClasses: cx.Argument = '';
export { extraClasses as cx };
</script>

<div
{id}
aria-label={label}
aria-labelledby={labeledBy}
role="menu"
class={cx(
'border border-medium bg-white py-1 shadow-sm filter-none',
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/lib/context-menu/floating-menu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { floatingStyle, type FloatingMenuPlacement } from './floating-style';
import ContextMenu from './context-menu.svelte';
export let isOpen: boolean;
export let label: string | undefined = undefined;
export let describedBy: string | undefined = undefined;
export let placement: FloatingMenuPlacement = 'bottom-start';
export let offset = 0;
export let buttonCX: cx.Argument = '';
export let menuCX: cx.Argument = '';
export let label: string | undefined = undefined;
export let describedBy: string | undefined = undefined;
export let onChange: (isOpen: boolean) => unknown;
const buttonID = uniqueId('floating-menu-control');
const menuID = uniqueId('floating-menu');
const style = floatingStyle();
const openMenu = () => onChange(true);
Expand Down Expand Up @@ -41,6 +42,7 @@ $: style.register({ controlElement, menuElement, placement, offset });
<svelte:window on:keydown={isOpen ? handleEscape : undefined} />

<button
id={buttonID}
class={cx(buttonCX)}
aria-haspopup="menu"
aria-controls={menuID}
Expand All @@ -64,6 +66,7 @@ $: style.register({ controlElement, menuElement, placement, offset });
>
<ContextMenu
id={menuID}
labeledBy={buttonID}
cx={menuCX}
>
<slot name="items" />
Expand Down

0 comments on commit 504a728

Please sign in to comment.