Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Tabs): Contained tabs on the grid #13927

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
698a6ec
feat(Tabs): allow tabs to distribute width with new normalizeWidth prop
francinelucca Jun 5, 2023
06eba0e
Merge branch 'main' of github.com:carbon-design-system/carbon into 13…
francinelucca Jun 7, 2023
054642d
feat(Tabs): add ellipsis overflow to fullWidth tabs and add test stories
francinelucca Jun 7, 2023
1cacef1
Merge branch 'main' into 13353-tabs-implement-contained-tabs-on-the-c…
francinelucca Jun 7, 2023
65b6472
Merge branch 'main' of github.com:carbon-design-system/carbon into 13…
francinelucca Jun 12, 2023
9a5e81e
fix(Tabs): mock useMatchMedia for tests and add fullWidth tests
francinelucca Jun 12, 2023
1a56114
fix: update snapshot
francinelucca Jun 12, 2023
f45617d
Merge branch 'main' into 13353-tabs-implement-contained-tabs-on-the-c…
guidari Jun 16, 2023
d6dce49
fix: add more docs around tabs in the grid
francinelucca Jun 16, 2023
6b92b17
Merge branch 'main' into 13353-tabs-implement-contained-tabs-on-the-c…
francinelucca Jun 19, 2023
a1924e2
Merge branch 'main' of github.com:carbon-design-system/carbon into 13…
francinelucca Jun 20, 2023
2e89178
fix: format
francinelucca Jun 20, 2023
f407b2a
Merge branch 'main' into 13353-tabs-implement-contained-tabs-on-the-c…
francinelucca Jun 20, 2023
ef33660
chore(Tabs): remove test story
francinelucca Jun 21, 2023
2d908a9
Merge branch '13353-tabs-implement-contained-tabs-on-the-css-grid' of…
francinelucca Jun 21, 2023
b842a48
Merge branch 'main' into 13353-tabs-implement-contained-tabs-on-the-c…
francinelucca Jun 21, 2023
fec0348
Merge branch 'main' into 13353-tabs-implement-contained-tabs-on-the-c…
guidari Jun 22, 2023
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
8 changes: 8 additions & 0 deletions e2e/components/Tabs/Tabs-test.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ test.describe('Tabs', () => {
});
});

test('contained fullWidth @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'Tabs',
id: 'components-tabs--contained-full-width',
theme,
});
});

test('contained with secondary labels @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'Tabs',
Expand Down
28 changes: 26 additions & 2 deletions packages/react/src/components/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { ChevronLeft, ChevronRight } from '@carbon/icons-react';
import { breakpoints } from '@carbon/layout';
import cx from 'classnames';
import debounce from 'lodash.debounce';
import PropTypes from 'prop-types';
Expand All @@ -23,6 +24,7 @@ import { usePressable } from './usePressable';
import deprecate from '../../prop-types/deprecate';
import { Close } from '@carbon/icons-react';
import { useEvent } from '../../internal/useEvent';
import { useMatchMedia } from '../../internal/useMatchMedia';

// Used to manage the overall state of the Tabs
const TabsContext = React.createContext();
Expand All @@ -32,6 +34,9 @@ const TabContext = React.createContext();

// Used to keep track of position in a list of tab panels
const TabPanelContext = React.createContext();

const lgMediaQuery = `(min-width: ${breakpoints.lg.width})`;

function Tabs({
children,
defaultSelectedIndex = 0,
Expand Down Expand Up @@ -138,6 +143,7 @@ function TabList({
children,
className: customClassName,
contained = false,
fullWidth = false,
iconSize,
leftOverflowButtonProps,
light,
Expand All @@ -160,6 +166,14 @@ function TabList({
const [isScrollable, setIsScrollable] = useState(false);
const [scrollLeft, setScrollLeft] = useState(null);

const isLg = useMatchMedia(lgMediaQuery);

const distributeWidth =
fullWidth &&
contained &&
isLg &&
React.Children.toArray(children).length < 9;

// Previous Button
// VISIBLE IF:
// SCROLLABLE
Expand All @@ -186,6 +200,7 @@ function TabList({
[`${prefix}--tabs__icon--default`]: iconSize === 'default',
[`${prefix}--tabs__icon--lg`]: iconSize === 'lg',
[`${prefix}--tabs--tall`]: hasSecondaryLabelTabs,
[`${prefix}--tabs--full-width`]: distributeWidth,
});

const isPreviousButtonVisible = ref.current
Expand Down Expand Up @@ -451,6 +466,11 @@ TabList.propTypes = {
*/
contained: PropTypes.bool,

/**
* Used for tabs within a grid, this makes it so tabs span the full container width and have the same width. Only available on contained tabs with <9 children
*/
fullWidth: PropTypes.bool,

/**
* If using `IconTab`, specify the size of the icon being used.
*/
Expand Down Expand Up @@ -651,7 +671,9 @@ const Tab = React.forwardRef(function Tab(
{<Icon size={16} />}
</div>
)}
<span className={`${prefix}--tabs__nav-item-label`}>{children}</span>
<span className={`${prefix}--tabs__nav-item-label`} title={children}>
{children}
</span>
{/* always rendering dismissIcon so we don't lose reference to it, otherwise events do not work when switching from/to dismissable state */}
<div
className={cx(`${prefix}--tabs__nav-item--icon`, {
Expand All @@ -662,7 +684,9 @@ const Tab = React.forwardRef(function Tab(
</div>
</div>
{hasSecondaryLabel && (
<div className={`${prefix}--tabs__nav-item-secondary-label`}>
<div
className={`${prefix}--tabs__nav-item-secondary-label`}
title={secondaryLabel}>
{secondaryLabel}
</div>
)}
Expand Down
53 changes: 52 additions & 1 deletion packages/react/src/components/Tabs/Tabs.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Props, Preview, Story } from '@storybook/addon-docs';
import { Props, Preview, Story, Canvas } from '@storybook/addon-docs';
import { Tabs, TabList, Tab, TabPanels, TabPanel } from './Tabs';
import { Grid, Column } from '../Grid'

# Tabs

Expand All @@ -9,6 +10,8 @@ import { Tabs, TabList, Tab, TabPanels, TabPanel } from './Tabs';
&nbsp;|&nbsp;
[Accessibility](https://www.carbondesignsystem.com/components/tabs/accessibility)

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Table of Contents

- [Overview](#overview)
Expand All @@ -18,12 +21,15 @@ import { Tabs, TabList, Tab, TabPanels, TabPanel } from './Tabs';
- [Dismissable Tabs](#dismissable-tabs)
- [Component API](#component-api)
- [Tab - render content on click](#tab---render-content-on-click)
- [Tabs and the Grid - fullWidth prop](#tabs-and-the-grid---fullwidth-prop)
- [V11](#v11)
- [Tabs composition](#tabs-composition)
- [Various updates](#various-updates)
- [Max width](#max-width)
- [Feedback](#feedback)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Overview

Use tabs to allow users to navigate easily between views within the same
Expand Down Expand Up @@ -201,6 +207,51 @@ loaded when the Tab is clicked. In v11, to do this, you can this by setting
</Tabs>
```

### Tabs and the Grid - fullWidth prop

By default, a `Tab` component is only as wide as it's content. This posses difficulties when trying to align tabs to the grid.
Alternatively, you may choose to use the `fullWidth` prop to allow Tab elements to grow as big wide their container allows.
Note that this feature is *only available* for `contained` tabs with less than 9 tabs, otherwise the prop will be ignored.
`fullWidth` paired up with a wrapping `Grid` component will allow for "grid-aware" tabs:
francinelucca marked this conversation as resolved.
Show resolved Hide resolved

<Canvas>
<Grid condensed>
<Column lg={16} md={8} sm={4}>
<Tabs>
<TabList aria-label="List of tabs" contained fullWidth>
<Tab>Tab Label 1</Tab>
<Tab>Tab Label 2</Tab>
<Tab disabled>Tab Label 3</Tab>
</TabList>
<TabPanels>
<TabPanel>Tab Panel 1</TabPanel>
<TabPanel>Tab Panel 2</TabPanel>
<TabPanel>Tab Panel 3</TabPanel>
</TabPanels>
</Tabs>
</Column>
</Grid>
</Canvas>

```jsx
<Grid condensed>
<Column lg={16} md={8} sm={4}>
<Tabs>
<TabList aria-label="List of tabs" contained fullWidth>
<Tab>Tab Label 1</Tab>
<Tab>Tab Label 2</Tab>
<Tab disabled>Tab Label 3</Tab>
</TabList>
<TabPanels>
<TabPanel>Tab Panel 1</TabPanel>
<TabPanel>Tab Panel 2</TabPanel>
<TabPanel>Tab Panel 3</TabPanel>
</TabPanels>
</Tabs>
</Column>
</Grid>
```

## V11

### Tabs composition
Expand Down
Loading