Tabs

Allows the user to alternate between related views while remaining in the same context.

yarn add @workday/canvas-kit-react
Install
yarn add @workday/canvas-kit-react

Anatomy

Image of a Card with annotation markers.

  1. Active Tab: The tab that is selected and currently displaying it's contents.
  2. Inactive Tab: All of the other unselected, available tabs.
  3. Active Chip: Highlights the active tab.
  4. Divider Line: Spans the width of the entire tabs container separating the tab set from its contents.

Usage Guidance

  • Tabs are used to help the user navigate through information while remaining in context of the page. This is the most important reason to use Tabs. Users should not navigate to a different page when interacting with Tabs.
  • Content that is grouped within a Tab should always be related so that the user knows what to expect when they navigate each Tab. Never force users to switch back and forth between Tabs to complete a task.
  • Tab labels should be concise, scannable, and descriptive of their contents. Avoid using multiple words for Tab labels. Never use icons. To reduce cognitive load and a cluttered UI, avoid using more than 6 Tabs.
  • Tabs should directly relate to the page section they’re within.
  • The Tab divider line should span the full width of its container and create a clear distinction between what’s under the Tab sections and the rest of the page.
  • Do not use Tabs as a primary form of navigation.
  • When there are too many tabs to display at once, use the overflow menu to indicate that more Tabs are available.
  • The recommended minimum width of a tab is 88px, standard padding to the left and right is 24px, and minimum padding is 16px.
  • You can place most components within Tabs, because they operate like mini-pages. For example, Grids, Field Sets, and Prompts can all be added within a tabbed page.
  • You can use fixed Tabs, especially when the contents of a tab is scrollable.

When To Use

  • When content can be grouped into logical sections in order to avoid overwhelming the user with a lot of information. Tabs should cater for distinct groups of information.
  • To alternate between two or more sections of organized content while keeping the user in-context of the greater UI.
  • Use Tabs to help section off and organize related content.
  • When you have an abundance of related content to house in a small container.

When To Use Something Else

  • Consider an alternative solution if the information within multiple Tabs needs to be viewed simultaneously. Tabs are not suitable for comparing information or data, as it forces the user to rely on short term memory when switching back and forth between Tabs.
  • Consider using a more prominent, alternative form of navigation when there is a need for more than 6 or 7 Tabs.
  • Avoid using Tabs within a card UI.
  • If the content on a page is cohesive and doesn’t take up too much space, Tabs are likely unnecessary.
  • When Tabs are already being used on the page.

Variations

TypePurpose
Default/StandardShould be used in most use cases for tabs.
Full-WidthExclusively used in smaller containers ~300-400px width (e.g. within side panels or responsive UI).
  • No margin between Tabs. Tab widths are evenly proportioned, defined by its container.
  • Active chip spans full-width of the active Tab.
  • 2-3 Tabs max for this variation.
  • Do not use on large desktop experiences. More suitable for container widths less than 400px.
Wrapped TabsEdge case for when there is a requirement to have lengthy or multiple words for a Tab label.
  • Max of two lines wrapped.
  • This variation increases the overall Tab set height.

Touch Based Behavior

Touch Based behavior for Tab compnents on web adapt and mimic the mobile experience to allow overflow when the tab text stretches past the width of the users’ screen. These Tabs support mobile behavior based on modality and help support WebView users. Touch Based behavior for Tabs will switch from displaying an overflow menu to become scrollable from left to right in order to replicate a mobile experience when viewing a WebView screen (not a native mobile screen) on a mobile device.

States and Behavior

  • By default, Tabs should always contain one Tab with an active state.
  • Only one Tab can have an active state at a time.
  • The inactive state of a Tab can inherit a hover, focus, and selected state.
  • The active state of a Tab can only inherit a focus state.

Examples

Basic Example

Tabs includes a container Tabs component and the following subcomponents which can be composed in a variety of ways: Tabs.List, Tabs.Item and Tabs.Panel. It follows the W3 Tabs specification.

In this example, we set up a basic Tabs component with five tabs. This example uses a static API that does not support overflow.

Contents of First Tab
Contents of Second Tab
Contents of Third Tab
Contents of Fourth Tab
Contents of Fifth Tab

Overflow Tabs

