Skip to content

Commit

Permalink
feat(tab): introduce fixed variant (#4431)
Browse files Browse the repository at this point in the history
The new variant is enabled with `.bx--tabs--fixed` class.

Fixes #1329.
  • Loading branch information
asudoh authored Oct 25, 2019
1 parent 58accea commit 2811a2c
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
min-width: 100%;

@include breakpoint('42rem') {
min-width: 570px;
min-width: 720px;
}
}

Expand All @@ -165,6 +165,10 @@
margin-top: 2rem;
}

.bx--tabs.bx--tabs--fixed + div {
margin-top: 0;
}

#tab-panel-1,
#tab-panel-2,
#tab-panel-3,
Expand All @@ -181,6 +185,15 @@
}
}

.component-example__live,
.demo--container {
.bx--tabs--fixed + div {
width: 100%;
height: 320px;
background-color: $ui-01;
}
}

.page-header + div > .bx--tabs {
background-color: $field-01;

Expand Down
98 changes: 97 additions & 1 deletion packages/components/src/components/tabs/_tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
}
}

.#{$prefix}--tabs--fixed {
@include carbon--breakpoint(md) {
min-height: rem(48px);
}
}

.#{$prefix}--tabs-trigger {
display: flex;
align-items: center;
Expand Down Expand Up @@ -153,6 +159,23 @@
}
}

.#{$prefix}--tabs--fixed .#{$prefix}--tabs__nav-item {
@include carbon--breakpoint(md) {
background-color: $ui-03;

& + .#{$prefix}--tabs__nav-item {
margin-left: 0;
// Draws the border without affecting the inner-content
box-shadow: -1px 0 0 0 $ui-04;
}

& + .#{$prefix}--tabs__nav-item.#{$prefix}--tabs__nav-item--selected,
&.#{$prefix}--tabs__nav-item--selected + .#{$prefix}--tabs__nav-item {
box-shadow: none;
}
}
}

.#{$prefix}--tabs__nav-item .#{$prefix}--tabs__nav-link {
transition: color $duration--fast-01 motion(standard, productive),
border-bottom-color $duration--fast-01 motion(standard, productive),
Expand All @@ -174,7 +197,18 @@

@include carbon--breakpoint(md) {
background-color: transparent;
box-shadow: none;

&,
& + .#{$prefix}--tabs__nav-item {
box-shadow: none;
}
}
}

.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item:hover:not(.#{$prefix}--tabs__nav-item--disabled) {
@include carbon--breakpoint(md) {
background-color: $hover-selected-ui;
}
}

Expand All @@ -191,6 +225,23 @@
pointer-events: none;
}

.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item.#{$prefix}--tabs__nav-item--disabled,
.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item.#{$prefix}--tabs__nav-item--disabled:hover {
@include carbon--breakpoint(md) {
background-color: $disabled-02;
}
}

.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item--disabled
.#{$prefix}--tabs__nav-link {
@include carbon--breakpoint(md) {
color: $disabled-03;
}
}

//-----------------------------
// Item Selected
//-----------------------------
Expand All @@ -215,6 +266,26 @@
}
}

.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item--selected:not(.#{$prefix}--tabs__nav-item--disabled),
.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item--selected:hover:not(.#{$prefix}--tabs__nav-item--disabled) {
@include carbon--breakpoint(md) {
background-color: $ui-01;

.#{$prefix}--tabs__nav-link {
// Draws the border without affecting the inner-content
box-shadow: inset 0 2px 0 0 $interactive-04;
border-bottom: none;
}

.#{$prefix}--tabs__nav-link:focus,
.#{$prefix}--tabs__nav-link:active {
box-shadow: none;
}
}
}

//-----------------------------
// Link
//-----------------------------
Expand Down Expand Up @@ -260,6 +331,15 @@
}
}

.#{$prefix}--tabs--fixed a.#{$prefix}--tabs__nav-link {
@include carbon--breakpoint(md) {
display: flex;
align-items: center;
height: rem(48px);
border-bottom: none;
}
}

