diff --git a/packages/ui-tabs/src/Tabs/Panel/__tests__/Panel.test.tsx b/packages/ui-tabs/src/Tabs/Panel/__tests__/Panel.test.tsx
index d79b29e65d..38cec62175 100644
--- a/packages/ui-tabs/src/Tabs/Panel/__tests__/Panel.test.tsx
+++ b/packages/ui-tabs/src/Tabs/Panel/__tests__/Panel.test.tsx
@@ -49,4 +49,26 @@ describe('', () => {
expect(tabPanel).toHaveAttribute('role', 'tabpanel')
})
+
+ it('should not have tabIndex 0 by default', async () => {
+ const { container } = render(
+
+ Panel contents
+
+ )
+ const tabPanel = container.querySelector('[role="tabpanel"]')
+
+ expect(tabPanel).not.toHaveAttribute('tabIndex', '0')
+ })
+
+ it('should allow custom tabIndex', async () => {
+ const { container } = render(
+
+ Panel contents
+
+ )
+ const tabPanel = container.querySelector('[role="tabpanel"]')
+
+ expect(tabPanel).toHaveAttribute('tabIndex', '-1')
+ })
})
diff --git a/packages/ui-tabs/src/Tabs/Panel/index.tsx b/packages/ui-tabs/src/Tabs/Panel/index.tsx
index 1d8361a2e0..1ad95c33c3 100644
--- a/packages/ui-tabs/src/Tabs/Panel/index.tsx
+++ b/packages/ui-tabs/src/Tabs/Panel/index.tsx
@@ -98,6 +98,7 @@ class Panel extends Component {
styles,
active,
unmountOnExit,
+ tabIndex,
...props
} = this.props
@@ -106,10 +107,10 @@ class Panel extends Component {
{...passthroughProps(props)}
css={styles?.panel}
role="tabpanel"
- tabIndex={0}
id={id}
aria-labelledby={labelledBy}
aria-hidden={this.isHidden ? 'true' : undefined}
+ tabIndex={this.isHidden ? undefined : tabIndex}
ref={this.handleRef}
>
{
>
{
- {lorem.paragraphs()}
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+ commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
+ velit esse cillum dolore eu fugiat nulla pariatur.
- {lorem.paragraphs()}
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem
+ accusantium doloremque laudantium. Totam rem aperiam, eaque ipsa quae ab
+ illo inventore veritatis et quasi architecto beatae vitae dicta sunt
+ explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
+ odit aut fugit, sed quia consequuntur magni dolores.
- {lorem.paragraphs()}
+ At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis
+ praesentium voluptatum deleniti atque corrupti. Quos dolores et quas
+ molestias excepturi sint occaecati cupiditate non provident, similique
+ sunt in culpa. Qui officia deserunt mollitia animi, id est laborum et
+ dolorum fuga.
)
@@ -74,17 +89,29 @@ const Example = () => {
minHeight="10rem"
maxHeight="10rem"
>
-
+
Hello World
- {lorem.paragraphs()}
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+ commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
+ velit esse cillum dolore eu fugiat nulla pariatur.
-
- {lorem.paragraphs()}
+
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem
+ accusantium doloremque laudantium. Totam rem aperiam, eaque ipsa quae ab
+ illo inventore veritatis et quasi architecto beatae vitae dicta sunt
+ explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
+ odit aut fugit, sed quia consequuntur magni dolores.
-
- {lorem.paragraphs()}
+
+ At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis
+ praesentium voluptatum deleniti atque corrupti. Quos dolores et quas
+ molestias excepturi sint occaecati cupiditate non provident, similique
+ sunt in culpa. Qui officia deserunt mollitia animi, id est laborum et
+ dolorum fuga.
)
@@ -122,50 +149,57 @@ const Example = () => {
id="tabA"
renderTitle="Tab A"
isSelected={selectedIndex === 0}
+ tabIndex={0}
>
- {lorem.sentence()}
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- {lorem.sentence()}
+ Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
- {lorem.sentence()}
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
- {lorem.sentence()}
+ Duis aute irure dolor in reprehenderit in voluptate velit esse.
- {lorem.sentence()}
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa.
- {lorem.sentence()}
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem.
- {lorem.sentence()}
+ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit.
)
@@ -244,6 +278,7 @@ const Example = () => {
>
{
- {lorem.paragraphs()}
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
+ ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
+ aliquip ex ea commodo consequat. Duis aute irure dolor in
+ reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur.
- {lorem.paragraphs()}
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem
+ accusantium doloremque laudantium. Totam rem aperiam, eaque ipsa quae
+ ab illo inventore veritatis et quasi architecto beatae vitae dicta
+ sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit
+ aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.
- {lorem.paragraphs()}
+ At vero eos et accusamus et iusto odio dignissimos ducimus qui
+ blanditiis praesentium voluptatum deleniti atque corrupti. Quos
+ dolores et quas molestias excepturi sint occaecati cupiditate non
+ provident, similique sunt in culpa. Qui officia deserunt mollitia
+ animi, id est laborum et dolorum fuga.
@@ -299,7 +349,14 @@ const Outlet = () => {
{show ? 'Hello Developer' : 'Simulating network call...'}
{show ? (
- lorem.paragraphs()
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
+ minim veniam, quis nostrud exercitation ullamco laboris nisi ut
+ aliquip ex ea commodo consequat. Duis aute irure dolor in
+ reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur.
+
) : (
)}
@@ -327,6 +384,7 @@ const Example = () => {
padding="large"
isSelected={selectedIndex === 0}
active
+ tabIndex={0}
>
@@ -387,6 +445,7 @@ const Example = () => {
>
{
{
id="tabC"
renderTitle="Tab C"
isSelected={selectedIndex === 2}
+ tabIndex={0}
>
Tab C
@@ -415,6 +476,7 @@ const Example = () => {
id="tabD"
renderTitle="Tab D"
isSelected={selectedIndex === 3}
+ tabIndex={0}
>
Tab D
@@ -425,6 +487,52 @@ const Example = () => {
render()
```
+### Managing focus with tabIndex
+
+**Best practice:** For text-only panels, set `tabIndex={0}` to include the panel in the keyboard tab sequence—this ensures screen reader users can navigate to and read the content. For panels containing interactive elements (buttons, inputs, links), leave `tabIndex` unset so keyboard users tab directly to the controls without stopping on the panel container first.
+
+```js
+---
+type: example
+---
+const Example = () => {
+ const [selectedIndex, setSelectedIndex] = useState(0)
+
+ const handleTabChange = (event, { index }) => {
+ setSelectedIndex(index)
+ }
+
+ return (
+
+
+
+
+
+ This panel only contains text, so tabIndex is set to 0 to include it in the tab sequence.
+
+
+ )
+}
+
+render()
+```
+
### Guidelines
```js