Tabs is a responsive component based on the width of its container. If the rendered tabs exceed the width of the Tabs.List, an overflow menu will be rendered. This only works against the dynamic API where you give the TabsModel an array of items to be rendered. The dynamic API handles the React key for you based on the item's identifier. The dynamic API requires either an id on each item object or a getId function that returns an identifier based on the item. The below example uses an id property on each item.

The dynamic API takes in any object, but since nothing is known about your object, a render prop is necessary to instruct a list how it should render.

Contents of First Tab

Change Tabs container size

Hoisted Model

By default, Tabs will create and use its own model internally. Alternatively, you may configure your own model with useTabsModel and pass it to Tabs via the model prop. This pattern is referred to as hoisting the model and provides direct access to its state and events outside of the Tabs component.

In this example, we set up external observation of the model state and create an external button to trigger an event to change the active tab.

Named Tabs

Tabs.Item and Tabs.Panel both take an optional data-id attribute that is used for the onActivate callback. This example is identical to the Basic Example, but with tabs named using data-id for the Tabs.Item and Tabs.Panel subcomponents.

Right-to-Left (RTL)

Tabs supports right-to-left languages when specified in the CanvasProvider theme.

תוכן הראשון
תוכן השני
תוכן השלישי
תוכן הרביעי
תוכן החמישי

Disabled Tab

Set the disabled prop of a Tabs.Item to true to disable it.

Contents of First Tab
Contents of Disabled Tab
Contents of Third Tab

Tab Icons

Tabs can have icons. Use the Icon and Text subcomponents.

Contents of First Tab
Contents of Second Tab
Contents of Third Tab
Contents of Fourth Tab

Alternative Tab Stop

By default, tab panels are focusable for accessibility. If the contents of a tab panel have a focusable element, you may disable this default behavior by setting the tabIndex prop of Tabs.Panel to undefined. This example has a tab panel with a focusable button.


Contents of First Tab. The tab panel is no longer focusable, but the button is. It may be desirable to disable focus on the tab panel and allow focus to flow into the tab panel to the first focusable element.
Contents of Second Tab
Contents of Third Tab

Single Tab Panel

The compound component pattern allows for advanced composition. For example, Tabs can be composed to have only a single Tabs.Panel using attribute overrides and callbacks. More information about attributes and callbacks can be found in the prop tables below for each subcomponent.

In this example, we use a hoisted model and the activeTab property of the state to show content from the contents object.

Dynamic Tabs

The Tabs.Item component takes in an optional index property if you want to specify the position of a tab. If not defined, by default it will append tabs to the end. In this example, our tabs are stored as an array in the state, and we have a fixed tab at the end that can add new tabs to that array.

Contents of Tab 1

Component API

Tabs

Tabs is a container component that is responsible for creating a and sharing it with its subcomponents using React context. It does not represent a real element.

<Tabs onSelect={data => console.log('Selected tab', data.id)}>
{child components}
</Tabs>

Alternatively, you may pass in a model using the hoisted model pattern.

const model = useTabsModel({
onSelect(data) {
console.log('Activated Tab', data.id);
},
});
<Tabs model={model}>{child components}</Tabs>

See Configuring a Model for more information on model configuration.

Props

Props extend from . If a model is passed, props from TabsModelConfig are ignored.

NameTypeDescriptionDefault
childrenReactNode

The contents of the Tabs. Can be Tabs children or any valid elements.

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

Tabs.List

Tabs.List is a <div role="tablist"> element. It is a container for subcomponents.

<Tabs.List>{Tabs.Items}</Tabs.List>

Layout Component

Tabs.List supports all props from thelayout component.

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
children ((item: T) => ReactNode) ReactNode

If items are passed to a TabsModel, the child of Tabs.List should be a render prop. The List will determine how and when the item will be rendered.

overflowButtonReactNode
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useTabsList

(
  (
    model: ,
    elemProps: {},
    ref: React.Ref
  ) => {
    role: 'tablist';
    overflowX:  'auto' undefined;
  },
  ,
  
)

Tabs.Item

Tabs.Item is a <button role="tab"> element. Each Tabs.Item is associated with a Tabs.Panel either by a data-id attribute or by the position in the list. If a data-id is provided, it must match the data-id passed to the corresponding Tabs.Panel component.

<Tabs.Item data-id="first">First Tab</Tabs.Item>

Layout Component

Tabs.Item supports all props from thelayout component.

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
indexnumber

Optionally pass index to tab item. This should be done if Tabs.Item components were created via a Array::map function. This index will ensure keyboard navigation works even if items are inserted out of order.

childrenReactNode

The contents of the tab item. This will be the accessible name of the tab for screen readers. Often, this is text. Icons are also supported. Using Tabs.Icon will render an icon that is not visible to screen readers and therefore the icon should not be necessary to understand the tab. In most circumstances, aria-label should not be used.

<Tabs.Item>First Tab</Tabs.Item>
<Tabs.Item>
<Tabs.Icon icon={canvasIcon} />
<Tabs.Text>Second Tab</Tabs.Text>
</Tabs.Item>
data-idstring

The identifier of the tab. This identifier will be used in change events and for initialTab. Must match the data-id of the associated tab panel. If this property is not provided, it will default to a string representation of the the zero-based index of the Tab when it was initialized.

idstring

Optional id. If not set, it will inherit the ID passed to the Tabs component and append the index at the end. Only set this for advanced cases.

aria-controlsstring

Part of the ARIA specification for tabs. This attributes links a role=tab to a role=tabpanel. This value must be the same as the associated id attribute of the tab panel. This is automatically set by the component and should only be used in advanced cases.

aria-selectedboolean

Part of the ARIA specification for tabs. Lets screen readers know which tab is active. This should either be true or undefined and never false. This is automatically set by the component and should only be used in advanced cases.

tabIndexnumber

Part of the ARIA specification for tabs. The currently active tab should not have a tabIndex set while all inactive tabs should have a tabIndex={-1}

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useTabsItem

(
  (
    model: ,
    elemProps: {
      data-id: string;
    },
    ref: React.Ref
  ) => {
    type: 'button';
    role: 'tab';
    aria-selected: boolean;
    aria-controls: string;
  },
  ,
  ,
  ,
  
)

Tabs.Item.Icon

Layout Component

SystemIcon supports all props from thelayout component.

Props

Props extend from span. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
icon

The icon to display from @workday/canvas-system-icons-web.

size number string undefined

The size of the SystemIcon in px.

accent

The accent color of the SystemIcon. This overrides color.

accentHover

The accent color of the SystemIcon on hover. This overrides colorHover.

background

The background color of the SystemIcon.

'transparent'
backgroundHover

The background color of the SystemIcon on hover.

'transparent'
color

The color of the SystemIcon. This defines accent and fill. color may be overriden by accent and fill.

colorHover

The hover color of the SystemIcon. This defines accentHover and fillHover. colorHover may be overriden by accentHover and fillHover.

fill

The fill color of the SystemIcon. This overrides color.

fillHover

The fill color of the SystemIcon on hover. This overrides colorHover.

styles
shouldMirrorboolean

If set to true, transform the SVG's x-axis to mirror the graphic

false
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

span
refReact.Ref<R = span>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Tabs.Item.Text

Props

Props extend from span. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReact.ReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

span
refReact.Ref<R = span>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Tabs.Panel

Tabs.Panel is a <div role="tabpanel"> element. It is focusable by default. Each Tabs.Panel is controlled by a Tabs.Item either by a data-id attribute or by the position in the list. If a data-id is provided, it must match the data-id passed to the corresponding Tabs.Item component.

<Tabs.Panel data-id="first">
{contents of tab panel}
</Tabs.Panel>

Layout Component

Tabs.Panel supports all props from thelayout component.

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

The contents of the TabPanel.

data-idstring

The identifier of the tab. This identifier will be used in change events and for initialTab. Must match the data-id of the associated tab item. If this property is not provided, it will default to a string representation of the the zero-based index of the Tab when it was initialized.

tabIndexnumber

Part of the ARIA specification for tabs. By default, all tabpanel elements have a tabIndex of 0 which makes the whole content area receive focus. If you have a focusable item near the top of the tab panel content area, you may set tabIndex to undefined to prevent the tab panel element from receiving focus. Only do this is a child of the tab panel can receive focus.

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useTabsPanel

(
  model: ,
  elemProps: {
    data-id: string;
    item: <any>;
  },
  ref: React.Ref
) => {
  role: 'tabpanel';
  aria-labelledby: string;
  hidden: boolean;
  id: string;
  tabIndex: 0;
}

Tabs.Panels

Optional subcomponent of tabs that makes dealing with dynamic tabs easier. Tabs.Panels only works if the model is given an array of items.

const items = [{ id: '1', name: 'first' }]
<Tabs items={items}>
{tab list}
<Tabs.Panels>
{item => <Tabs.Panel>Contents of {item.name}</Tabs.Panel>}
</Tabs.Panels>
</Tabs>

Props

NameTypeDescriptionDefault
children ((item: T) => ReactNode) ReactNode
model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

Tabs.OverflowButton

The overflow button of a Tabs.List. When a tab list overflows, this overflow button is rendered. Overflow only works when the model is given an array of items.

<Tabs items={items}>
<Tabs.List overflowButton={
<Tabs.OverflowButton>More</Tabs.OverflowButton>
}>
{dynamic tab items}
</Tabs.List>
</Tabs>

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

The label text of the Tab.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useTabsOverflowButton

(
  (
    model: ,
    elemProps: {},
    ref: React.Ref
  ) => {
    aria-haspopup: true;
  },
  ,
  (
    (model: ) => ,
    
  )
)

Tabs.MenuPopper

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
anchorElement <Element> Element null

The reference element used to position the Popper. Popper content will try to follow the anchorElement if it moves and will reposition itself if there is no longer room in the window.

children ((props: {
    placement: ;
  }) => ReactNode)
ReactNode

The content of the Popper. If a function is provided, it will be treated as a Render Prop and pass the placement chosen by PopperJS. This placement value is useful if your popup needs to animate and that animation depends on the direction of the content in relation to the anchorElement.

getAnchorClientRect() => 

When provided, this optional callback will be used to determine positioning for the Popper element instead of calling getBoundingClientRect on the anchorElement prop. Use this when you need complete control over positioning. When this prop is specified, it is safe to pass null into the anchorElement prop. If null is passed into the anchorElement prop, an owner will not be provided for the PopupStack.

openboolean

Determines if Popper content should be rendered. The content only exists in the DOM when open is true

true
placement

The placement of the Popper contents relative to the anchorElement. Accepts auto, top, right, bottom, or left. Each placement can also be modified using any of the following variations: -start or -end.

fallbackPlacements[]

Define fallback placements by providing a list of in array (in order of preference). The default preference is following the order of top, right, bottom, and left. Once the initial and opposite placements are not available, the fallback placements will be in use. Use an empty array to disable the fallback placements.

onPlacementChange(placement: ) => void

A callback function that will be called whenever PopperJS chooses a placement that is different from the provided placement preference. If a placement preference doesn't fit, PopperJS will choose a new one and call this callback.

popperOptions<PopperOptions>

The additional options passed to the Popper's popper.js instance.

portalboolean

If false, render the Popper within the DOM hierarchy of its parent. A non-portal Popper will constrained by the parent container overflows. If you set this to false, you may experience issues where you content gets cut off by scrollbars or overflow: hidden

true
popperInstanceRefRef<>

Reference to the PopperJS instance. Useful for making direct method calls on the popper instance like update.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

usePopupPopper

Adds the necessary props to a component. Used by the subcomponent.

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  open: boolean;
  anchorElement: <>;
  ref: (instance:  null) => void;
  onPlacementChange: (placement: ) => void;
}

Tabs.Menu

The overflow menu of the Tabs component. If there isn't enough room to render all the tab items, the extra tabs that don't fit will be overflowed into this menu.

<Tabs.Menu.Popper>
<Tabs.Menu.Card>
<Tabs.Menu.List>
{(item: MyTabItem) => <Tabs.Menu.Item data-id={item.id}>
{item.text}
</Tabs.Menu.Item>}
</Tabs.Menu.List>
</Tabs.Menu.Card>
</Tabs.Menu.Popper>

This component references the component.

Model

useTabsModel

The TabsModel extends the Collection System. Tabs have tab items and panels. Tabs can be overflowed if there isn't enough room to render and will overflow to a sub-model.

const model = useTabsModel({
onSelect(data) {
console.log('Selected Tab', data)
}
})
<Tabs model={model}>{Tabs child components}</Tabs>
useTabsModel (config: ):

