Migrate tabs to sass

old
Javi Velasco 2015-10-11 22:27:59 +02:00
parent 06f1b866b3
commit f4f537b7f4
7 changed files with 122 additions and 83 deletions

View File

@ -0,0 +1,72 @@
@import "../variables";
$tab-text: $color-black !default;
$tab-text-color: unquote("rgb(#{$tab-text})") !default;
$tab-text-inactive-color: unquote("rgba(#{$tab-text}, 0.70)") !default;
$tab-pointer-height: .2 * $unit;
$tab-pointer-color: unquote("rgb(#{$color-primary})") !default;
$tab-navigation-border-color: $color-divider;
$tab-text-height: 1.4 * $unit;
$tab-label-height: 4.8 * $unit;
$tab-label-h-padding: 1.2 * $unit;
$tab-label-v-padding: ($tab-label-height - $tab-text-height) / 2;
$tab-label-disabled-opacity: .2;
.root {
position: relative;
}
.navigation {
box-shadow: inset 0 -1px $tab-navigation-border-color;
}
.label {
padding: $tab-label-v-padding $tab-label-h-padding;
font-size: $tab-text-height;
font-weight: $font-weight-semi-bold;
line-height: 1;
color: $tab-text-inactive-color;
text-transform: uppercase;
transition-timing-function: $animation-curve-default;
transition-duration: $animation-duration;
transition-property: box-shadow, color;
&.active {
color: $tab-text-color;
}
&.disabled {
opacity: $tab-label-disabled-opacity;
}
&:not(.disabled) {
cursor: pointer;
}
&.hidden {
display: none;
}
}
.pointer {
position: absolute;
width: 0;
height: $tab-pointer-height;
margin-top: - $tab-pointer-height;
background-color: $tab-pointer-color;
transition-timing-function: $animation-curve-default;
transition-duration: $animation-duration;
transition-property: left, width;
}
.tab {
padding: $tab-label-v-padding $tab-label-h-padding;
&:not(.active) {
display: none;
}
&.active {
display: block;
}
}

View File

@ -1,43 +0,0 @@
@import '../constants'
:local(.root)
position : relative
> nav
box-shadow : inset 0 -1px DIVIDER
> label
padding : (OFFSET / 2) OFFSET
font-size : FONT_SIZE_TINY
font-weight : FONT_WEIGHT_BOLD
text-transform : Uppercase
color : TEXT_SECONDARY
transition-property : box-shadow, color
transition-duration : ANIMATION_DURATION
transition-timing-function : ANIMATION_EASE
&.active
color : TEXT
// box-shadow : inset 0 (-(OFFSET / 10)) PRIMARY
&.disabled
opacity : 0.2
&:not(.disabled)
cursor : pointer
&.hidden
display : none
:local(.pointer)
HEIGHT = (OFFSET / 10)
position : absolute
margin-left : -(OFFSET)
margin-top : -(HEIGHT)
height : HEIGHT
width : 128px
background-color : PRIMARY
transition-property : left, width
transition-duration : ANIMATION_DURATION
transition-timing-function : ANIMATION_EASE
:local(.tab)
padding : (OFFSET / 2) OFFSET
&:not(.active)
display : none
&.active
display : block

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import style from './style'; import style from './style';
export default React.createClass({ export default React.createClass({
@ -32,9 +31,9 @@ export default React.createClass({
render () { render () {
let className = `${style.tab} ${this.props.className}`; let className = `${style.tab} ${this.props.className}`;
if (this.props.active) className += ' active'; if (this.props.active) className += ` ${style.active}`;
if (this.props.disabled) className += ' disabled'; if (this.props.disabled) className += ` ${style.disabled}`;
if (this.props.hidden) className += ' hidden'; if (this.props.hidden) className += ` ${style.hidden}`;
return ( return (
<section <section

View File

@ -1,17 +1,7 @@
import React from 'react'; import React from 'react';
import PureRenderMixin from 'react-addons-pure-render-mixin'; import PureRenderMixin from 'react-addons-pure-render-mixin';
import style from './style'; import style from './style';
function _pointerPosition (index = 0, navigation) {
const label = navigation.children[index].getBoundingClientRect();
return {
top: `${navigation.getBoundingClientRect().height}px`,
left: `${label.left}px`,
width: `${label.width}px`
};
}
export default React.createClass({ export default React.createClass({
mixins: [PureRenderMixin], mixins: [PureRenderMixin],
@ -39,7 +29,7 @@ export default React.createClass({
componentDidMount () { componentDidMount () {
this.setState({ this.setState({
pointer: _pointerPosition(this.state.index, this.refs.navigation.getDOMNode()) pointer: this._pointerPosition(this.state.index, this.refs.navigation)
}); });
}, },
@ -47,27 +37,45 @@ export default React.createClass({
const index = next_props.index || this.state.index; const index = next_props.index || this.state.index;
this.setState({ this.setState({
index: index, index: index,
pointer: _pointerPosition(index, this.refs.navigation.getDOMNode()) pointer: this._pointerPosition(index, this.refs.navigation)
}); });
}, },
_pointerPosition (index = 0, navigation) {
const startPoint = this.refs.tabs.getBoundingClientRect().left;
const label = navigation.children[index].getBoundingClientRect();
return {
top: `${navigation.getBoundingClientRect().height}px`,
left: `${label.left - startPoint}px`,
width: `${label.width}px`
};
},
onClick (index) { onClick (index) {
this.setState({ this.setState({
index: index, index: index,
pointer: _pointerPosition(index, this.refs.navigation.getDOMNode()) pointer: this._pointerPosition(index, this.refs.navigation)
}); });
if (this.props.onChange) this.props.onChange(this); if (this.props.onChange) this.props.onChange(this);
}, },
renderLabels (labels) {
return labels.map((props) => {
return <label {...props}>{ props.label }</label>;
});
},
render () { render () {
let labels = []; let labels = [];
const tabs = this.props.children.map((tab, index) => { const tabs = this.props.children.map((tab, index) => {
let active = this.state.index === index; let active = this.state.index === index;
let className = `${style.label} ${tab.props.className}`;
let className = tab.props.className; if (active) className += ` ${style.active}`;
if (active) className += ' active'; if (tab.props.disabled) className += ` ${style.disabled}`;
if (tab.props.disabled) className += ' disabled'; if (tab.props.hidden) className += ` ${style.hidden}`;
if (tab.props.hidden) className += ' hidden';
labels.push({ labels.push({
className: className, className: className,
@ -79,16 +87,15 @@ export default React.createClass({
return React.cloneElement(tab, {active: active, key: index, tabIndex: index }); return React.cloneElement(tab, {active: active, key: index, tabIndex: index });
}); });
let className = style.root;
if (this.props.className) className += ` ${this.props.className}`;
return ( return (
<div <div data-react-toolbox='tabs' ref='tabs' className={className} data-flex='vertical'>
data-react-toolbox='tabs' <nav className={style.navigation} ref='navigation' data-flex='horizontal'>
className={style.root + ' ' + this.props.className} { this.renderLabels(labels) }
data-flex='vertical'
>
<nav ref='navigation' data-flex='horizontal'>
{ labels.map((props) => { return <label {...props}>{props.label}</label>; }) }
</nav> </nav>
<span className={style.pointer} style={this.state.pointer}></span> <span className={style.pointer} style={this.state.pointer} />
{ tabs } { tabs }
</div> </div>
); );

View File

@ -33,6 +33,7 @@ $font-size-normal: $font-size !default;
$font-size-big: 1.8 * $unit !default; $font-size-big: 1.8 * $unit !default;
$font-weight-thin: 300 !default; $font-weight-thin: 300 !default;
$font-weight-normal: 400 !default; $font-weight-normal: 400 !default;
$font-weight-semi-bold: 500 !default;
$font-weight-bold: 700 !default; $font-weight-bold: 700 !default;
//-- Shadows //-- Shadows

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import { Tabs } from '../../components/tabs'; import { Tabs, Tab } from '../../components/tabs';
import { Tab } from '../../components/tabs';
export default React.createClass({ export default React.createClass({
displayName: 'TabsTest', displayName: 'TabsTest',
@ -8,13 +7,15 @@ export default React.createClass({
render () { render () {
return ( return (
<section> <section>
<h2>Tabs</h2> <h5>Tabs</h5>
<Tabs> <p>This tabs can be disabled or hidden</p>
<Tab label='Primary'><small>primary</small></Tab>
<Tab label='Secondary'><small>secondary</small></Tab> <Tabs>
<Tab label='Third' disabled><small>third</small></Tab> <Tab label='Primary'><small>Primary content</small></Tab>
<Tab label='Fourth' hidden><small>Fourth</small></Tab> <Tab label='Secondary'><small>Secondary content</small></Tab>
<Tab label='Fifth'><small>Fifth</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> </Tabs>
</section> </section>
); );

View File

@ -14,9 +14,10 @@ import Progress from './components/progress';
import RadioGroup from './components/radio_group'; import RadioGroup from './components/radio_group';
import Slider from './components/slider'; import Slider from './components/slider';
import Switch from './components/switch'; import Switch from './components/switch';
import Tabs from './components/tabs';
// import FontIcon from './components/font_icon'; // import FontIcon from './components/font_icon';
// import Form from './components/form'; // import Form from './components/form';
// import Tabs from './components/tabs';
const Test = React.createClass({ const Test = React.createClass({
displayName: 'App', displayName: 'App',
@ -39,6 +40,7 @@ const Test = React.createClass({
<RadioGroup /> <RadioGroup />
<Slider /> <Slider />
<Switch /> <Switch />
<Tabs />
</app> </app>
); );
} }