Skip to content

Instantly share code, notes, and snippets.

@PavelLaptev
Last active September 13, 2018 08:52
Show Gist options
  • Save PavelLaptev/c9486f516f1da4dc1d3aab285a50b5f8 to your computer and use it in GitHub Desktop.
Save PavelLaptev/c9486f516f1da4dc1d3aab285a50b5f8 to your computer and use it in GitHub Desktop.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { PropertyControls, ControlType } from "framer";
import { fontStyles } from "../data/style/_fontStyles";
import styled from "styled-components";
// Define type of property
interface Props {
amount: number;
lineWidth: number;
lineLeft: number;
}
interface States {
lineProps: any;
}
// Define Styled components
const TabGroup = styled<Props, any>("div")`
display: flex;
width: 100%;
height: 100%;
justify-content: space-between;
padding: 0 16px;
background: white;
`;
const TabItem = styled<Props, any>("div")`
display: flex;
flex: 1 1 auto;
justify-content: center;
height: 100%;
`;
const TabText = styled<Props, any>("span")`
${fontStyles["Small Bold"]};
margin-top: 3px;
text-align: center;
letter-spacing: 0.11em;
text-transform: uppercase;
pointer-events: none;
`;
const TabLine = styled<Props, any>("div")`
position: absolute;
bottom: 0;
left: ${props => props.lineLeft}px;
width: ${props => props.lineWidth}px;
height: 4px;
background: black;
transition: all 0.25s cubic-bezier(0.595, 0, 0.435, 1);
`;
export class Tabs extends React.Component<Partial<Props>, States> {
// Set default properties
static defaultProps = {
width: 375,
height: 32,
amount: 3,
item1: "Women",
item2: "Men",
item3: "Kids",
item4: "Item #4",
item5: "Item #5"
};
// Items shown in property panel
static propertyControls: PropertyControls = {
amount: { type: ControlType.Number, min: 2, max: 5, title: "Amount" },
item1: { type: ControlType.String, title: "Item #1" },
item2: { type: ControlType.String, title: "Item #2" },
item3: {
type: ControlType.String,
title: "Item #3",
hidden(props) {
if (props.amount >= 3) {
return false;
} else {
return true;
}
}
},
item4: {
type: ControlType.String,
title: "Item #4",
hidden(props) {
if (props.amount >= 4) {
return false;
} else {
return true;
}
}
},
item5: {
type: ControlType.String,
title: "Item #5",
hidden(props) {
if (props.amount >= 5) {
return false;
} else {
return true;
}
}
}
};
state = {
lineProps: {
width: 50,
left: 54
}
};
private tabGroupRef = React.createRef<any>();
private itemsArray = [];
private currentItem = 1;
getLineProps = i => {
let width = ReactDOM.findDOMNode(this.tabGroupRef.current).children[i]
.children[0].clientWidth;
let left = ReactDOM.findDOMNode(this.tabGroupRef.current).children[i]
.children[0].offsetLeft;
return {
width: width,
left: left
};
};
updateCurrentTab = e => {
this.setState({
lineProps: {
width: e.target.children[0].clientWidth,
left: e.target.children[0].offsetLeft
}
});
};
componentWillReceiveProps(props: Props) {
this.itemsArray.length = 0;
for (let i = 0; i < props.amount; i++) {
this.itemsArray.push(props[`item${i + 1}`]);
}
}
componentWillMount() {
for (let i = 0; i < this.props.amount; i++) {
this.itemsArray.push(this.props[`item${i + 1}`]);
}
}
componentDidUpdate(prevProps, prevState) {
if (prevState.lineProps !== this.state.lineProps) {
return false;
} else {
this.setState({
lineProps: this.getLineProps(this.currentItem)
});
}
}
render() {
const itemsAmount = this.itemsArray.map((item, index) => (
<TabItem
key={`item-${index}`}
onClick={e => {
this.updateCurrentTab(e);
}}
>
<TabText>{this.itemsArray[index]}</TabText>
</TabItem>
));
return (
<TabGroup ref={this.tabGroupRef}>
<TabLine
lineWidth={this.state.lineProps.width}
lineLeft={this.state.lineProps.left}
/>
{itemsAmount}
</TabGroup>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment