We'll use the Activatables
stateful component to control
animating the Tabs. Each Activatables
component will act as a group of Tabs. This
will also allow easily forcing at least one tab to be open.
First we'll create an AnimatedTitle
component to animate the Tab title using styled-components
.
Then we'll create a TabButton
component, which uses the active
and onClick
props provided by the Activatable
stateful component to drive the AnimatedTitle
animation, as well as toggling the active
state on click.
import styled from 'styled-components'import { Activatable, Text, Button } from '@intouchg/components'const AnimatedTitle = styled(Text)`color: ${(props) => props.active ? 'green' : 'red'};`const TabButton = ({ id, ...props }) => (<Activatable id={id}>{({ active, toggleActive }) => (<ButtoninvisibleonClick={toggleActive}><AnimatedTitleactive={active}{...props}/></Button>)}</Activatable>)export { TabButton }
Next we'll create an AnimatedContent
component to animate the Tab content using react-spring
. The useTransition
hook allows
specifying how an element will animate in and out as its state changes.
Then we'll create a TabContent
component, which uses the active
prop provided by the Activatable
stateful
component to drive the AnimatedContent
animation.
import { useTransition, animated } from 'react-spring'import { Activatable, Box } from '@intouchg/components'const AnimatedContent = ({ active, ...props }) => {const transition = useTransition(active, {from: { x: '-20%', opacity: 0 },enter: { x: '0%', opacity: 1 },leave: { x: '20%', opacity: 0 },})return transition((styles, active) => active && (<animated.divstyle={{position: 'absolute',...styles,}}><Box {...props} /></animated.div>))}const TabContent = ({ id, ...props }) => (<Activatable id={id}>{({ active }) => (<AnimatedContentactive={active}{...props}/>)}</Activatable>)export { TabContent }
Next we'll create a TabContainer
component for basic container styles. This will be the parent element to the TabContent
components.
import styled from 'styled-components'import { Stack } from '@intouchg/components'const TabContainer = styled(Stack)`position: relative;width: 100%;background-color: white;border: 2px solid grey;border-radius: 8px;`export { TabContainer }
We're finally ready to build some Tabs. Each group of Tabs should be wrapped in an Activatables
component.
Use the TabContainer
, TabButton
, and TabContent
components to build the Tabs. Remember to pass the
id
prop to the TabButton
and TabContent
components.
import { Activatables, Flex } from '@intouchg/components'import { TabContainer } from './TabContainer'import { TabButton } from './TabButton'import { TabContent } from './TabContent'const MyPage = () => (<ActivatablesallowNoneActive={false}defaultActiveIds={[ '1' ]}><Flex><TabButton id="1">Tab 1</TabButton><TabButton id="2">Tab 2</TabButton><TabButton id="3">Tab 3</TabButton></Flex><TabContainer><TabContent id="1">First tab content - Lorem ipsum dolor sit amet,consectetur adipiscing elit.</TabContent><TabContent id="2">Second tab content - Lorem ipsum dolor sit amet,consectetur adipiscing elit.</TabContent><TabContent id="3">Third tab content - Lorem ipsum dolor sit amet,consectetur adipiscing elit.</TabContent></TabContainer></Activatables>)