Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 144 additions & 25 deletions packages/react-core/src/components/Tabs/examples/Tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ class SimpleTabs extends React.Component {

return (
<div>
<Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isBox={isBox} aria-label="Tabs in the default example">
<Tabs
activeKey={activeTabKey}
onSelect={this.handleTabClick}
isBox={isBox}
aria-label="Tabs in the default example"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
Users
</Tab>
Expand Down Expand Up @@ -99,7 +104,9 @@ class SimpleTabs extends React.Component {

### With tooltip react ref

When using a React ref to link a Tooltip to a Tab component, an `id` must be manually set on the Tooltip component, and the Tab component must have a matching `aria-describedby` attribute so that screen readers are able to announce the Tooltip contents.
When using a React ref to link a Tooltip to a Tab component via the `reference` prop, you should avoid manually passing in a value of "off" to the `aria-live` prop. Doing so may lead to the tooltip becoming less accessible to assistive technologies.

The tooltip should also have the `id` prop passed in. The value given to this prop should then be passed into the tab's `aria-describedby` prop. This ensures a tooltip used with a React ref will be announced by the JAWS and NVDA screen readers.

```js
import React from 'react';
Expand Down Expand Up @@ -132,7 +139,12 @@ class SimpleTabs extends React.Component {

return (
<div>
<Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isBox={isBox} aria-label="Tabs in the example with a tooltip ref">
<Tabs
activeKey={activeTabKey}
onSelect={this.handleTabClick}
isBox={isBox}
aria-label="Tabs in the example with a tooltip ref"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
Users
</Tab>
Expand All @@ -153,15 +165,15 @@ class SimpleTabs extends React.Component {
title={<TabTitleText>ARIA Disabled (Tooltip)</TabTitleText>}
isAriaDisabled
ref={tooltipRef}
aria-describedby="tooltip-tab-5"
aria-describedby="tooltip-ref1"
>
ARIA Disabled (Tooltip)
</Tab>
</Tabs>
<Tooltip
id="tooltip-ref1"
content="Aria-disabled tabs are like disabled tabs, but focusable. Allows for tooltip support."
reference={tooltipRef}
id="tooltip-tab-5"
/>
<div style={{ marginTop: '20px' }}>
<Checkbox
Expand Down Expand Up @@ -338,7 +350,12 @@ class ScrollButtonsPrimaryTabs extends React.Component {
const { activeTabKey, isBox } = this.state;
return (
<div>
<Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isBox={isBox} aria-label="Tabs in the default overflow example">
<Tabs
activeKey={activeTabKey}
onSelect={this.handleTabClick}
isBox={isBox}
aria-label="Tabs in the default overflow example"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
Users
</Tab>
Expand Down Expand Up @@ -424,7 +441,13 @@ class VerticalTabs extends React.Component {

return (
<div>
<Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isVertical isBox={isBox} aria-label="Tabs in the vertical example">
<Tabs
activeKey={activeTabKey}
onSelect={this.handleTabClick}
isVertical
isBox={isBox}
aria-label="Tabs in the vertical example"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
Users
</Tab>
Expand Down Expand Up @@ -689,7 +712,13 @@ class PageInsetsTabs extends React.Component {
const { activeTabKey, isBox } = this.state;
return (
<div>
<Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} usePageInsets isBox={isBox} aria-label="Tabs in the page insets example">
<Tabs
activeKey={activeTabKey}
onSelect={this.handleTabClick}
usePageInsets
isBox={isBox}
aria-label="Tabs in the page insets example"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
Users
</Tab>
Expand Down Expand Up @@ -753,7 +782,11 @@ class IconAndTextTabs extends React.Component {

render() {
return (
<Tabs activeKey={this.state.activeTabKey} onSelect={this.handleTabClick} aria-label="Tabs in the icons and text example">
<Tabs
activeKey={this.state.activeTabKey}
onSelect={this.handleTabClick}
aria-label="Tabs in the icons and text example"
>
<Tab
eventKey={0}
title={
Expand Down Expand Up @@ -876,9 +909,19 @@ class SecondaryTabs extends React.Component {
const { activeTabKey1, activeTabKey2, isBox } = this.state;
return (
<div>
<Tabs activeKey={activeTabKey1} onSelect={this.handleTabClickFirst} isBox={isBox} aria-label="Tabs in the tabs with subtabs example">
<Tabs
activeKey={activeTabKey1}
onSelect={this.handleTabClickFirst}
isBox={isBox}
aria-label="Tabs in the tabs with subtabs example"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
<Tabs aria-label="secondary tabs for users" activeKey={activeTabKey2} isSecondary onSelect={this.handleTabClickSecond}>
<Tabs
aria-label="secondary tabs for users"
activeKey={activeTabKey2}
isSecondary
onSelect={this.handleTabClickSecond}
>
<Tab eventKey={20} title={<TabTitleText>Secondary tab item 1</TabTitleText>}>
Secondary tab item 1 item section
</Tab>
Expand Down Expand Up @@ -983,7 +1026,13 @@ class FilledTabs extends React.Component {
const { activeTabKey, isBox } = this.state;
return (
<div>
<Tabs isFilled activeKey={activeTabKey} onSelect={this.handleTabClick} isBox={isBox} aria-label="Tabs in the filled example">
<Tabs
isFilled
activeKey={activeTabKey}
onSelect={this.handleTabClick}
isBox={isBox}
aria-label="Tabs in the filled example"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>
Users
</Tab>
Expand Down Expand Up @@ -1044,7 +1093,13 @@ class FilledTabsWithIcons extends React.Component {
const { activeTabKey, isBox } = this.state;
return (
<div>
<Tabs isFilled activeKey={activeTabKey} onSelect={this.handleTabClick} isBox={isBox} aria-label="Tabs in the filled with icons example">
<Tabs
isFilled
activeKey={activeTabKey}
onSelect={this.handleTabClick}
isBox={isBox}
aria-label="Tabs in the filled with icons example"
>
<Tab
eventKey={0}
title={
Expand Down Expand Up @@ -1270,7 +1325,11 @@ class SeparateTabContent extends React.Component {
render() {
return (
<React.Fragment>
<Tabs activeKey={this.state.activeTabKey} onSelect={this.handleTabClick} aria-label="Tabs in the seperate content example">
<Tabs
activeKey={this.state.activeTabKey}
onSelect={this.handleTabClick}
aria-label="Tabs in the seperate content example"
>
<Tab
eventKey={0}
title={<TabTitleText>Tab item 1</TabTitleText>}
Expand All @@ -1291,13 +1350,30 @@ class SeparateTabContent extends React.Component {
/>
</Tabs>
<div>
<TabContent eventKey={0} id="refTab1Section" ref={this.contentRef1} aria-label="This is content for the first tab">
<TabContent
eventKey={0}
id="refTab1Section"
ref={this.contentRef1}
aria-label="This is content for the first tab"
>
Tab 1 section
</TabContent>
<TabContent eventKey={1} id="refTab2Section" ref={this.contentRef2} aria-label="This is content for the second tab" hidden>
<TabContent
eventKey={1}
id="refTab2Section"
ref={this.contentRef2}
aria-label="This is content for the second tab"
hidden
>
Tab 2 section
</TabContent>
<TabContent eventKey={2} id="refTab3Section" ref={this.contentRef3} aria-label="This is content for the third tab" hidden>
<TabContent
eventKey={2}
id="refTab3Section"
ref={this.contentRef3}
aria-label="This is content for the third tab"
hidden
>
Tab 3 section
</TabContent>
</div>
Expand Down Expand Up @@ -1351,10 +1427,22 @@ const TabContentWithBody = () => {
<TabContent eventKey={0} id="refTab1Section" ref={contentRef1} aria-label="This is content for the first tab">
<TabContentBody hasPadding> Tab 1 section </TabContentBody>
</TabContent>
<TabContent eventKey={1} id="refTab2Section" ref={contentRef2} aria-label="This is content for the second tab" hidden>
<TabContent
eventKey={1}
id="refTab2Section"
ref={contentRef2}
aria-label="This is content for the second tab"
hidden
>
<TabContentBody hasPadding> Tab 2 section </TabContentBody>
</TabContent>
<TabContent eventKey={2} id="refTab3Section" ref={contentRef3} aria-label="This is content for the third tab" hidden>
<TabContent
eventKey={2}
id="refTab3Section"
ref={contentRef3}
aria-label="This is content for the third tab"
hidden
>
<TabContentBody hasPadding> Tab 3 section </TabContentBody>
</TabContent>
</div>
Expand Down Expand Up @@ -1385,7 +1473,12 @@ class MountingSimpleTabs extends React.Component {

render() {
return (
<Tabs mountOnEnter activeKey={this.state.activeTabKey} onSelect={this.handleTabClick} aria-label="Tabs in the children mounting on click example">
<Tabs
mountOnEnter
activeKey={this.state.activeTabKey}
onSelect={this.handleTabClick}
aria-label="Tabs in the children mounting on click example"
>
<Tab eventKey={0} title={<TabTitleText>Tab item 1</TabTitleText>}>
Tab 1 section
</Tab>
Expand Down Expand Up @@ -1423,7 +1516,12 @@ class UnmountingSimpleTabs extends React.Component {

render() {
return (
<Tabs unmountOnExit activeKey={this.state.activeTabKey} onSelect={this.handleTabClick} aria-label="Tabs in the unmounting invisible children example">
<Tabs
unmountOnExit
activeKey={this.state.activeTabKey}
onSelect={this.handleTabClick}
aria-label="Tabs in the unmounting invisible children example"
>
<Tab eventKey={0} title={<TabTitleText>Tab item 1</TabTitleText>}>
Tab 1 section
</Tab>
Expand Down Expand Up @@ -1473,23 +1571,44 @@ class ToggledSeparateContent extends React.Component {
{isTab2Hidden ? 'Show' : 'Hide'} tab 2
</Button>
<Divider style={{ paddingTop: '1rem', paddingBottom: '1rem' }} />
<Tabs activeKey={this.state.activeTabKey} onSelect={this.handleTabClick} aria-label="Tabs in the toggled separate content example">
<Tabs
activeKey={this.state.activeTabKey}
onSelect={this.handleTabClick}
aria-label="Tabs in the toggled separate content example"
>
<Tab eventKey={0} title="Tab item 1" tabContentId="refTab1Section" tabContentRef={this.contentRef1} />
{!isTab2Hidden && (
<Tab eventKey={1} title="Tab item 2" tabContentId="refTab2Section" tabContentRef={this.contentRef2} />
)}
<Tab eventKey={2} title="Tab item 3" tabContentId="refTab3Section" tabContentRef={this.contentRef3} />
</Tabs>
<div>
<TabContent eventKey={0} id="refTab1Section" ref={this.contentRef1} aria-label="This is content for the first tab">
<TabContent
eventKey={0}
id="refTab1Section"
ref={this.contentRef1}
aria-label="This is content for the first tab"
>
Tab 1 section
</TabContent>
{!isTab2Hidden && (
<TabContent eventKey={1} id="refTab2Section" ref={this.contentRef2} aria-label="This is content for the second tab" hidden>
<TabContent
eventKey={1}
id="refTab2Section"
ref={this.contentRef2}
aria-label="This is content for the second tab"
hidden
>
Tab 2 section
</TabContent>
)}
<TabContent eventKey={2} id="refTab3Section" ref={this.contentRef3} aria-label="This is content for the third tab" hidden>
<TabContent
eventKey={2}
id="refTab3Section"
ref={this.contentRef3}
aria-label="This is content for the third tab"
hidden
>
Tab 3 section
</TabContent>
</div>
Expand Down
8 changes: 8 additions & 0 deletions packages/react-core/src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export interface TooltipProps extends Omit<React.HTMLProps<HTMLDivElement>, 'con
* If you don't want that or prefer to add the aria attribute yourself on the trigger, set aria to 'none'.
*/
aria?: 'describedby' | 'labelledby' | 'none';
/**
* Determines whether the tooltip is an aria-live region. If the reference prop is passed in the
* default behavior is 'polite' in order to ensure the tooltip contents is announced to
* assistive technologies. Otherwise the default behavior is 'off'.
*/
'aria-live'?: 'off' | 'polite';
/**
* The reference element to which the Tooltip is relatively placed to.
* If you cannot wrap the reference with the Tooltip, you can use the reference prop instead.
Expand Down Expand Up @@ -155,6 +161,7 @@ export const Tooltip: React.FunctionComponent<TooltipProps> = ({
children,
animationDuration = 300,
reference,
'aria-live': ariaLive = reference ? 'polite' : 'off',
boundary,
isAppLauncher,
tippyProps,
Expand Down Expand Up @@ -251,6 +258,7 @@ export const Tooltip: React.FunctionComponent<TooltipProps> = ({
const hasCustomMaxWidth = maxWidth !== tooltipMaxWidth.value;
const content = (
<div
aria-live={ariaLive}
className={css(styles.tooltip, className)}
role="tooltip"
id={id}
Expand Down
Loading