Skip to content

Commit

Permalink
feat(react): add IconTab component with size prop (#10301)
Browse files Browse the repository at this point in the history
* chore check in progress

* chore: check in progress

* feat(react): add size prop and IconTab

* fix(react): update class names and story for icon tabs

* test(react): update snapshots

* fix(react): use scss variable to declare icon tab height/width

* chore(react): fix typo

* fix(react): update iconSize prop and snapshots

* fix(react): add support for contained icon tabs

* feat(react): add tooltip to icon tab

* fix(react): update snapshots
  • Loading branch information
abbeyhrt authored Jan 14, 2022
1 parent c235676 commit 405c510
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 15 deletions.
34 changes: 34 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7960,6 +7960,31 @@ Map {
},
"render": [Function],
},
"unstable_IconTab" => Object {
"$$typeof": Symbol(react.forward_ref),
"propTypes": Object {
"children": Object {
"type": "node",
},
"className": Object {
"type": "string",
},
"defaultOpen": Object {
"type": "bool",
},
"enterDelayMs": Object {
"type": "number",
},
"label": Object {
"isRequired": true,
"type": "node",
},
"leaveDelayMs": Object {
"type": "number",
},
},
"render": [Function],
},
"unstable_Layer" => Object {
"propTypes": Object {
"as": Object {
Expand Down Expand Up @@ -8526,6 +8551,15 @@ Map {
"contained": Object {
"type": "bool",
},
"iconSize": Object {
"args": Array [
Array [
"default",
"lg",
],
],
"type": "oneOf",
},
"light": Object {
"type": "bool",
},
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ Array [
"unstable_HStack",
"unstable_Heading",
"unstable_IconButton",
"unstable_IconTab",
"unstable_Layer",
"unstable_Menu",
"unstable_MenuDivider",
Expand Down
10 changes: 8 additions & 2 deletions packages/react/src/components/Tabs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
*/

import * as FeatureFlags from '@carbon/feature-flags';
import { Tabs as TabsNext, TabPanel, TabPanels, TabList } from './next/Tabs';
import {
Tabs as TabsNext,
TabPanel,
TabPanels,
TabList,
IconTab,
} from './next/Tabs';
import { default as TabsClassic } from './Tabs';
import { default as TabsSkeletonClassic } from './Tabs.Skeleton';
import { default as TabsSkeletonNext } from './next/Tabs.Skeleton';
Expand All @@ -19,6 +25,6 @@ const TabsSkeleton = FeatureFlags.enabled('enable-v11-release')
? TabsSkeletonNext
: TabsSkeletonClassic;

export { TabsSkeleton, TabPanels, TabPanel, TabList };
export { TabsSkeleton, TabPanels, TabPanel, TabList, IconTab };

export default Tabs;
75 changes: 74 additions & 1 deletion packages/react/src/components/Tabs/next/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import PropTypes from 'prop-types';
import React, { useState, useRef, useEffect } from 'react';
import cx from 'classnames';
import { Tooltip } from '../../Tooltip/next';
import { keys, match, matches } from '../../../internal/keyboard';
import { usePrefix } from '../../../internal/usePrefix';
import { useId } from '../../../internal/useId';
Expand Down Expand Up @@ -125,6 +126,7 @@ function TabList({
light,
scrollIntoView,
contained = false,
iconSize,
...rest
}) {
const {
Expand All @@ -138,6 +140,8 @@ function TabList({
const className = cx(`${prefix}--tabs`, customClassName, {
[`${prefix}--tabs--contained`]: contained,
[`${prefix}--tabs--light`]: light,
[`${prefix}--tabs__icon--default`]: iconSize === 'default',
[`${prefix}--tabs__icon--lg`]: iconSize === 'lg',
});

const tabs = [];
Expand Down Expand Up @@ -242,6 +246,10 @@ TabList.propTypes = {
*/

contained: PropTypes.bool,
/**
* If using `IconTab`, specify the size of the icon being used.
*/
iconSize: PropTypes.oneOf(['default', 'lg']),
/**
* Specify whether or not to use the light component variant
*/
Expand Down Expand Up @@ -343,6 +351,71 @@ Tab.propTypes = {
renderButton: PropTypes.func,
};

const IconTab = React.forwardRef(function IconTab(
{
children,
className: customClassName,
defaultOpen = false,
enterDelayMs,
leaveDelayMs,
label,
...rest
},
ref
) {
const prefix = usePrefix();

const classNames = cx(`${prefix}--tabs__nav-item--icon`, customClassName);
return (
<Tooltip
align="bottom"
defaultOpen={defaultOpen}
className={`${prefix}--icon-tooltip`}
enterDelayMs={enterDelayMs}
label={label}
leaveDelayMs={leaveDelayMs}>
<Tab className={classNames} ref={ref} {...rest}>
{children}
</Tab>
</Tooltip>
);
});

IconTab.propTypes = {
/**
* Provide an icon to be rendered inside of `IconTab` as the visual label for Tab.
*/
children: PropTypes.node,

/**
* Specify an optional className to be added to your Tab
*/
className: PropTypes.string,

/**
* Specify whether the tooltip for the icon should be open when it first renders
*/
defaultOpen: PropTypes.bool,

/**
* Specify the duration in milliseconds to delay before displaying the tooltip for the icon.
*/
enterDelayMs: PropTypes.number,

/**
* Provide the label to be rendered inside of the Tooltip. The label will use
* `aria-labelledby` and will fully describe the child node that is provided.
* This means that if you have text in the child node it will not be
* announced to the screen reader.
*/
label: PropTypes.node.isRequired,

/**
* Specify the duration in milliseconds to delay before hiding the tooltip
*/
leaveDelayMs: PropTypes.number,
};

const TabPanel = React.forwardRef(function TabPanel(
{ children, className: customClassName, ...rest },
forwardRef
Expand Down Expand Up @@ -407,7 +480,7 @@ TabPanels.propTypes = {
children: PropTypes.node,
};

export { Tabs, Tab, TabPanel, TabPanels, TabList };
export { Tabs, Tab, IconTab, TabPanel, TabPanels, TabList };

// TO DO: implement horizontal scroll and the following props:
// leftOverflowButtonProps
Expand Down
52 changes: 40 additions & 12 deletions packages/react/src/components/Tabs/next/Tabs.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@
*/

import React from 'react';
import { Tabs, TabList, Tab, TabPanels, TabPanel } from './Tabs';
import { Tabs, TabList, Tab, TabPanels, TabPanel, IconTab } from './Tabs';
import Button from '../../Button';

import TabsSkeleton from './Tabs.Skeleton';
import { Monster20, Corn20, Bat20 } from '@carbon/icons-react';
import {
Monster20,
Corn20,
Bat20,
Monster16,
Corn16,
Bat16,
} from '@carbon/icons-react';

import { unstable_FeatureFlags as FeatureFlags } from 'carbon-components-react';

Expand Down Expand Up @@ -55,18 +62,39 @@ export const Default = () => (
</Tabs>
);

export const Icon20Only = () => (
<Tabs>
<TabList iconSize="lg" aria-label="List of tabs">
<IconTab label="Monster" disabled>
<Monster20 aria-label="Monster" />
</IconTab>
<IconTab label="Corn">
<Corn20 aria-label="Corn" />
</IconTab>
<IconTab label="Bat">
<Bat20 aria-label="Bat" />
</IconTab>
</TabList>
<TabPanels>
<TabPanel>Tab Panel 1</TabPanel>
<TabPanel>Tab Panel 2</TabPanel>
<TabPanel>Tab Panel 3</TabPanel>
</TabPanels>
</Tabs>
);

export const IconOnly = () => (
<Tabs>
<TabList aria-label="List of tabs">
<Tab disabled>
<Monster20 />
</Tab>
<Tab>
<Corn20 />
</Tab>
<Tab>
<Bat20 />
</Tab>
<TabList iconSize="default" aria-label="List of tabs">
<IconTab label="Monster" disabled>
<Monster16 aria-label="Monster" />
</IconTab>
<IconTab label="Corn">
<Corn16 aria-label="Corn" />
</IconTab>
<IconTab label="Bat">
<Bat16 aria-label="Bat" />
</IconTab>
</TabList>
<TabPanels>
<TabPanel>Tab Panel 1</TabPanel>
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ export {
TabPanel as unstable_TabPanel,
TabPanels as unstable_TabPanels,
TabList as unstable_TabList,
IconTab as unstable_IconTab,
} from './components/Tabs';
export { usePrefix as unstable_usePrefix } from './internal/usePrefix';
export {
Expand Down
21 changes: 21 additions & 0 deletions packages/styles/scss/components/tabs/_tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
@use '../../utilities/rotate' as *;
@use '../../utilities/box-shadow' as *;
@use '../../utilities/component-tokens' as *;
@use '../../utilities/custom-property';
@use '../../utilities/skeleton' as *;
@use '../../utilities/visually-hidden' as *;
@use '../../utilities/button-reset';
@use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/convert' as *;

$icon-tab-size: custom-property.get-var('icon-tab-size', rem(40px));

/// Tabs styles
/// @access public
/// @group tabs
Expand Down Expand Up @@ -244,6 +247,24 @@
text-align: left;
}

//-----------------------------
// Icon Item
//-----------------------------

.#{$prefix}--tabs__nav-item--icon,
&.#{$prefix}--tabs--contained .#{$prefix}--tabs__nav-item--icon {
display: flex;
width: $icon-tab-size;
height: $icon-tab-size;
align-items: center;
justify-content: center;
padding: 0;
}

&.#{$prefix}--tabs__icon--lg {
@include custom-property.declaration('icon-tab-size', rem(48px));
}

//-----------------------------
// Item Hover
//-----------------------------
Expand Down

0 comments on commit 405c510

Please sign in to comment.