//-----------------------------
// Link Hover
//-----------------------------
Expand All @@ -272,6 +352,14 @@
}
}

.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item:hover:not(.#{$prefix}--tabs__nav-item--selected):not(.#{$prefix}--tabs__nav-item--disabled)
.#{$prefix}--tabs__nav-link {
@include carbon--breakpoint(md) {
border-bottom: none;
}
}

//-----------------------------
// Link Disabled
//-----------------------------
Expand All @@ -291,6 +379,14 @@
border-bottom: $tab-underline-disabled;
}

.#{$prefix}--tabs--fixed
.#{$prefix}--tabs__nav-item--disabled
.#{$prefix}--tabs__nav-link {
@include carbon--breakpoint(md) {
border-bottom: none;
}
}

//-----------------------------
// Link Focus
//-----------------------------
Expand Down
36 changes: 22 additions & 14 deletions packages/components/src/components/tabs/tabs.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,33 @@

const { prefix } = require('../../globals/js/settings');

const items = [
const items = idSuffix => [
{
linkId: 'tab-link-1',
panelId: 'tab-panel-1',
panelClass: 'tab-1',
linkId: `tab-link-1-${idSuffix}`,
panelId: `tab-panel-1-${idSuffix}`,
panelClass: `tab-1-${idSuffix}`,
label: 'Tab label 1',
panelContent: 'Content for first tab goes here.',
selected: true,
},
{
linkId: 'tab-link-2',
panelId: 'tab-panel-2',
panelClass: 'tab-2',
linkId: `tab-link-2-${idSuffix}`,
panelId: `tab-panel-2-${idSuffix}`,
panelClass: `tab-2-${idSuffix}`,
label: 'Tab label 2',
panelContent: 'Content for second tab goes here.',
},
{
linkId: 'tab-link-3',
panelId: 'tab-panel-3',
panelClass: 'tab-3',
linkId: `tab-link-3-${idSuffix}`,
panelId: `tab-panel-3-${idSuffix}`,
panelClass: `tab-3-${idSuffix}`,
label: 'Tab label 3',
panelContent: 'Content for third tab goes here.',
},
{
linkId: 'tab-link-4',
panelId: 'tab-panel-4',
panelClass: 'tab-4',
linkId: `tab-link-4-${idSuffix}`,
panelId: `tab-panel-4-${idSuffix}`,
panelClass: `tab-4-${idSuffix}`,
label: 'Tab label 4',
panelContent: 'Content for fourth tab goes here.',
disabled: true,
Expand All @@ -51,7 +51,15 @@ module.exports = {
name: 'default',
label: 'Tabs',
context: {
items,
items: items('default'),
},
},
{
name: 'fixed',
label: 'Tabs (fixed)',
context: {
fixed: true,
items: items('fixed'),
},
},
],
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/components/tabs/tabs.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
LICENSE file in the root directory of this source tree.
-->

<div data-tabs class="{{@root.prefix}}--tabs">
<div data-tabs class="{{@root.prefix}}--tabs{{#if fixed}} {{@root.prefix}}--tabs--fixed{{/if}}">
<div class="{{@root.prefix}}--tabs-trigger" tabindex="0">
<a href="javascript:void(0)" class="{{@root.prefix}}--tabs-trigger-text" tabindex="-1"></a>
{{ carbon-icon 'ChevronDownGlyph' }}
Expand Down
42 changes: 41 additions & 1 deletion packages/react/src/components/Tabs/Tabs-story.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import './Tabs-story.scss';

import { withKnobs, boolean, number, text } from '@storybook/addon-knobs';
import Tabs from '../Tabs';
Expand All @@ -27,7 +28,8 @@ const props = {
'The description of the trigger icon for narrow mode (iconDescription in <Tabs>)',
'show menu options'
),
onClick: action('onClick'),
// Disabling action logger for `<Tabs onClick>` for now given it seems to be significantly slowing down Storybook
// onClick: action('onClick'),
onKeyDown: action('onKeyDown'),
onSelectionChange: action('onSelectionChange'),
tabContentClassName: text(
Expand Down Expand Up @@ -94,6 +96,44 @@ storiesOf('Tabs', module)
},
}
)
.add(
'Fixed',
() => (
<Tabs type="fixed" {...props.tabs()}>
<Tab {...props.tab()} label="Tab label 1">
<div className="some-content" style={{ paddingLeft: 16 }}>
Content for first tab goes here.
</div>
</Tab>
<Tab {...props.tab()} label="Tab label 2">
<div className="some-content" style={{ paddingLeft: 16 }}>
Content for second tab goes here.
</div>
</Tab>
<Tab
{...props.tab()}
label="Tab label 3"
renderContent={TabContentRenderedOnlyWhenSelected}>
<div className="some-content" style={{ paddingLeft: 16 }}>
Content for third tab goes here.
</div>
</Tab>
<Tab {...props.tab()} label={<CustomLabel text="Custom Label" />}>
<div className="some-content" style={{ paddingLeft: 16 }}>
Content for fourth tab goes here.
</div>
</Tab>
</Tabs>
),
{
info: {
text: `
Tabs are used to quickly navigate between views within the same context. Create individual
Tab components for each item in the Tabs list.
`,
},
}
)
.add('skeleton', () => <TabsSkeleton />, {
info: {
text: `
Expand Down
9 changes: 9 additions & 0 deletions packages/react/src/components/Tabs/Tabs-story.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// IMPORTANT: This import path should _not_ be used outside our source tree
// as `src` directory is _not_ meant to be shipped in our NPM package.
// Use e.g. `@import '~carbon-components/scss/globals/scss/styles.scss'` instead.
@import '~carbon-components/src/globals/scss/css--helpers'; // SEE THE NOTE ABOVE

.bx--tabs--fixed ~ div {
height: 320px;
background-color: $ui-01;
}
14 changes: 14 additions & 0 deletions packages/react/src/components/Tabs/Tabs-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ describe('Tabs', () => {
.hasClass(`${prefix}--tabs`)
).toBe(true);
});

it('supports fixed variant', () => {
expect(
shallow(
<Tabs className="extra-class" type="fixed">
<Tab label="firstTab">content1</Tab>
<Tab label="lastTab">content2</Tab>
</Tabs>
)
.find('div')
.first()
.hasClass(`${prefix}--tabs--fixed`)
).toBe(true);
});
});

describe('Trigger (<div>)', () => {
Expand Down
11 changes: 10 additions & 1 deletion packages/react/src/components/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export default class Tabs extends React.Component {
*/
role: PropTypes.string.isRequired,

/**
* Provide the type of Tab
*/
type: PropTypes.oneOf(['default', 'fixed']),

/**
* Optionally provide an `onClick` handler that is invoked when a <Tab> is
* clicked
Expand Down Expand Up @@ -87,6 +92,7 @@ export default class Tabs extends React.Component {
static defaultProps = {
iconDescription: 'show menu options',
role: 'navigation',
type: 'default',
triggerHref: '#',
selected: 0,
ariaLabel: 'listbox',
Expand Down Expand Up @@ -191,6 +197,7 @@ export default class Tabs extends React.Component {
className,
triggerHref,
role,
type,
onSelectionChange,
tabContentClassName,
...other
Expand Down Expand Up @@ -241,7 +248,9 @@ export default class Tabs extends React.Component {
});

const classes = {
tabs: classNames(`${prefix}--tabs`, className),
tabs: classNames(`${prefix}--tabs`, className, {
[`${prefix}--tabs--fixed`]: type === 'fixed',
}),
tablist: classNames(`${prefix}--tabs__nav`, {
[`${prefix}--tabs__nav--hidden`]: this.state.dropdownHidden,
}),
Expand Down

0 comments on commit 2811a2c

Please sign in to comment.