Skip to content
This repository has been archived by the owner on Nov 1, 2018. It is now read-only.

Commit

Permalink
✨ Added swipe actions to the transition pages component
Browse files Browse the repository at this point in the history
  • Loading branch information
Gejsi committed May 3, 2018
1 parent 6dc4cd9 commit 4067e32
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 33 deletions.
6 changes: 5 additions & 1 deletion packages/Sidenav/src/overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import styled, { lightTheme } from '@slup/theming'
export const Drawer = styled.div`
z-index: 1000;
overflow-y: auto;
transition: max-width 150ms linear, transform 320ms cubic-bezier(0.4, 0.0, 0.2, 1);
transition: max-width 150ms linear,
transform 320ms ${props => props.opened
? 'cubic-bezier(0.0, 0.0, 0.2, 1)'
: 'cubic-bezier(0.4, 0.0, 0.6, 1)'
};
height: 100%;
width: calc(100% - 64px);
max-width: 320px;
Expand Down
1 change: 0 additions & 1 deletion packages/Site/src/components/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ export class Demo extends Component<{ module: string }, IState> {
.replace(']', '')
.replace(',', '')
.replace('/', '')
.replace('--', '')

/**
* Load the README and parse its contents
Expand Down
2 changes: 1 addition & 1 deletion packages/Site/src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Path = styled.path`
stroke-width: 40;
stroke-dasharray: 10000;
stroke-dashoffset: 10000;
animation: ${DASH} 5s linear forwards;
animation: ${DASH} 6s linear forwards;
`

const Line = Path.withComponent('line')
Expand Down
38 changes: 24 additions & 14 deletions packages/Tabs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ npm install --save @slup/tabs

## Usage
```js
import { Tabs, Tab } from '@slup/tabs'
import { Tabs, Tab, TransitionPages, Page } from '@slup/tabs'

