Skip to content

Commit

Permalink
fix(react-infobutton): Apply aria-owns only when the popover is open …
Browse files Browse the repository at this point in the history
…and cleanup infobutton stories (#28463)
  • Loading branch information
sopranopillow authored Jul 14, 2023
1 parent dbce79b commit d2c1969
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "fix(react-infobutton): Make InfoLabel only add aria-owns when the popover is open.",
"packageName": "@fluentui/react-infobutton",
"email": "esteban.230@hotmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { render } from '@testing-library/react';
import { fireEvent, render } from '@testing-library/react';
import { isConformant } from '../../testing/isConformant';
import { InfoLabel } from './InfoLabel';

Expand Down Expand Up @@ -44,13 +44,21 @@ describe('InfoLabel', () => {
expect(infoButton.getAttribute('aria-labelledby')).toBe(`${label.id} ${infoButton.id}`);
});

it("applies InfoButton's info slot id to aria-owns on the InfoLabel's wrapper", () => {
it("applies InfoButton's info slot id to aria-owns on the InfoLabel's wrapper when open", () => {
const { container } = render(<InfoLabel className="info-label-wrapper" info={{ id: 'test-id' }} />);
expect(container.getElementsByClassName('info-label-wrapper')[0].getAttribute('aria-owns')).toBeNull();

fireEvent.click(container.getElementsByTagName('button')[0]);

expect(container.getElementsByClassName('info-label-wrapper')[0].getAttribute('aria-owns')).toBe('test-id');
});

it("applies InfoButton's correct id to aria-owns on the InfoLabel's wrapper when id is provided to the infoButton slot", () => {
const { container } = render(<InfoLabel className="info-label-wrapper" infoButton={{ info: { id: 'test-id' } }} />);
expect(container.getElementsByClassName('info-label-wrapper')[0].getAttribute('aria-owns')).toBeNull();

fireEvent.click(container.getElementsByTagName('button')[0]);

expect(container.getElementsByClassName('info-label-wrapper')[0].getAttribute('aria-owns')).toBe('test-id');
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';

import { Label } from '@fluentui/react-label';
import { resolveShorthand, useId } from '@fluentui/react-utilities';
import { mergeCallbacks, resolveShorthand, useEventCallback, useId } from '@fluentui/react-utilities';
import { InfoButton } from '../InfoButton/InfoButton';
import type { InfoLabelProps, InfoLabelState } from './InfoLabel.types';

Expand All @@ -26,6 +26,7 @@ export const useInfoLabel_unstable = (props: InfoLabelProps, ref: React.Ref<HTML
...labelProps
} = props;
const baseId = useId('infolabel-');
const [open, setOpen] = React.useState(false);

const root = resolveShorthand(rootShorthand, {
required: true,
Expand Down Expand Up @@ -54,15 +55,26 @@ export const useInfoLabel_unstable = (props: InfoLabelProps, ref: React.Ref<HTML
},
});

const infoButtonPopover = resolveShorthand(infoButton?.popover, { required: true });
infoButtonPopover.onOpenChange = useEventCallback(
mergeCallbacks(infoButtonPopover.onOpenChange, (e, data) => {
setOpen(data.open);
}),
);

if (infoButton) {
infoButton.popover = infoButtonPopover;
infoButton.info = resolveShorthand(infoButton?.info, {
defaultProps: {
id: baseId + '__info',
},
});

infoButton['aria-labelledby'] ??= `${label.id} ${infoButton.id}`;
root['aria-owns'] ??= infoButton.info?.id;

if (open) {
root['aria-owns'] ??= infoButton.info?.id;
}
}

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { InfoButton } from '@fluentui/react-infobutton';
import { Label, Link, makeStyles, useId } from '@fluentui/react-components';
import { Label, makeStyles, useId } from '@fluentui/react-components';
import type { InfoButtonProps } from '@fluentui/react-infobutton';
import type { PopoverProps } from '@fluentui/react-components';

Expand All @@ -15,16 +15,11 @@ export const Default = (props: Partial<InfoButtonProps>) => {
const labelId = useId('label');
const infobuttonId = useId('infobutton');
const infobuttonInfoId = infobuttonId + '__info';

const [open, setOpen] = React.useState(false);

const info = (
<>
This is example information for an InfoButton. <Link href="https://react.fluentui.dev">Learn more</Link>
</>
);

const onOpenChange: PopoverProps['onOpenChange'] = (e, data) => setOpen(data.open);
const onOpenChange: PopoverProps['onOpenChange'] = (e, data) => {
setOpen(data.open);
};

return (
<div aria-owns={open ? infobuttonInfoId : undefined}>
Expand All @@ -35,7 +30,7 @@ export const Default = (props: Partial<InfoButtonProps>) => {
className={styles.infoButton}
info={{
id: infobuttonInfoId,
children: info,
children: 'This is example information for an InfoButton.',
}}
popover={{
onOpenChange,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { InfoButton } from '@fluentui/react-infobutton';
import { Label, Link, makeStyles, shorthands, useId } from '@fluentui/react-components';
import { Label, makeStyles, shorthands, useId } from '@fluentui/react-components';
import type { InfoButtonProps } from '@fluentui/react-infobutton';
import type { PopoverProps } from '@fluentui/react-components';

Expand All @@ -19,28 +19,19 @@ const useStyles = makeStyles({

const InfoButtonSize: React.FC<{ size: InfoButtonProps['size'] }> = ({ size }) => {
const styles = useStyles();
const labelId = useId('label');
const infobuttonId = useId('infobutton');
const infobuttonInfoId = infobuttonId + '__info';

const infobuttonInfoId = useId('infobuton__info');
const [open, setOpen] = React.useState(false);
const info = 'This is example information for an InfoButton.';

const info = (
<>
This is example information for an InfoButton. <Link href="https://react.fluentui.dev">Learn more</Link>
</>
);

const onOpenChange: PopoverProps['onOpenChange'] = (e, data) => setOpen(data.open);
const onOpenChange: PopoverProps['onOpenChange'] = (e, data) => {
setOpen(data.open);
};

return (
<div aria-owns={open ? infobuttonInfoId : undefined}>
<Label size={size} id={labelId}>
This is a {size} Infobutton
</Label>
<Label size={size}>This is a {size} Infobutton</Label>
<InfoButton
size={size}
id={infobuttonId}
className={styles.infoButton}
info={{
id: infobuttonInfoId,
Expand Down

0 comments on commit d2c1969

Please sign in to comment.