Specifications

GivenWhenThen
the Basic story is rendered
    • it should pass axe checks
    the Basic story is rendered
      • it should have an element with a role of "tablist"
      the Basic story is rendered
        • it should have elements with a role of "tab" inside the "tablist"
        the Basic story is rendered
          • it should have "aria-selected=true" for the first tab
          the Basic story is rendered
            • it should not have "aria-selected" for the second tab
            the Basic story is rendered
              • it should not have tabindex=-1 on the first tab
              the Basic story is rendered
                • it should have "tabindex=-1" on the second tab
                the Basic story is rendered
                  • it should have an id on the first tab
                  the Basic story is rendered
                    • it should label the tab panel "First Tab"
                    the Basic story is rendered
                      • it should have an "aria-controls" on the first tab
                      the Basic story is rendered
                        • it should have an "aria-controls" that matches the first tab panel
                        the Basic story is rendered
                          • it should have a default cursor for the (active) first tab
                          the Basic story is rendered
                            • it should have a pointer cursor for the second tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the tab key is pressed
                            • it should move focus to the tabpanel
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • it should have tabindex=-1 on the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • it should not have tabindex=-1 on the second tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • it should focus on the second tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the space key is pressed
                            • it should not have "aria-selected" on the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the space key is pressed
                            • it should have "aria-selected=true" on the second tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the enter key is pressed
                            • it should not have "aria-selected" on the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the enter key is pressed
                            • it should have "aria-selected=true" on the second tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the tab key is pressed
                            • it should focus on the tab panel of the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the tab key is pressed
                            • AND THEN shift + tab keys are pressed
                            • it should not have tabindex=-1 on the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the tab key is pressed
                            • AND THEN shift + tab keys are pressed
                            • it should set "tabindex=-1" on the second tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the right arrow key is pressed
                            • AND THEN the tab key is pressed
                            • AND THEN shift + tab keys are pressed
                            • it should focus on the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the left arrow is pressed
                            • it should have tabindex=-1 on the first tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the left arrow is pressed
                            • it should not have tabindex=-1 on the last tab
                            the Basic story is rendered
                            • the first tab is active and focused
                            • AND THEN the left arrow is pressed
                            • it should focus on the last tab
                            the Basic story is rendered
                            • the fifth tab is clicked
                            • it should show the contents of the fifth tab
                            the Basic story is rendered
                            • the fifth tab is clicked
                            • AND THEN the right arrow key is pressed
                            • it should not have tabindex=-1 on the first tab
                            the Basic story is rendered
                            • the fifth tab is clicked
                            • AND THEN the right arrow key is pressed
                            • it should set "tabindex=-1" on the last tab
                            the Named Tabs story is rendered
                              • it should pass axe checks
                              the Named Tabs story is rendered
                                • it should have an element with a role of "tablist"
                                the Named Tabs story is rendered
                                  • it should have elements with a role of "tab" inside the "tablist"
                                  the Named Tabs story is rendered
                                    • it should have "aria-selected=true" for the first tab
                                    the Named Tabs story is rendered
                                      • it should not have "aria-selected" for the second tab
                                      the Named Tabs story is rendered
                                        • it should not have tabindex=-1 on the first tab
                                        the Named Tabs story is rendered
                                          • it should have "tabindex=-1" on the second tab
                                          the Named Tabs story is rendered
                                            • it should have an id on the first tab
                                            the Named Tabs story is rendered
                                              • it should label the tab panel "First Tab"
                                              the Named Tabs story is rendered
                                                • it should have an "aria-controls" on the first tab
                                                the Named Tabs story is rendered
                                                  • it should have an "aria-controls" that matches the first tab panel
                                                  the Named Tabs story is rendered
                                                    • it should have a default cursor for the (active) first tab
                                                    the Named Tabs story is rendered
                                                      • it should have a pointer cursor for the second tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the tab key is pressed
                                                      • it should move focus to the tabpanel
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • it should have tabindex=-1 on the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • it should not have tabindex=-1 on the second tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • it should focus on the second tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the space key is pressed
                                                      • it should not have "aria-selected" on the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the space key is pressed
                                                      • it should have "aria-selected=true" on the second tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the enter key is pressed
                                                      • it should not have "aria-selected" on the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the enter key is pressed
                                                      • it should have "aria-selected=true" on the second tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the tab key is pressed
                                                      • it should focus on the tab panel of the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the tab key is pressed
                                                      • AND THEN shift + tab keys are pressed
                                                      • it should not have tabindex=-1 on the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the tab key is pressed
                                                      • AND THEN shift + tab keys are pressed
                                                      • it should set "tabindex=-1" on the second tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the tab key is pressed
                                                      • AND THEN shift + tab keys are pressed
                                                      • it should focus on the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow is pressed
                                                      • it should have tabindex=-1 on the first tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow is pressed
                                                      • it should not have tabindex=-1 on the last tab
                                                      the Named Tabs story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow is pressed
                                                      • it should focus on the last tab
                                                      the Named Tabs story is rendered
                                                      • the fifth tab is clicked
                                                      • it should show the contents of the fifth tab
                                                      the Named Tabs story is rendered
                                                      • the fifth tab is clicked
                                                      • AND THEN the right arrow key is pressed
                                                      • it should not have tabindex=-1 on the first tab
                                                      the Named Tabs story is rendered
                                                      • the fifth tab is clicked
                                                      • AND THEN the right arrow key is pressed
                                                      • it should set "tabindex=-1" on the last tab
                                                      the DisabledTab story is rendered
                                                      • the Disabled Tab is clicked
                                                      • it should not set "[aria-selected=true]" on the Disabled Tab
                                                      the DisabledTab story is rendered
                                                      • the Disabled Tab is clicked
                                                      • it should leave the first tab selected
                                                      the DisabledTab story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • it should focus on the Disabled Tab
                                                      the DisabledTab story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the enter key is pressed
                                                      • it should not set "[aria-selected=true]" on the Disabled Tab
                                                      the DisabledTab story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow key is pressed
                                                      • AND THEN the enter key is pressed
                                                      • it should leave the first tab selected
                                                      the DynamicTabs story is rendered
                                                      • "Add Tab" is clicked
                                                      • it should focus on "Add Tab"
                                                      the DynamicTabs story is rendered
                                                      • "Add Tab" is clicked
                                                      • AND THEN the left arrow key is pressed
                                                      • it should focus on Tab 4
                                                      the DynamicTabs story is rendered
                                                      • "Tab 1" is activated
                                                      • AND THEN the Delete key is pressed
                                                      • it should have "aria-selected=true" for "Tab 2"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 1" is activated
                                                      • AND THEN the Delete key is pressed
                                                      • it should show "Tab 2" contents
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the Delete key is pressed
                                                      • it should remove "Tab 2"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the Delete key is pressed
                                                      • it should move focus to "Tab 3"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the Delete key is pressed
                                                      • it should have "aria-selected=true" for "Tab 3"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the Delete key is pressed
                                                      • it should show "Tab 3" contents
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the Delete key is pressed
                                                      • AND THEN the Delete key is pressed again
                                                      • it should move focus to "Add Tab"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed twice
                                                      • AND THEN the Delete key is pressed
                                                      • it should remove "Tab 1"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed twice
                                                      • AND THEN the Delete key is pressed
                                                      • it should move focus to "Tab 2"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed twice
                                                      • AND THEN the Delete key is pressed
                                                      • it should have "aria-selected=true" for "Tab 3"
                                                      the DynamicTabs story is rendered
                                                      • "Tab 3" is activated
                                                      • AND THEN the left arrow key is pressed twice
                                                      • AND THEN the Delete key is pressed
                                                      • it should show "Tab 3" contents
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the tab key is pressed
                                                      • it should move focus to the tabpanel
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow key is pressed
                                                      • it should have tabindex=-1 on the first tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow key is pressed
                                                      • it should not have tabindex=-1 on the second tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow key is pressed
                                                      • it should focus on the second tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the space key is pressed
                                                      • it should not have "aria-selected" on the first tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the left arrow key is pressed
                                                      • AND THEN the space key is pressed
                                                      • it should have "aria-selected=true" on the second tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow is pressed
                                                      • it should have tabindex=-1 on the first tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow is pressed
                                                      • it should not have tabindex=-1 on the last tab
                                                      the LeftToRight story is rendered
                                                      • the first tab is active and focused
                                                      • AND THEN the right arrow is pressed
                                                      • it should focus on the last tab
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • it should pass axe checks
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • it should not show the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • it should have 7 tab items
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • it should not have scroll
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN the "First Tab" is focused
                                                      • AND THEN the Tab key is pressed
                                                      • it should focus on the tab panel
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • it should pass axe checks
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • it should show the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • it should show only 3 tab items
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • it should not have scroll
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • AND THEN the "First Tab" is focused
                                                      • AND THEN the Tab key is pressed
                                                      • it should focus on the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • AND THEN the "More" button is clicked
                                                      • it should show the Tab overflow menu
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • AND THEN the "More" button is clicked
                                                      • it should have the fourth Tab as the first menu item
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • AND THEN the "More" button is clicked
                                                      • AND THEN the "Sixth Tab" is clicked
                                                      • it should select the Sixth Tab
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 500px wide
                                                      • AND THEN the "More" button is clicked
                                                      • AND THEN the "Sixth Tab" is clicked
                                                      • it should move focus back to the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 360px wide
                                                      • it should pass axe checks
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 360px wide
                                                      • it should show the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 360px wide
                                                      • it should not have scroll
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 360px wide
                                                      • it should show only 2 tab items
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 360px wide
                                                      • AND THEN the "More" button is clicked
                                                      • it should show the Tab overflow menu
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 360px wide
                                                      • AND THEN the "More" button is clicked
                                                      • it should have the third Tab as the first menu item
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 150px wide
                                                      • it should pass axe checks
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 150px wide
                                                      • it should show the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 150px wide
                                                      • it should not have scroll
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 150px wide
                                                      • it should show no tab items
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 150px wide
                                                      • AND THEN the "More" button is clicked
                                                      • it should show the Tab overflow menu
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • AND THEN tab list container is only 150px wide
                                                      • AND THEN the "More" button is clicked
                                                      • it should have the third Tab as the first menu item
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • mobile viewport should not show the "More" button
                                                      Could not find a "given". Check the spec file.
                                                      • [Components/Containers/Tabs, OverflowTabs] story is rendered
                                                      • mobile viewport should have scroll behavior
                                                      Source: Tabs.spec.ts

                                                      Accessibility Guidelines

                                                      Keyboard Interaction

                                                      Each tab must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.

                                                      Tabs must support the following keyboard interactions:

                                                      • Tab: focus the active tab element
                                                      • Left Arrow or Right Arrow: move focus to the previous or next tab element
                                                      • Enter and Space: activate the focused tab element
                                                      • Alternative Tab Stop : tabpanel can optionally be included in focus order to improve discoverability for screen readers, and allow scrolling with the keyboard when the height is fixed.

                                                      Screen Reader Interaction

                                                      Tabs must communicate the following to users:

                                                      • The focus is placed on a tab control
                                                      • Which page tab in the set is currently selected
                                                      • How many total number of tabs are available

                                                      Design Annotations Needed

                                                      No design annotations needed.

                                                      Implementation Markup Needed

                                                      • Interactive elements are not allowed inside of a tablist or tab element.
                                                      • [Included in component] All tab buttons must have a role="tab", inside of a parent element with role="tablist" attribute.
                                                      • [Included in component] All tabs are required to have an aria-selected="false" attribute, except for the actively selected tab, must be set to “true”.
                                                      • [Included in component] The content area container for the tablist, must have a role="tabpanel" attribute and an aria-labelledby attribute referencing the unique id of the active tab element.

                                                      Resources

                                                      Content Guidelines

                                                      • When writing tab labels, be concise and avoid using multiple words when possible. Labels should clearly describe the contents of the tab to the user.
                                                      • The page or page section title (if applicable) should make clear sense when placed after the tab name. Try to imagine the page title is a noun after the tab label. For example: If the page is titled “Fruit”, and the tabs are labeled “ripe” and “rotten”. You could read it in your head as “ripe fruit” or “rotten fruit”.
                                                      • Refer to the UI Text > Tabs section of the Content Style Guide when writing tab labels.

                                                      Can't Find What You Need?

                                                      Check out our FAQ section which may help you find the information you're looking for.

                                                      FAQ Section