Skip to content

Commit

Permalink
Improve Switch component (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaszantas committed Apr 25, 2022
1 parent 1096b68 commit 027ddb6
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 83 deletions.
62 changes: 0 additions & 62 deletions applications/launchpad_v2/src/components/Inputs/Switch/index.tsx

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ import { fireEvent, render, screen } from '@testing-library/react'
import { ThemeProvider } from 'styled-components'

import Switch from '.'
import themes from '../../../styles/themes'
import themes from '../../styles/themes'

describe('Switch', () => {
it('should render without crash', () => {
const onClick = jest.fn()
const testLabel = 'Test label for the switch component'
const anotherTestLabel = 'Test label for the switch component'
const val = false
render(
<ThemeProvider theme={themes.light}>
<Switch value={val} label={testLabel} onClick={onClick} />
<Switch
value={val}
leftLabel={testLabel}
rightLabel={anotherTestLabel}
onClick={onClick}
/>
</ThemeProvider>,
)

Expand Down
107 changes: 107 additions & 0 deletions applications/launchpad_v2/src/components/Switch/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { animated, useSpring } from 'react-spring'
import { useTheme } from 'styled-components'

import Text from '../Text'

import {
LabelText,
SwitchContainer,
SwitchController,
SwitchCircle,
} from './styles'
import { SwitchProps } from './types'

/**
* Switch input controller
*
* @param {boolean} value - the input value
* @param {string | ReactNode} [leftLabel] - the text or ReactNode element on the left side of the switch.
* @param {string | ReactNode} [rightLabel] - the text or ReactNode element on the right side of the switch.
* @param {(val: boolean) => void} onClick - when the switch is clicked. Returns the new value.
* @param {boolean} [inverted] - use inverted styles
* @param {string} [testId] - the test ID (react-testing/jest)
*
* @example
* <Switch
* leftLabel={<SvgSun width='1.4em' height='1.4em' />}
* rightLabel={'The label text'}
* value={currentTheme === 'dark'}
* onClick={v => dispatch(setTheme(v ? 'dark' : 'light'))}
* />
*/
const Switch = ({
value,
leftLabel,
rightLabel,
onClick,
inverted,
testId,
}: SwitchProps) => {
const theme = useTheme()

const themeStyle = inverted ? theme.inverted : theme

const circleAnim = useSpring({
left: value ? 10 : -1,
})

const labelColorAnim = useSpring({
color: themeStyle.primary,
})

const controllerAnim = useSpring({
background: value ? themeStyle.accent : 'transparent',
})

const leftLabelEl =
leftLabel && typeof leftLabel === 'string' ? (
<Text as={animated.span} type='smallMedium' style={{ ...labelColorAnim }}>
{leftLabel}
</Text>
) : (
leftLabel
)
const rightLabelEl =
rightLabel && typeof rightLabel === 'string' ? (
<Text as={animated.span} type='smallMedium' style={{ ...labelColorAnim }}>
{rightLabel}
</Text>
) : (
rightLabel
)

return (
<SwitchContainer
onClick={() => onClick && onClick(!value)}
data-testid={testId || 'switch-input-cmp'}
>
{leftLabelEl ? (
<LabelText
style={{
marginRight: 12,
...labelColorAnim,
}}
>
{leftLabelEl}
</LabelText>
) : null}

<SwitchController style={{ ...controllerAnim }}>
<SwitchCircle style={{ ...circleAnim }} />
</SwitchController>

{rightLabelEl ? (
<LabelText
style={{
marginLeft: 12,
...labelColorAnim,
}}
>
{rightLabelEl}
</LabelText>
) : null}
</SwitchContainer>
)
}

export default Switch
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import { animated } from 'react-spring'
import styled from 'styled-components'
import colors from '../../../styles/styles/colors'
import colors from '../../styles/styles/colors'

export const SwitchContainer = styled.label`
display: flex;
align-items: center;
cursor: pointer;
`

export const SwitchController = styled(animated.div)`
height: 14px;
width: 24px;
border: 1.5px solid ${colors.dark.primary};
border-radius: 6px;
margin-right: 12px;
position: relative;
box-sizing: border-box;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.08);
cursor: pointer;
`

export const SwitchCircle = styled(animated.div)`
position: absolute;
width: 14px;
height: 14px;
top: -1.5px;
bottom: 0;
top: 0;
margin-top: -1px;
border-radius: 6px;
box-sizing: border-box;
background: #fff;
Expand All @@ -34,4 +35,7 @@ export const LabelText = styled(animated.span)`
font-weight: 500;
font-size: 14px;
line-height: 160%;
display: flex;
align-items: center;
margin: 0;
`
10 changes: 10 additions & 0 deletions applications/launchpad_v2/src/components/Switch/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ReactNode } from 'react'

export interface SwitchProps {
value: boolean
leftLabel?: string | ReactNode
rightLabel?: string | ReactNode
onClick: (val: boolean) => void
inverted?: boolean
testId?: string
}
15 changes: 14 additions & 1 deletion applications/launchpad_v2/src/components/Text/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CSSProperties } from 'styled-components'
import { ReactNode } from 'react'
import { AnimatedComponent } from 'react-spring'

/**
* @typedef TextProps
Expand All @@ -26,6 +27,18 @@ export interface TextProps {
children: ReactNode
color?: string
style?: CSSProperties
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h4' | 'h5' | 'h6' | 'h7' | 'p' | 'span'
as?:
| 'h1'
| 'h2'
| 'h3'
| 'h4'
| 'h4'
| 'h5'
| 'h6'
| 'p'
| 'span'
| AnimatedComponent<
'h1' | 'h2' | 'h3' | 'h4' | 'h4' | 'h5' | 'h6' | 'p' | 'span'
>
testId?: string
}
11 changes: 5 additions & 6 deletions applications/launchpad_v2/src/components/TitleBar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { useContext } from 'react'
import { ThemeContext } from 'styled-components'
import { useTheme } from 'styled-components'
import { useDispatch, useSelector } from 'react-redux'
import { animated, useSpring } from 'react-spring'
import { appWindow } from '@tauri-apps/api/window'

import Button from '../Button'
import Logo from '../Logo'
import Switch from '../Inputs/Switch'
import Switch from '../Switch'

import { selectExpertView } from '../../store/app/selectors'
import { setExpertView } from '../../store/app'
Expand All @@ -30,7 +29,7 @@ const TitleBar = ({ drawerViewWidth = '50%' }: TitleBarProps) => {
const dispatch = useDispatch()

const expertView = useSelector(selectExpertView)
const theme = useContext(ThemeContext)
const theme = useTheme()

const [expertViewSize] = ExpertViewUtils.convertExpertViewModeToValue(
expertView,
Expand Down Expand Up @@ -196,10 +195,10 @@ const TitleBar = ({ drawerViewWidth = '50%' }: TitleBarProps) => {
</Button>
<Switch
value={expertView !== 'hidden'}
label='Expert view'
rightLabel='Expert view'
onClick={onExpertViewClick}
testId={'titlebar-expert-view-btn'}
invertedStyle={expertView !== 'hidden'}
inverted={expertView !== 'hidden'}
/>
</animated.div>
</StyledTitleBar>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
import { useDispatch } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'
import Switch from '../../components/Switch'

import Text from '../../components/Text'
import SvgSun from '../../styles/Icons/Sun'
import SvgMoon from '../../styles/Icons/Moon'

import { setTheme } from '../../store/app'
import { selectTheme } from '../../store/app/selectors'

/**
* @TODO move user-facing text to i18n file when implementing
*/

const MiningContainer = () => {
const dispatch = useDispatch()
const currentTheme = useSelector(selectTheme)

return (
<div>
<h2>Mining</h2>
<button onClick={() => dispatch(setTheme('light'))}>
Set light theme
</button>
<button onClick={() => dispatch(setTheme('dark'))}>Set dark theme</button>
<div>
<Text>Select theme</Text>
<Switch
leftLabel={<SvgSun width='1.4em' height='1.4em' />}
rightLabel={<SvgMoon width='1.4em' height='1.4em' />}
value={currentTheme === 'dark'}
onClick={v => dispatch(setTheme(v ? 'dark' : 'light'))}
/>
</div>
</div>
)
}
Expand Down

0 comments on commit 027ddb6

Please sign in to comment.