export class Test extends Component {
tabs = [
Expand All @@ -27,24 +27,34 @@ export class Test extends Component {

state = { selected: 0 }

handleClick(i) {
handleSelectionChange(i) {
this.setState({ selected: i })
}

render() {
return (
<Tabs selected={this.state.selected}>
{this.tabs.map((item, i) => {
return (
<Tab
onClick={() => this.handleClick(i)}
selected={this.state.selected === i}
>
{item}
</Tab>
)
})}
</Tabs>
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
<Tabs selected={this.state.selected}>
{this.tabs.map((item, i) => {
return (
<Tab
onClick={() => this.handleSelectionChange(i)}
selected={this.state.selected === i}
>
{item}
</Tab>
)
})}
</Tabs>
<TransitionPages
onSwipe={this.handleSelectionChange.bind(this)}
selected={this.state.selected}
>
<Page>1</Page>
<Page>2</Page>
<Page>3</Page>
</TransitionPages>
</div>
)
}
}
Expand Down
11 changes: 6 additions & 5 deletions packages/Tabs/src/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class Tabs extends Component<IProps, IState> {
* from the props as a fallback
*
* We check if the value is NOT a number, becuase
* 0 is still an acceptable number but would be fals
* 0 is still an acceptable number but would be false
* in an ipothetical if statement
*/
const selected = !newProps
Expand Down Expand Up @@ -94,16 +94,16 @@ export class Tabs extends Component<IProps, IState> {
self.scroll.scrollLeft += 1

if(count == 100) clearInterval(id)
}, 0.05)
}, 0.03)
break

case 'left':
id = setInterval(() => {
count++
self.scroll.scrollLeft -= 1

if (count == 100) clearInterval(id)
}, 0.05)
if(count == 100) clearInterval(id)
}, 0.03)
break
}
}
Expand Down Expand Up @@ -155,7 +155,8 @@ export class Tabs extends Component<IProps, IState> {
children={[
...children,
<Indicator
{...props}
secondaryIndicator={secondaryIndicator}
scrollable={scrollable}
translate={translate}
style={style}
/>
Expand Down
2 changes: 1 addition & 1 deletion packages/Tabs/src/indicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import styled, { lightTheme } from '@slup/theming'

export const Indicator = styled.div`
position: absolute;
transition: width 150ms, left 150ms;
transition: width 200ms, left 200ms;
height: 2px;
bottom: ${props => props.translate && props.scrollable ? 14 : 0}px;
background: ${props => props.secondaryIndicator
Expand Down
5 changes: 3 additions & 2 deletions packages/Tabs/src/scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import styled, { lightTheme, darken } from '@slup/theming'

export const Scroll = styled.div`
position: absolute;
height: 100%;
width: 100%;
display: flex;
align-items: center;
overflow-x: ${props => props.center ? 'hidden' : 'auto'};
Expand All @@ -12,7 +14,6 @@ export const Scroll = styled.div`
transform: ${props => props.translate && props.scrollable
? 'translateY(16px)'
: null};
width: ${props => props.scrollable ? '100%' : 'auto'};
left: ${props => props.scrollable ? '80px' : 'auto'};
right: ${props => props.scrollable ? '80px' : 'auto'};
background: ${props => props.primary
Expand All @@ -22,7 +23,7 @@ export const Scroll = styled.div`
div:not(:last-child) {
width: ${props => props.fit
? `calc(100vw / ${props.childCount})`
? `calc(100% / ${props.childCount})`
: 'auto'
};
}
Expand Down
1 change: 1 addition & 0 deletions packages/Tabs/src/tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import styled, { lightTheme, rgba } from '@slup/theming'

const Item = styled.div`
-webkit-tap-highlight-color: transparent;
text-align: center;
box-sizing: border-box;
min-height: 48px;
max-height: 72px;
Expand Down
134 changes: 126 additions & 8 deletions packages/Tabs/src/transitionPages.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,142 @@
import styled, { lightTheme } from '@slup/theming'
import Inferno, { linkEvent } from 'inferno'
import Component from 'inferno-component'
import styled from '@slup/theming'

const Scroll = styled.div`
overflow-x: hidden;
height: 100%;
`

export const Pages = styled.div`
height: 100%;
width: auto;
display: flex;
transition: transform 300ms cubic-bezier(0.4, 0.0, 0.2, 1);
transform: ${props => `translateX(-${props.selected * 100}%)`}
transition: transform 200ms ${props => !props.touched
? 'cubic-bezier(0.4, 0.0, 0.2, 1)'
: 'none'
};
`

export const Page = styled.div`
flex-shrink: 0;
height: 100%;
width: 100%;
`

export const TransitionPages = props =>
<Scroll>
<Pages {...props} />
</Scroll>
interface IProps {
selected: number
onSwipe: (index: number) => void
}

interface IState {
touched: boolean
startX: number
translate: number
}

export class TransitionPages extends Component<IProps, IState> {
private container: HTMLDivElement

public state: IState = {
touched: false,
startX: 0,
translate: 0
}

public componentWillReceiveProps(nextProps: IProps) {
const stateSelection = Math.round(this.state.translate / 100)
const DID_PROP_CHANGE = this.props.selected !== nextProps.selected

if(nextProps.selected !== stateSelection && DID_PROP_CHANGE) {
this.setState({ translate: nextProps.selected * 100 })
this.emitSwipe(nextProps.selected)
}
}

/**
* Emit the new selected index to a possible onSwipe listener
*
* @param index the new index
*/
private emitSwipe(index: number) {
if(this.props.onSwipe && typeof this.props.onSwipe == 'function') {
this.props.onSwipe(index)
}
}

/**
* Saves the latest touch on the x axis
*
* @param self The local class
* @param event The data from the fired event
*/
private handleTouchStart(self, { targetTouches }) {
const { translate } = self.state
const { clientX } = targetTouches[0]
const { clientWidth } = self.container

const increment = (translate * clientWidth) / 100

self.setState({
touched: true,
startX: clientX + increment
})
}

/**
* Creates a percentage to move the container
* using the current touch and the saved one
* on the x axis
*
* @param self The local class
* @param event The data from the fired event
*/
private handleTouchMove(self, { targetTouches }) {
const { startX } = self.state
const { clientX } = targetTouches[0]
const { clientWidth } = self.container
const childrenCount = self.container.children[0].children.length

let percentage = ((startX - clientX) / clientWidth) * 100

if (percentage < 0)
percentage = 0
else if (percentage > ((childrenCount - 1) * 100))
percentage = (childrenCount - 1) * 100

self.setState({ translate: percentage })
}

/**
* Rounds the percentage
*
* @param self The local class
*/
private handleTouchEnd(self) {
self.setState({
touched: false,
translate: Math.round(self.state.translate / 100) * 100
})

self.emitSwipe(Math.round(self.state.translate / 100))
}

public render(props, { translate, touched }) {
return(
<Scroll
{...props}
innerRef={e => this.container = e}
onTouchStart={linkEvent(this, this.handleTouchStart)}
onTouchMove={linkEvent(this, this.handleTouchMove)}
onTouchEnd={linkEvent(this, this.handleTouchEnd)}
>
<Pages
selected={props.selected}
touched={touched}
style={`transform: translateX(-${translate}%)`}
>
{props.children}
</Pages>
</Scroll>
)
}
}

0 comments on commit 4067e32

Please sign in to comment.