Migrate tabs to sass
parent
06f1b866b3
commit
f4f537b7f4
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue