Skip to content

Commit

Permalink
feat(components/tabbar): be able to disable responsive behavior (#2412)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabien Rassinier authored Sep 17, 2019
1 parent 358e06a commit 15ad774
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,11 @@ exports[`Drawer should render with tabs 1`] = `
onKeyDown={[Function]}
>
<ul
className="tc-tab-bar theme-tc-responsive-tab-bar nav nav-tabs"
className="theme-tc-tab-bar tc-tab-bar theme-tc-tab-bar-responsive tc-tab-bar-responsive nav nav-tabs"
role="tablist"
>
<li
className=""
className="theme-tc-tab-bar-item tc-tab-bar-item"
role="presentation"
>
<button
Expand All @@ -209,7 +209,7 @@ exports[`Drawer should render with tabs 1`] = `
</button>
</li>
<li
className="active"
className="theme-tc-tab-bar-item tc-tab-bar-item active"
role="presentation"
>
<button
Expand Down
57 changes: 42 additions & 15 deletions packages/components/src/TabBar/TabBar.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ function TabBar(props) {

const [showDropdown, setShowDropDown] = useState(false);

const { responsive = true } = props;

function tryShowDropdown() {
const tabContainer = tabBarContainerRef.current;
if (tabContainer) {
Expand All @@ -43,8 +45,11 @@ function TabBar(props) {
}

useEffect(() => {
const resizeListener = window.addEventListener('resize', debounce(showTabBarAndTest, 200));
return () => window.removeEventListener('resize', resizeListener);
if (responsive) {
const resizeListener = window.addEventListener('resize', debounce(showTabBarAndTest, 200));
return () => window.removeEventListener('resize', resizeListener);
}
return undefined;
}, []);

useEffect(() => {
Expand All @@ -62,7 +67,9 @@ function TabBar(props) {
});

useEffect(() => {
tryShowDropdown();
if (responsive) {
tryShowDropdown();
}
}, []);

const { onSelect } = props; // to avoid react/no-unused-prop-types
Expand Down Expand Up @@ -104,19 +111,28 @@ function TabBar(props) {
</Tab.Content>
);

if (showDropdown) {
if (responsive && showDropdown) {
return (
<React.Fragment>
<form>
<div className={theme['tc-responsive-tab-bar-select-container']}>
<select onChange={event => handleSelect(event.target.value, event)} value={selectedKey}>
{items.map(item => (
<option value={item.key} key={item.key}>
{item.label}
</option>
))}
</select>
</div>
<select
className={classnames(theme['tc-tab-bar-dropdown'], 'tc-tab-bar-dropdown')}
onChange={event => handleSelect(event.target.value, event)}
value={selectedKey}
>
{items.map(item => (
<option
className={classnames(
theme['tc-tab-bar-dropdown-item'],
'tc-tab-bar-dropdown-item',
)}
value={item.key}
key={item.key}
>
{item.label}
</option>
))}
</select>
</form>
{tabContent}
</React.Fragment>
Expand All @@ -134,11 +150,21 @@ function TabBar(props) {
<div ref={tabBarContainerRef}>
<Nav
bsStyle="tabs"
className={classnames('tc-tab-bar', theme['tc-responsive-tab-bar'])}
className={classnames(
theme['tc-tab-bar'],
'tc-tab-bar',
responsive && theme['tc-tab-bar-responsive'],
responsive && 'tc-tab-bar-responsive',
)}
ref={tabBarRef}
>
{items.map(item => (
<NavItem {...item} eventKey={item.key} componentClass="button">
<NavItem
className={classnames(theme['tc-tab-bar-item'], 'tc-tab-bar-item')}
{...item}
eventKey={item.key}
componentClass="button"
>
{item.label}
</NavItem>
))}
Expand All @@ -164,6 +190,7 @@ TabBar.propTypes = {
}).isRequired,
).isRequired,
onSelect: PropTypes.func.isRequired,
responsive: PropTypes.bool,
selectedKey: PropTypes.any,
};

Expand Down
13 changes: 6 additions & 7 deletions packages/components/src/TabBar/TabBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M8 13.6l-8-8L2.6 3 8 8.4 13.4 3 16 5.6z" fill="#{hex-to-url($color)}"/></svg>');
}

.tc-responsive-tab-bar {
overflow: hidden;
.tc-tab-bar {
white-space: nowrap;
overflow: hidden;

li {
& &-item {
float: none;
display: inline-block;
}
}
.tc-responsive-tab-bar-select-container {
select {

&-dropdown {
@include caret-down($st-tropaz);
background-position: right center;
background-repeat: no-repeat;
Expand All @@ -35,7 +34,7 @@
appearance: none;
padding: 13px 30px 12px 20px;

option {
&-item {
color: initial;
}
}
Expand Down
14 changes: 12 additions & 2 deletions packages/components/src/TabBar/__snapshots__/TabBar.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ exports[`TabBar component should render with selected children from item definit
<Nav
bsClass="nav"
bsStyle="tabs"
className="tc-tab-bar theme-tc-responsive-tab-bar"
className="theme-tc-tab-bar tc-tab-bar theme-tc-tab-bar-responsive tc-tab-bar-responsive"
justified={false}
pullLeft={false}
pullRight={false}
stacked={false}
>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.1"
disabled={false}
Expand All @@ -30,6 +31,7 @@ exports[`TabBar component should render with selected children from item definit
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.2"
disabled={false}
Expand All @@ -40,6 +42,7 @@ exports[`TabBar component should render with selected children from item definit
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.3"
disabled={false}
Expand All @@ -50,6 +53,7 @@ exports[`TabBar component should render with selected children from item definit
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.4"
disabled={false}
Expand All @@ -60,6 +64,7 @@ exports[`TabBar component should render with selected children from item definit
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.5"
disabled={false}
Expand Down Expand Up @@ -138,14 +143,15 @@ exports[`TabBar component should render with selected children managed by user 1
<Nav
bsClass="nav"
bsStyle="tabs"
className="tc-tab-bar theme-tc-responsive-tab-bar"
className="theme-tc-tab-bar tc-tab-bar theme-tc-tab-bar-responsive tc-tab-bar-responsive"
justified={false}
pullLeft={false}
pullRight={false}
stacked={false}
>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.1"
disabled={false}
Expand All @@ -156,6 +162,7 @@ exports[`TabBar component should render with selected children managed by user 1
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.2"
disabled={false}
Expand All @@ -166,6 +173,7 @@ exports[`TabBar component should render with selected children managed by user 1
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.3"
disabled={false}
Expand All @@ -176,6 +184,7 @@ exports[`TabBar component should render with selected children managed by user 1
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.4"
disabled={false}
Expand All @@ -186,6 +195,7 @@ exports[`TabBar component should render with selected children managed by user 1
</NavItem>
<NavItem
active={false}
className="theme-tc-tab-bar-item tc-tab-bar-item"
componentClass="button"
data-feature="action.5"
disabled={false}
Expand Down
75 changes: 49 additions & 26 deletions packages/components/stories/TabBar.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

Expand Down Expand Up @@ -59,34 +59,47 @@ function generateChildId(key, kind) {
return null;
}

class InteractiveTabs extends React.Component {
constructor(props) {
super(props);
this.state = { selectedKey: '2' };
this.onSelect = this.onSelect.bind(this);
}
onSelect(event, item) {
this.setState({ selectedKey: item.key });
}
render() {
return (
<TabBar {...this.props} selectedKey={this.state.selectedKey} onSelect={this.onSelect}>
I'm the child of tab {this.state.selectedKey}
</TabBar>
);
}
const InteractiveTabs = props => {
const [selectedKey, setSelectedKey] = useState('2');

return (
<TabBar
{...props}
selectedKey={selectedKey}
onSelect={(event, item) => setSelectedKey(item.key)}
>
I'm the child of tab {selectedKey}
</TabBar>
);
};

function renderContent() {
return (
<div style={{ padding: '1rem 2rem' }}>
<p>I'm the child</p>
</div>
);
}

const stories = storiesOf('TabBar', module);
stories
.add('default', () => (
<nav>
<h3>Default TabBar</h3>
<div id="default">
<TabBar {...tabProps}>I'm the child</TabBar>
<TabBar {...tabProps}>{renderContent()}</TabBar>
</div>
<h3>Default TabBar with too small container</h3>
<div id="default-smaller" style={{ width: '300px' }}>
<TabBar {...tabProps}>I'm the child</TabBar>
<div id="default-smaller" style={{ width: '30rem', border: '1px solid' }}>
<TabBar {...tabProps}>{renderContent()}</TabBar>
</div>
<h3>
Default TabBar with too small container and <code>responsive = false</code>
</h3>
<div id="default-smaller" style={{ width: '47rem', border: '1px solid' }}>
<TabBar {...tabProps} responsive={false}>
{renderContent()}
</TabBar>
</div>
</nav>
))
Expand All @@ -95,8 +108,10 @@ stories
<h3>TabBar with custom ids</h3>
<p>
By default, you pass an id (required for accessibility) to the component and all ids are
generated.<br />
But you can customize the ids.<br />
generated.
<br />
But you can customize the ids.
<br />
The generated id will be passed to the panel as aria-describedby.
<pre>{`
function generateChildId(key, kind) {
Expand Down Expand Up @@ -125,11 +140,19 @@ function generateChildId(key, kind) {
<h3>TabBar with custom content</h3>
<div id="customContent">
<TabBar {...tabProps} generateChildId={generateChildId} />
<div id="my-custom-id-1" style={{ display: 'none' }}>I'm the existing content of tab 1</div>
<div id="my-custom-id-1" style={{ display: 'none' }}>
I'm the existing content of tab 1
</div>
<div id="my-custom-id-2">I'm the existing content of tab 2</div>
<div id="my-custom-id-3" style={{ display: 'none' }}>I'm the existing content of tab 3</div>
<div id="my-custom-id-4" style={{ display: 'none' }}>I'm the existing content of tab 4</div>
<div id="my-custom-id-5" style={{ display: 'none' }}>I'm the existing content of tab 5</div>
<div id="my-custom-id-3" style={{ display: 'none' }}>
I'm the existing content of tab 3
</div>
<div id="my-custom-id-4" style={{ display: 'none' }}>
I'm the existing content of tab 4
</div>
<div id="my-custom-id-5" style={{ display: 'none' }}>
I'm the existing content of tab 5
</div>
</div>
</nav>
))
Expand Down

0 comments on commit 15ad774

Please sign in to comment.