old
Javi Velasco 2016-08-22 22:30:36 +02:00
commit 13d2590205
12 changed files with 277 additions and 86 deletions

View File

@ -110,7 +110,7 @@ $color-primary: $palette-blue-500;
$color-primary-dark: $palette-blue-700;
```
This file should be prepended to each stylesheet compilation which be achieved in multiple ways.
This file should be prepended to each stylesheet compilation which can be achieved in multiple ways.
### Using SASS Loader
@ -122,7 +122,7 @@ sassLoader: {
}
```
In this case we have are prepending the theme import to each SASS compilation so the primary color will be changed in every single stylesheet. If you are not using webpack maybe your loader still has a similar option, otherwise don't worry, there are solutions.
In this case we are prepending the theme import to each SASS compilation so the primary color will be changed in every single stylesheet. If you are not using webpack maybe your loader still has a similar option, otherwise don't worry, there are solutions.
### Using SASS imports and props

View File

@ -124,7 +124,7 @@ const factory = (Chip, Input) => {
}
this.setState({active: target});
}
this.select(target, event);
this.select(event, target);
}
if (event.which === 27) ReactDOM.findDOMNode(this).querySelector('input').blur();
@ -225,10 +225,11 @@ const factory = (Chip, Input) => {
return valueMap;
}
select = (event) => {
select = (event, target) => {
events.pauseEvent(event);
const values = this.values(this.props.value);
this.handleChange([event.target.id, ...values.keys()], event);
const newValue = target === void 0 ? event.target.id : target;
this.handleChange([newValue, ...values.keys()], event);
};
unselect (key, event) {

View File

@ -31,14 +31,14 @@
> span:not([data-react-toolbox="tooltip"]) {
display: inline-block;
line-height: $button-height;
vertical-align: middle;
vertical-align: top;
}
> svg {
display: inline-block;
width: 1em;
height: $button-height;
font-size: 120%;
vertical-align: middle;
vertical-align: top;
fill: currentColor;
}
> * {
@ -126,7 +126,7 @@
> .icon, svg {
font-size: $button-toggle-font-size;
line-height: $button-height;
vertical-align: middle;
vertical-align: top;
}
> .rippleWrapper {
border-radius: 50%;

View File

@ -11,9 +11,13 @@ const factory = (Tab, TabContent) => {
children: PropTypes.node,
className: PropTypes.string,
disableAnimatedBottomBorder: PropTypes.bool,
fixed: PropTypes.bool,
index: PropTypes.number,
inverse: PropTypes.bool,
onChange: PropTypes.func,
theme: PropTypes.shape({
fixed: PropTypes.string,
inverse: PropTypes.string,
navigation: PropTypes.string,
pointer: PropTypes.string,
tabs: PropTypes.string
@ -21,7 +25,9 @@ const factory = (Tab, TabContent) => {
};
static defaultProps = {
index: 0
index: 0,
fixed: false,
inverse: false
};
state = {
@ -30,6 +36,8 @@ const factory = (Tab, TabContent) => {
componentDidMount () {
!this.props.disableAnimatedBottomBorder && this.updatePointer(this.props.index);
window.addEventListener('resize', this.handleResize);
this.handleResize();
}
componentWillReceiveProps (nextProps) {
@ -37,6 +45,8 @@ const factory = (Tab, TabContent) => {
}
componentWillUnmount () {
window.removeEventListener('resize', this.handleResize);
clearTimeout(this.resizeTimeout);
clearTimeout(this.pointerTimeout);
}
@ -45,6 +55,21 @@ const factory = (Tab, TabContent) => {
if (this.props.onChange) this.props.onChange(idx);
};
handleResize = () => {
if (!this.props.fixed) {
return;
}
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
this.resizeTimeout = setTimeout(this.handleResizeEnd, 50);
};
handleResizeEnd = () => {
this.updatePointer(this.props.index);
};
parseChildren () {
const headers = [];
const contents = [];
@ -104,10 +129,18 @@ const factory = (Tab, TabContent) => {
}
render () {
const { className, theme } = this.props;
const { className, theme, fixed, inverse } = this.props;
const { headers, contents } = this.parseChildren();
const classes = classnames(
theme.tabs,
className,
{
[theme.fixed]: fixed,
[theme.inverse]: inverse
}
);
return (
<div ref='tabs' data-react-toolbox='tabs' className={classnames(theme.tabs, className)}>
<div ref='tabs' data-react-toolbox='tabs' className={classes}>
<nav className={theme.navigation} ref='navigation'>
{this.renderHeaders(headers)}
</nav>

View File

@ -3,10 +3,17 @@ import utils from '../../utils/testing';
import ReactTestUtils from 'react-addons-test-utils';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Tabs from '../Tabs';
import Tabs, { Tabs as RawTabs } from '../Tabs';
import Tab from '../Tab';
import TabContent from '../TabContent';
import theme from '../theme.scss';
const getRenderedClassName = (tree, TargetComponent) => {
const rendered = ReactTestUtils.findRenderedComponentWithType(tree, TargetComponent);
return ReactDOM.findDOMNode(rendered).getAttribute('class');
};
describe('Tabs', function () {
let tabContents, composition;
@ -48,4 +55,29 @@ describe('Tabs', function () {
expect(tabContents[0].props.tabIndex).toEqual(1);
});
describe('#render', function () {
it('does not use fixed by default', function () {
const tree = ReactTestUtils.renderIntoDocument(<Tabs theme={theme} />);
const className = getRenderedClassName(tree, RawTabs);
expect(className).toNotContain(theme.fixed);
});
it('uses fixed when set', function () {
const tree = ReactTestUtils.renderIntoDocument(<Tabs theme={theme} fixed />);
const className = getRenderedClassName(tree, RawTabs);
expect(className).toContain(theme.fixed);
});
it('does not use inverse by default', function () {
const tree = ReactTestUtils.renderIntoDocument(<Tabs theme={theme} />);
const className = getRenderedClassName(tree, RawTabs);
expect(className).toNotContain(theme.inverse);
});
it('uses inverse when set', function () {
const tree = ReactTestUtils.renderIntoDocument(<Tabs theme={theme} inverse />);
const className = getRenderedClassName(tree, RawTabs);
expect(className).toContain(theme.inverse);
});
});
});

View File

@ -9,3 +9,10 @@ $tab-pointer-height: .2 * $unit !default;
$tab-text: $color-black !default;
$tab-text-color: $tab-text !default;
$tab-text-inactive-color: rgba($tab-text, .7) !default;
// Inverse
$tab-inverse-bar-color: $color-primary !default;
$tab-inverse-pointer-color: $color-accent !default;
$tab-inverse-text: $color-primary-contrast !default;
$tab-inverse-text-color: $tab-inverse-text !default;
$tab-inverse-text-inactive-color: rgba($tab-inverse-text, .7) !default;

View File

@ -8,26 +8,51 @@ import {Tab, Tabs} from 'react-toolbox';
class TabsTest extends React.Component {
state = {
index: 1
index: 1,
fixedIndex: 1,
inverseIndex: 1
};
handleTabChange = (index) => {
this.setState({index});
};
handleFixedTabChange = (index) => {
this.setState({fixedIndex: index});
};
handleInverseTabChange = (index) => {
this.setState({inverseIndex: index});
};
handleActive = () => {
console.log('Special one activated');
};
render () {
return (
<Tabs index={this.state.index} onChange={this.handleTabChange}>
<Tab label='Primary'><small>Primary content</small></Tab>
<Tab label='Secondary' onActive={this.handleActive}><small>Secondary content</small></Tab>
<Tab label='Third' disabled><small>Disabled content</small></Tab>
<Tab label='Fourth' hidden><small>Fourth content hidden</small></Tab>
<Tab label='Fifth'><small>Fifth content</small></Tab>
</Tabs>
<section>
<Tabs index={this.state.index} onChange={this.handleTabChange}>
<Tab label='Primary'><small>Primary content</small></Tab>
<Tab label='Secondary' onActive={this.handleActive}><small>Secondary content</small></Tab>
<Tab label='Third' disabled><small>Disabled content</small></Tab>
<Tab label='Fourth' hidden><small>Fourth content hidden</small></Tab>
<Tab label='Fifth'><small>Fifth content</small></Tab>
</Tabs>
<h5>Fixed Tabs</h5>
<Tabs index={this.state.fixedIndex} onChange={this.handleFixedTabChange} fixed>
<Tab label='First'><small>First Content</small></Tab>
<Tab label='Second'><small>Second Content</small></Tab>
<Tab label='Third'><small>Third Content</small></Tab>
</Tabs>
<h5>Inverse Tabs</h5>
<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse>
<Tab label='First'><small>First Content</small></Tab>
<Tab label='Second'><small>Second Content</small></Tab>
<Tab label='Third'><small>Third Content</small></Tab>
<Tab label='Disabled' disabled><small>Disabled Content</small></Tab>
</Tabs>
</section>
);
}
}
@ -45,7 +70,9 @@ This component acts as the wrapper and the main controller of the content that i
|:-----|:-----|:-----|:-----|
| `className` | `String` | `''` | Additional class name to provide custom styling.|
| `disableAnimatedBottomBorder` | `Boolean` | `false` | Disable the animation below the active tab.|
| `fixed` | `Boolean` | `false` | If True, the tabs will be 'fixed tabs'.|
| `index` | `Number` | `0` | Current <Tab> |
| `inverse` | `Boolean` | `false` | If True, the tabs will have an inverse style.|
| `onChange` | `Function` | | Callback function that is fired when the tab changes.|
### Theming
@ -53,6 +80,8 @@ This component acts as the wrapper and the main controller of the content that i
| Name | Description|
|:---------|:-----------|
| `active` | Added to the active tab content and header.|
| `fixed` | Used to make the tabs 'fixed tabs'.|
| `inverse` | Used to invert the colors.|
| `navigation` | Used for the navigation element.|
| `pointer` | Used for the moving underline element.|
| `tabs` |Used as a root classname for the component.|

View File

@ -61,3 +61,27 @@
display: block;
}
}
.fixed {
.label {
flex: 1;
text-align: center;
}
}
.inverse {
.navigation {
background-color: $tab-inverse-bar-color;
}
.label {
color: $tab-inverse-text-inactive-color;
&.active {
color: $tab-inverse-text-color;
}
}
.pointer {
background-color: $tab-inverse-pointer-color;
}
}

View File

@ -1,21 +1,50 @@
class TabsExample extends React.Component {
state = {
index: 1
index: 1,
fixedIndex: 1,
inverseIndex: 1
};
handleTabChange = (index) => {
this.setState({index});
};
handleFixedTabChange = (index) => {
this.setState({fixedIndex: index});
};
handleInverseTabChange = (index) => {
this.setState({inverseIndex: index});
};
handleActive = () => {
console.log('Special one activated');
};
render () {
return (
<Tabs index={this.state.index} onChange={this.handleTabChange}>
<Tab label='Primary'><small>Primary content</small></Tab>
<Tab label='Secondary'><small>Secondary content</small></Tab>
<Tab label='Third' disabled><small>Disabled content</small></Tab>
<Tab label='Fourth' hidden><small>Fourth content hidden</small></Tab>
<Tab label='Fifth'><small>Fifth content</small></Tab>
</Tabs>
<section>
<Tabs index={this.state.index} onChange={this.handleTabChange}>
<Tab label='Primary'><small>Primary content</small></Tab>
<Tab label='Secondary' onActive={this.handleActive}><small>Secondary content</small></Tab>
<Tab label='Third' disabled><small>Disabled content</small></Tab>
<Tab label='Fourth' hidden><small>Fourth content hidden</small></Tab>
<Tab label='Fifth'><small>Fifth content</small></Tab>
</Tabs>
<h5>Fixed Tabs</h5>
<Tabs index={this.state.fixedIndex} onChange={this.handleFixedTabChange} fixed>
<Tab label='First'><small>First Content</small></Tab>
<Tab label='Second'><small>Second Content</small></Tab>
<Tab label='Third'><small>Third Content</small></Tab>
</Tabs>
<h5>Inverse Tabs</h5>
<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse>
<Tab label='First'><small>First Content</small></Tab>
<Tab label='Second'><small>Second Content</small></Tab>
<Tab label='Third'><small>Third Content</small></Tab>
<Tab label='Disabled' disabled><small>Disabled Content</small></Tab>
</Tabs>
</section>
);
}
}

View File

@ -36,63 +36,63 @@
"toolkit"
],
"dependencies": {
"classnames": "^2.2.5",
"core-js": "^2.4.0",
"react-css-themr": "^1.2.0"
"classnames": "~2.2.5",
"core-js": "~2.4.0",
"react-css-themr": "~1.2.0"
},
"devDependencies": {
"autoprefixer": "^6.4.0",
"babel-cli": "^6.8.0",
"babel-core": "^6.13.2",
"babel-eslint": "^6.0.4",
"babel-loader": "^6.2.4",
"babel-plugin-react-transform": "^2.0.2",
"babel-polyfill": "^6.13.0",
"babel-preset-es2015": "^6.13.2",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"bluebird": "^3.3.5",
"cpx": "^1.3.1",
"cross-env": "^2.0.0",
"css-loader": "^0.23.1",
"eslint": "^3.2.2",
"eslint-plugin-babel": "^3.2.0",
"eslint-plugin-react": "^6.0.0",
"expect": "^1.20.1",
"express": "^4.13.4",
"extract-text-webpack-plugin": "^1.0.1",
"glob": "^7.0.3",
"karma": "^1.1.2",
"karma-chrome-launcher": "^1.0.1",
"karma-cli": "^1.0.0",
"karma-mocha": "^1.0.1",
"karma-phantomjs-launcher": "^1.0.0",
"karma-webpack": "^1.7.0",
"mocha": "^3.0.1",
"node-sass": "^3.7.0",
"normalize.css": "^4.1.1",
"phantomjs": "^2.1.7",
"autoprefixer": "~6.4.0",
"babel-cli": "~6.8.0",
"babel-core": "~6.13.2",
"babel-eslint": "~6.0.4",
"babel-loader": "~6.2.4",
"babel-plugin-react-transform": "~2.0.2",
"babel-polyfill": "~6.13.0",
"babel-preset-es2015": "~6.13.2",
"babel-preset-react": "~6.5.0",
"babel-preset-stage-0": "~6.5.0",
"bluebird": "~3.3.5",
"cpx": "~1.3.1",
"cross-env": "~2.0.0",
"css-loader": "~0.23.1",
"eslint": "~3.2.2",
"eslint-plugin-babel": "~3.2.0",
"eslint-plugin-react": "~6.0.0",
"expect": "~1.20.1",
"express": "~4.13.4",
"extract-text-webpack-plugin": "~1.0.1",
"glob": "~7.0.3",
"karma": "~1.1.2",
"karma-chrome-launcher": "~1.0.1",
"karma-cli": "~1.0.0",
"karma-mocha": "~1.0.1",
"karma-phantomjs-launcher": "~1.0.0",
"karma-webpack": "~1.7.0",
"mocha": "~3.0.1",
"node-sass": "~3.7.0",
"normalize.css": "~4.2.0",
"phantomjs": "~2.1.7",
"phantomjs-polyfill": "0.0.2",
"phantomjs-prebuilt": "^2.1.7",
"postcss-loader": "^0.9.1",
"react": "^15.2.1",
"react-addons-css-transition-group": "^15.2.1",
"react-addons-test-utils": "^15.2.1",
"react-addons-update": "^15.2.1",
"react-docgen": "^2.8.2",
"react-dom": "^15.2.1",
"react-transform-catch-errors": "^1.0.2",
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.2.4",
"rimraf": "^2.5.2",
"phantomjs-prebuilt": "~2.1.7",
"postcss-loader": "~0.9.1",
"react": "~15.3.0",
"react-addons-update": "~15.3.0",
"react-addons-test-utils": "~15.3.0",
"react-addons-css-transition-group": "~15.3.0",
"react-docgen": "~2.8.2",
"react-dom": "~15.3.0",
"react-transform-catch-errors": "~1.0.2",
"react-transform-hmr": "~1.0.4",
"redbox-react": "~1.2.4",
"rimraf": "~2.5.2",
"sass-lint": "1.8.2",
"sass-loader": "^4.0.0",
"sass-loader": "~4.0.0",
"sinon": "git://github.com/sinonjs/sinon.git#b672042043517b9f84e14ed0fb8265126168778a",
"style-loader": "^0.13.1",
"style-loader": "~0.13.1",
"toolbox-loader": "0.0.3",
"webpack": "^1.13.0",
"webpack-dev-middleware": "^1.6.1",
"webpack-hot-middleware": "^2.10.0"
"webpack": "~1.13.0",
"webpack-dev-middleware": "~1.6.1",
"webpack-hot-middleware": "~2.10.0"
},
"scripts": {
"babel": "babel ./components --out-dir ./lib",
@ -113,11 +113,11 @@
},
"license": "MIT",
"peerDependencies": {
"classnames": "^2.2.0",
"normalize.css": "^4.0.0",
"react": "^0.14 || ^15.2.0",
"react-addons-css-transition-group": "^0.14.0 || ^15.2.0",
"react-addons-update": "^0.14 || ^15.2.0",
"react-dom": "^0.14.0 || ^15.2.0"
"classnames": "~2.2.0",
"normalize.css": "~4.2.0",
"react": "~0.14 || ~15.3.0",
"react-addons-css-transition-group": "~0.14.0 || ~15.3.0",
"react-addons-update": "~0.14 || ~15.3.0",
"react-dom": "~0.14.0 || ~15.3.0"
}
}

View File

@ -24,6 +24,17 @@ const ButtonTest = () => (
<IconButton primary><GithubIcon/></IconButton>
<Button icon='add' label='Add this' flat primary />
<Button icon='add' label='Add this' flat disabled />
<h5>Icon Button Alignment</h5>
<p>
Icon Buttons should align in the vertical center, to see this we need to
put them next to text or highlight thier background color.
</p>
<IconButton icon='menu' style={{'background-color': 'red'}} inverse />
<span style={{'vertical-align': 'middle'}}>Menu</span>
<IconButton icon='menu' />
<span style={{'vertical-align': 'middle'}}>Menu</span>
<IconButton><GithubIcon /></IconButton>
<span style={{'vertical-align': 'middle'}}>Github</span>
</section>
);

View File

@ -3,13 +3,23 @@ import { Tabs, Tab } from '../../components/tabs';
class TabsTest extends React.Component {
state = {
index: 1
index: 1,
fixedIndex: 1,
inverseIndex: 1
};
handleTabChange = (index) => {
this.setState({index});
};
handleFixedTabChange = (index) => {
this.setState({fixedIndex: index});
};
handleInverseTabChange = (index) => {
this.setState({inverseIndex: index});
};
handleActive = () => {
console.log('Special one activated');
};
@ -26,6 +36,21 @@ class TabsTest extends React.Component {
<Tab label='Fourth' hidden><small>Fourth content hidden</small></Tab>
<Tab label='Fifth'><small>Fifth content</small></Tab>
</Tabs>
<h5>Fixed Tabs</h5>
<p>These tabs fill the given space.</p>
<Tabs index={this.state.fixedIndex} onChange={this.handleFixedTabChange} fixed>
<Tab label='First'><small>First Content</small></Tab>
<Tab label='Second'><small>Second Content</small></Tab>
<Tab label='Third'><small>Third Content</small></Tab>
</Tabs>
<h5>Inverse Tabs</h5>
<p>These tabs have an inverted theme.</p>
<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse>
<Tab label='First'><small>First Content</small></Tab>
<Tab label='Second'><small>Second Content</small></Tab>
<Tab label='Third'><small>Third Content</small></Tab>
<Tab label='Disabled' disabled><small>Disabled Content</small></Tab>
</Tabs>
</section>
);
}