Browse Source

Create ToggleButton And Add Animation To ChannelPreview

Francesco Baccetti 4 years ago
parent
commit
4c1e432155

+ 2 - 1
package.json

@@ -28,8 +28,9 @@
     "@types/node": "^12.0.0",
     "@typescript-eslint/eslint-plugin": "^3.5.0",
     "@typescript-eslint/parser": "^3.2.0",
+    "babel-plugin-emotion": "^10.0.33",
     "concurrently": "^5.2.0",
-    "csstype": "^2.6.10",
+    "csstype": "^3.0.0-beta.4",
     "enzyme": "^3.11.0",
     "enzyme-adapter-react-16": "^1.15.2",
     "eslint": "^6.6.0",

+ 9 - 1
packages/app/config-overrides.js

@@ -1,6 +1,13 @@
 /* eslint-disable @typescript-eslint/no-var-requires */
 const path = require('path')
-const { override, addBabelPreset, addWebpackAlias, disableEsLint, addWebpackModuleRule } = require('customize-cra')
+const {
+  override,
+  addBabelPreset,
+  addBabelPlugin,
+  addWebpackAlias,
+  disableEsLint,
+  addWebpackModuleRule,
+} = require('customize-cra')
 const eslintConfig = require('../../.eslintrc.js')
 
 const modifiedEslintConfig = {
@@ -46,6 +53,7 @@ const customEslintConfig = (configRules) => {
 
 module.exports = {
   webpack: override(
+    addBabelPlugin('babel-plugin-emotion'),
     addBabelPreset('@emotion/babel-preset-css-prop'),
     addWebpackAlias({
       '@': path.resolve(__dirname, 'src/'),

+ 1 - 1
packages/app/src/components/Hero.tsx

@@ -39,7 +39,7 @@ const Hero: React.FC<Partial<HeroProps>> = ({ backgroundImg }) => {
           Play
         </Button>
         <Button
-          type="secondary"
+          variant="secondary"
           containerCss={css`
             width: 96px;
           `}

+ 2 - 2
packages/app/src/components/TagsGallery.tsx

@@ -1,5 +1,5 @@
 import React from 'react'
-import { Gallery, TagButton } from '@/shared/components'
+import { Gallery, ToggleButton } from '@/shared/components'
 
 const tags = [
   'finance',
@@ -28,7 +28,7 @@ type TagsProps = {
 const TagsGallery: React.FC<Partial<TagsProps>> = ({ title, action }) => (
   <Gallery title={title} action={action}>
     {tags.map((tag) => (
-      <TagButton key={tag}>{tag}</TagButton>
+      <ToggleButton key={tag}>{tag}</ToggleButton>
     ))}
   </Gallery>
 )

+ 4 - 0
packages/app/src/shared/.storybook/preview.jsx

@@ -8,6 +8,10 @@ import { GlobalStyle } from '../components'
 
 const wrapperStyle = css`
   padding: 10px;
+
+  & > * + * {
+    margin-left: 15px;
+  }
 `
 
 const stylesWrapperDecorator = (styleFn) => (

+ 137 - 110
packages/app/src/shared/components/Button/Button.style.ts

@@ -1,129 +1,156 @@
 import React from 'react'
+import { css } from '@emotion/core'
+import styled from '@emotion/styled'
+import { BlockIcon } from '@/shared/icons'
 import { typography, colors } from '../../theme'
-import { makeStyles, StyleFn } from '../../utils'
-import { disabled, dimensionsFromProps } from '../../theme/fragments'
 
 export type ButtonStyleProps = {
-  text?: string
-  type?: 'primary' | 'secondary' | 'tertiary'
+  variant?: 'primary' | 'secondary' | 'tertiary'
   full?: boolean
   size?: 'regular' | 'small' | 'smaller'
-  children?: React.ReactNode
+  hasText?: boolean
+  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
   disabled?: boolean
+  clickable?: boolean
 }
 
-const baseStyles: StyleFn = () => ({
-  borderWidth: '1px',
-  borderStyle: 'solid',
-  fontFamily: typography.fonts.headers,
-  fontWeight: typography.weights.medium,
-  display: 'inline-flex',
-  justifyContent: 'center',
-  alignItems: 'center',
-  color: colors.white,
-  '&::selected': {
-    background: 'transparent',
-  },
-})
-const colorFromType: StyleFn = (styles = {}, { type }: ButtonStyleProps) => {
-  switch (type) {
+const colorsFromProps = ({ variant }: ButtonStyleProps) => {
+  let styles
+  switch (variant) {
+    case 'tertiary': {
+      styles = css`
+        background-color: transparent;
+        border-color: transparent;
+        color: ${colors.blue[500]};
+        &:hover {
+          color: ${colors.blue[300]};
+        }
+        &:active {
+          color: ${colors.blue[700]};
+        }
+      `
+      break
+    }
+    case 'secondary': {
+      styles = css`
+        color: ${colors.white};
+        background-color: ${colors.black};
+        border-color: ${colors.blue[500]};
+        &:hover {
+          border-color: ${colors.blue[700]};
+          color: ${colors.blue[300]};
+        }
+        &:active {
+          border-color: ${colors.blue[700]};
+          color: ${colors.blue[700]};
+        }
+      `
+      break
+    }
     case 'primary':
-      return {
-        ...styles,
-        backgroundColor: colors.blue[500],
-        borderColor: colors.blue[500],
-
-        '&:hover': {
-          backgroundColor: colors.blue[700],
-          borderColor: colors.blue[700],
-          color: colors.white,
-        },
-        '&:active': {
-          backgroundColor: colors.blue[900],
-          borderColor: colors.blue[900],
-          color: colors.white,
-        },
-      }
-
-    case 'secondary':
-      return {
-        ...styles,
-        backgroundColor: colors.black,
-        borderColor: colors.blue[500],
-
-        '&:hover': {
-          borderColor: colors.blue[700],
-          color: colors.blue[300],
-        },
-
-        '&:active': {
-          borderColor: colors.blue[700],
-          color: colors.blue[700],
-        },
-      }
-
-    case 'tertiary':
-      return {
-        ...styles,
-        backgroundColor: 'transparent',
-        borderColor: 'transparent',
-        color: colors.blue[500],
-        '&:hover': {
-          color: colors.blue[300],
-        },
-        '&:active': {
-          color: colors.blue[700],
-        },
-      }
-
-    default:
-      return { ...styles }
+    default: {
+      styles = css`
+        color: ${colors.white};
+        background-color: ${colors.blue[500]};
+        border-color: ${colors.blue[500]};
+        &:hover {
+          background-color: ${colors.blue[700]};
+          border-color: ${colors.blue[700]};
+          color: ${colors.white};
+        }
+        &:active {
+          background-color: ${colors.blue[900]};
+          border-color: ${colors.blue[900]};
+          color: ${colors.white};
+        }
+      `
+      break
+    }
   }
+  return styles
 }
-const paddingFromType: StyleFn = (
-  styles,
-  { size = 'regular', children }: { size: 'regular' | 'small' | 'smaller'; children?: React.ReactNode; full: boolean }
-) => {
-  return {
-    ...styles,
-    padding:
-      size === 'regular'
-        ? children
-          ? '14px 20px'
-          : '14px'
-        : size === 'small'
-        ? children
-          ? '12px 14px'
-          : '12px'
-        : '10px',
-    fontSize:
-      size === 'regular'
-        ? typography.sizes.button.large
-        : size === 'small'
-        ? typography.sizes.button.medium
-        : typography.sizes.button.small,
+
+const sizeFromProps = ({ size = 'regular', full, hasText }: ButtonStyleProps) => {
+  let padding, fontSize
+  switch (size) {
+    case 'smaller': {
+      padding = '10px'
+      fontSize = typography.sizes.button.small
+      break
+    }
+    case 'small': {
+      padding = hasText ? `12px 14px` : '12px'
+      fontSize = typography.sizes.button.medium
+      break
+    }
+    case 'regular':
+    default: {
+      padding = hasText ? `14px 20px` : '14px'
+      fontSize = typography.sizes.button.large
+      break
+    }
   }
+  return css`
+    width: ${full ? '100%' : ''};
+    display: ${full ? 'flex' : 'inline-flex'};
+    font-size: ${fontSize};
+    padding: ${padding};
+  `
 }
 
-const iconStyles: StyleFn = (styles, { children, size }) => {
-  return {
-    ...styles,
-    marginRight: children != null ? '10px' : '0',
-    fontSize:
+const disabled = ({ disabled }: ButtonStyleProps) =>
+  disabled
+    ? css`
+        box-shadow: none;
+        fill: unset;
+        stroke: unset;
+        color: ${colors.white};
+        background-color: ${colors.gray[100]};
+        border-color: ${colors.gray[100]};
+        &:hover {
+          color: ${colors.white};
+          background-color: ${colors.gray[100]};
+          border-color: ${colors.gray[100]};
+        }
+        &:active {
+          color: ${colors.white};
+          background-color: ${colors.gray[100]};
+          border-color: ${colors.gray[100]};
+        }
+      `
+    : null
+
+export const StyledIcon = styled(BlockIcon)`
+  flex-shrink: 0;
+  & > * {
+    stroke: currentColor;
+  }
+`
+export const StyledButton = styled.button<ButtonStyleProps>`
+	border-width: 1px;
+	border-style: solid;
+	font-family: ${typography.fonts.headers};
+	font-weight: ${typography.weights.medium};
+	display: inline-flex;
+	justify-content: center;
+	align-items: center;
+	&:hover {
+		cursor: ${(props) => (!props.disabled && props.clickable ? 'pointer' : '')}
+	}
+	&::selected {
+		background: transparent;
+	}
+	${colorsFromProps}
+	${sizeFromProps}
+	${disabled}
+	& > ${StyledIcon} {
+		font-size: ${({ size }) =>
       size === 'regular'
         ? typography.sizes.icon.large
         : size === 'small'
         ? typography.sizes.icon.medium
-        : typography.sizes.icon.small,
-
-    flexShrink: 0,
-    '& > *': {
-      stroke: 'currentColor',
-    },
-  }
-}
-
-export const useCSS = (props: ButtonStyleProps) => ({
-  container: makeStyles([baseStyles, colorFromType, dimensionsFromProps, paddingFromType, disabled])(props),
-  icon: makeStyles([iconStyles])(props),
-})
+        : typography.sizes.icon.small};
+		& + * {
+			margin-left: 10px
+		}
+	};`

+ 33 - 16
packages/app/src/shared/components/Button/Button.tsx

@@ -1,31 +1,48 @@
 import React from 'react'
 import { SerializedStyles } from '@emotion/core'
-import { ButtonStyleProps, useCSS } from './Button.style'
-import { BlockIcon } from '../../icons'
+import { ButtonStyleProps, StyledButton, StyledIcon } from './Button.style'
 
-type ButtonProps = {
-  children?: React.ReactNode
-  icon?: boolean
-  disabled?: boolean
+export type ButtonProps = {
+  icon: boolean
+  disabled: boolean
   containerCss: SerializedStyles
-  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
-} & ButtonStyleProps
+  className: string
+  onClick: (e: React.MouseEvent<HTMLButtonElement>) => void
+} & Omit<ButtonStyleProps, 'clickable' | 'hasText'>
 
 const Button: React.FC<Partial<ButtonProps>> = ({
   children,
   icon,
-  type = 'primary',
+  variant = 'primary',
   disabled = false,
+  full = false,
+  size = 'regular',
   containerCss,
-  onClick = () => {},
-  ...styleProps
+  className,
+  onClick,
 }) => {
-  const styles = useCSS({ disabled, type, children, ...styleProps })
+  const clickable = !!onClick
+  const hasText = !!children
+  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
+    if (!onClick) return
+    onClick(e)
+  }
+
   return (
-    <button css={[styles.container, containerCss]} onClick={onClick} disabled={disabled}>
-      {icon && <BlockIcon css={styles.icon} />}
-      {children}
-    </button>
+    <StyledButton
+      css={containerCss}
+      className={className}
+      onClick={handleClick}
+      disabled={disabled}
+      variant={variant}
+      clickable={clickable}
+      hasText={hasText}
+      full={full}
+      size={size}
+    >
+      {icon && <StyledIcon />}
+      {children && <span>{children}</span>}
+    </StyledButton>
   )
 }
 

+ 11 - 2
packages/app/src/shared/components/ChannelPreview/ChannelPreview.tsx

@@ -10,14 +10,23 @@ type ChannelPreviewProps = {
   views: number
   avatarURL?: string
   className?: string
+  animated?: boolean
 }
 
-const ChannelPreview: React.FC<ChannelPreviewProps> = ({ name, avatarURL, views, className }) => {
+const ChannelPreview: React.FC<ChannelPreviewProps> = ({ name, avatarURL, views, className, animated = false }) => {
   const avatarNode = <StyledAvatar img={avatarURL} />
   const nameNode = <NameHeader>{name}</NameHeader>
   const metaNode = <MetaSpan>{formatNumberShort(views)} views</MetaSpan>
 
-  return <ChannelPreviewBase className={className} avatarNode={avatarNode} nameNode={nameNode} metaNode={metaNode} />
+  return (
+    <ChannelPreviewBase
+      className={className}
+      avatarNode={avatarNode}
+      nameNode={nameNode}
+      metaNode={metaNode}
+      animated={animated}
+    />
+  )
 }
 
 const NameHeader = styled.h2`

+ 19 - 2
packages/app/src/shared/components/ChannelPreview/ChannelPreviewBase.style.tsx

@@ -1,5 +1,6 @@
-import { colors } from '../../theme'
+import { css } from '@emotion/core'
 import styled from '@emotion/styled'
+import { colors, spacing } from '../../theme'
 
 const imageTopOverflow = '2rem'
 
@@ -9,12 +10,28 @@ export const OuterContainer = styled.article`
   padding-top: ${imageTopOverflow};
 `
 
-export const InnerContainer = styled.div`
+type InnerContainerProps = {
+  animated: boolean
+}
+const hoverTransition = ({ animated }: InnerContainerProps) =>
+  animated
+    ? css`
+        transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
+        &:hover {
+          transform: translate3d(-${spacing.xs}, -${spacing.xs}, 0);
+          border: 1px solid ${colors.white};
+          box-shadow: ${spacing.xs} ${spacing.xs} 0 ${colors.blue[500]};
+        }
+      `
+    : null
+
+export const InnerContainer = styled.div<InnerContainerProps>`
   background-color: ${colors.gray[800]};
   color: ${colors.gray[300]};
   display: flex;
   flex-direction: column;
   height: 100%;
+  ${hoverTransition}
 `
 
 export const Info = styled.div`

+ 9 - 2
packages/app/src/shared/components/ChannelPreview/ChannelPreviewBase.tsx

@@ -8,16 +8,23 @@ type ChannelPreviewBaseProps = {
   nameNode?: React.ReactNode
   metaNode?: React.ReactNode
   className?: string
+  animated?: boolean
 }
 
-const ChannelPreviewBase: React.FC<ChannelPreviewBaseProps> = ({ avatarNode, nameNode, metaNode, className }) => {
+const ChannelPreviewBase: React.FC<ChannelPreviewBaseProps> = ({
+  avatarNode,
+  nameNode,
+  metaNode,
+  className,
+  animated = false,
+}) => {
   const avatarPlaceholder = <Placeholder rounded />
   const namePlaceholder = <Placeholder width="140px" height="16px" />
   const metaPlaceholder = <MetaPlaceholder width="80px" height="12px" />
 
   return (
     <OuterContainer className={className}>
-      <InnerContainer>
+      <InnerContainer animated={animated}>
         <AvatarContainer>{avatarNode || avatarPlaceholder}</AvatarContainer>
         <Info>
           {nameNode || namePlaceholder}

+ 1 - 1
packages/app/src/shared/components/Gallery/Gallery.tsx

@@ -18,7 +18,7 @@ const Gallery: React.FC<GalleryProps> = ({ title, action = '', containerCss, onC
       <div css={styles.headingContainer}>
         {title && <h4>{title}</h4>}
         {action && (
-          <Button type="tertiary" onClick={onClick}>
+          <Button variant="tertiary" onClick={onClick}>
             {action}
           </Button>
         )}

+ 124 - 0
packages/app/src/shared/components/ToggleButton/ToggleButton.styles.tsx

@@ -0,0 +1,124 @@
+import styled from '@emotion/styled'
+import { css } from '@emotion/core'
+
+import Button from '../Button'
+import type { ButtonStyleProps } from '../Button/Button.style'
+import { spacing, colors } from '../../theme'
+
+export type ToggleButtonStyleProps = {
+  pressedDown: boolean
+} & ButtonStyleProps
+
+const hoverTransition = ({ pressedDown, disabled = false, variant }: ToggleButtonStyleProps) =>
+  !pressedDown && !disabled
+    ? css`
+        &:hover {
+          transform: translate3d(-${spacing.xxs}, -${spacing.xxs}, 0);
+          box-shadow: ${spacing.xxs} ${spacing.xxs} 0 ${variant === 'primary' ? colors.blue[300] : colors.blue[500]};
+          border-color: ${variant === 'primary' ? '' : colors.white};
+          color: ${colors.white};
+        }
+      `
+    : null
+
+const pressed = ({ pressedDown }: ToggleButtonStyleProps) =>
+  pressedDown
+    ? css`
+        border-color: ${colors.white};
+        color: ${colors.white};
+        background-color: ${colors.blue[500]};
+        &:hover {
+          background-color: ${colors.blue[700]};
+        }
+        &:active {
+          background-color: ${colors.blue[900]};
+        }
+      `
+    : null
+
+const colorsFromProps = ({ variant, pressedDown }: ToggleButtonStyleProps) => {
+  let styles
+  switch (variant) {
+    case 'tertiary': {
+      styles = css`
+        background-color: transparent;
+        border-color: transparent;
+        color: ${colors.blue[500]};
+        &:hover {
+          color: ${colors.blue[300]};
+        }
+        &:active {
+          color: ${colors.blue[700]};
+        }
+      `
+      break
+    }
+    case 'secondary': {
+      styles = css`
+        color: ${colors.white};
+        background-color: ${pressedDown ? colors.blue[500] : colors.black};
+        border-color: ${pressedDown ? colors.white : colors.blue[500]};
+        &:hover {
+          border-color: ${pressedDown ? colors.white : colors.blue[700]};
+          color: ${pressedDown ? colors.white : colors.blue[300]};
+          background-color: ${pressedDown ? colors.blue[700] : ''};
+        }
+        &:active {
+          border-color: ${pressedDown ? colors.white : colors.blue[700]};
+          color: ${pressedDown ? colors.white : colors.blue[700]};
+        }
+      `
+      break
+    }
+    case 'primary':
+    default: {
+      styles = css`
+        color: ${colors.white};
+        background-color: ${colors.blue[500]};
+        border-color: ${pressedDown ? colors.white : colors.blue[500]};
+        &:hover {
+          background-color: ${colors.blue[700]};
+          border-color: ${pressedDown ? colors.white : colors.blue[700]};
+          color: ${colors.white};
+        }
+        &:active {
+          background-color: ${colors.blue[900]};
+          border-color: ${pressedDown ? colors.white : colors.blue[900]};
+          color: ${colors.white};
+        }
+      `
+      break
+    }
+  }
+  return styles
+}
+
+const disabled = ({ disabled }: ToggleButtonStyleProps) =>
+  disabled
+    ? css`
+        box-shadow: none;
+        fill: unset;
+        stroke: unset;
+        color: ${colors.white};
+        background-color: ${colors.gray[100]};
+        border-color: ${colors.gray[100]};
+        &:hover {
+          color: ${colors.white};
+          background-color: ${colors.gray[100]};
+          border-color: ${colors.gray[100]};
+        }
+        &:active {
+          color: ${colors.white};
+          background-color: ${colors.gray[100]};
+          border-color: ${colors.gray[100]};
+        }
+      `
+    : null
+
+export const StyledToggleButton = styled(Button)`
+     transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
+      ${colorsFromProps}
+      ${pressed}
+      ${hoverTransition}
+      ${disabled}
+      `

+ 21 - 0
packages/app/src/shared/components/ToggleButton/ToggleButton.tsx

@@ -0,0 +1,21 @@
+import React, { useState } from 'react'
+import { StyledToggleButton, ToggleButtonStyleProps } from './ToggleButton.styles'
+
+import type { ButtonProps } from '../Button/Button'
+
+type ToggleButtonProps = ButtonProps & Omit<ToggleButtonStyleProps, 'pressedDown'>
+const ToggleButton: React.FC<Partial<ToggleButtonProps>> = ({ onClick, children, ...buttonProps }) => {
+  const [pressedDown, setPressedDown] = useState(false)
+  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
+    if (onClick) {
+      onClick(e)
+    }
+    setPressedDown(!pressedDown)
+  }
+  return (
+    <StyledToggleButton onClick={handleClick} pressedDown={pressedDown} {...buttonProps}>
+      {children}
+    </StyledToggleButton>
+  )
+}
+export default ToggleButton

+ 1 - 0
packages/app/src/shared/components/ToggleButton/index.ts

@@ -0,0 +1 @@
+export { default } from './ToggleButton'

+ 1 - 0
packages/app/src/shared/components/index.ts

@@ -25,3 +25,4 @@ export { default as ChannelAvatar } from './ChannelAvatar'
 export { default as GlobalStyle } from './GlobalStyle'
 export { default as Placeholder } from './Placeholder'
 export { default as InfiniteVideoGrid } from './InfiniteVideoGrid'
+export { default as ToggleButton } from './ToggleButton'

+ 22 - 15
packages/app/src/shared/stories/01-Button.stories.tsx

@@ -1,18 +1,21 @@
 import React from 'react'
 import { Button } from '../components'
+import { text, withKnobs } from '@storybook/addon-knobs'
+import { action } from '@storybook/addon-actions'
 
 export default {
   title: 'Button',
   component: Button,
+  decorators: [withKnobs],
 }
 
 export const Primary = () => (
   <>
-    <Button onClick={() => console.log('Button clicked!')}>Regular</Button>
-    <Button size="small" onClick={() => console.log('Button clicked!')}>
+    <Button onClick={() => action('Button Clicked')}>{text('Button Text', 'Regular')}</Button>
+    <Button size="small" onClick={() => action('Button Clicked')}>
       Small
     </Button>
-    <Button size="smaller" onClick={() => console.log('Button clicked!')}>
+    <Button size="smaller" onClick={() => action('Button Clicked')}>
       Smaller
     </Button>
   </>
@@ -20,12 +23,14 @@ export const Primary = () => (
 
 export const Secondary = () => (
   <>
-    <Button type="secondary">Regular</Button>
-    <Button type="secondary" size="small">
+    <Button variant="secondary" onClick={() => action('Button Clicked')}>
+      Regular
+    </Button>
+    <Button variant="secondary" size="small">
       Small
     </Button>
-    <Button type="secondary" size="smaller">
-      Smaller
+    <Button variant="secondary" size="smaller">
+      Has no onClik
     </Button>
   </>
 )
@@ -33,7 +38,7 @@ export const Secondary = () => (
 export const PrimaryFullSize = () => <Button full>Primary Full Size</Button>
 
 export const SecondaryFullSize = () => (
-  <Button full type="secondary">
+  <Button full variant="secondary">
     Secondary Full Size
   </Button>
 )
@@ -52,13 +57,13 @@ export const PrimaryWithIcon = () => (
 
 export const SecondaryWithIcon = () => (
   <>
-    <Button type="secondary" icon>
+    <Button variant="secondary" icon>
       Regular
     </Button>
-    <Button type="secondary" icon size="small">
+    <Button variant="secondary" icon size="small">
       Small
     </Button>
-    <Button type="secondary" icon size="smaller">
+    <Button variant="secondary" icon size="smaller">
       Smaller
     </Button>
   </>
@@ -74,15 +79,17 @@ export const PrimaryWithoutText = () => (
 
 export const SecondaryWithoutText = () => (
   <>
-    <Button type="secondary" icon />
-    <Button type="secondary" icon size="small" />
-    <Button type="secondary" icon size="smaller" />
+    <Button variant="secondary" icon />
+    <Button variant="secondary" icon size="small" />
+    <Button variant="secondary" icon size="smaller" />
   </>
 )
 
 export const Disabled = () => (
   <>
-    <Button disabled={true}>Disabled</Button>
+    <Button disabled={true} onClick={() => action('Clicked a disabled button, this should not happen.')}>
+      Disabled
+    </Button>
     <Button disabled={true} icon={true}>
       Disabled with icon
     </Button>

+ 0 - 11
packages/app/src/shared/stories/03-TagButton.stories.tsx

@@ -1,11 +0,0 @@
-import React from 'react'
-import { TagButton } from '../components'
-
-export default {
-  title: 'TagButton',
-  component: TagButton,
-}
-
-export const Default = () => <TagButton text="Finance" />
-
-export const Selected = () => <TagButton text="Finance" selected={true} />

+ 98 - 0
packages/app/src/shared/stories/03-ToggleButton.stories.tsx

@@ -0,0 +1,98 @@
+import React from 'react'
+import { ToggleButton } from '../components'
+import { text, withKnobs } from '@storybook/addon-knobs'
+import { action } from '@storybook/addon-actions'
+
+export default {
+  title: 'ToggleButton',
+  component: ToggleButton,
+  decorators: [withKnobs],
+}
+
+export const Primary = () => (
+  <>
+    <ToggleButton onClick={() => action('ToggleButton Clicked')}>{text('ToggleButton Text', 'Regular')}</ToggleButton>
+    <ToggleButton size="small" onClick={() => action('ToggleButton Clicked')}>
+      Small
+    </ToggleButton>
+    <ToggleButton size="smaller" onClick={() => action('ToggleButton Clicked')}>
+      Smaller
+    </ToggleButton>
+  </>
+)
+
+export const Secondary = () => (
+  <>
+    <ToggleButton variant="secondary" onClick={() => action('ToggleButton Clicked')}>
+      Regular
+    </ToggleButton>
+    <ToggleButton variant="secondary" size="small">
+      Small
+    </ToggleButton>
+    <ToggleButton variant="secondary" size="smaller">
+      Has no onClik
+    </ToggleButton>
+  </>
+)
+
+export const PrimaryFullSize = () => <ToggleButton full>Primary Full Size</ToggleButton>
+
+export const SecondaryFullSize = () => (
+  <ToggleButton full variant="secondary">
+    Secondary Full Size
+  </ToggleButton>
+)
+
+export const PrimaryWithIcon = () => (
+  <>
+    <ToggleButton icon>Regular</ToggleButton>
+    <ToggleButton icon size="small">
+      Small
+    </ToggleButton>
+    <ToggleButton icon size="smaller">
+      Smaller
+    </ToggleButton>
+  </>
+)
+
+export const SecondaryWithIcon = () => (
+  <>
+    <ToggleButton variant="secondary" icon>
+      Regular
+    </ToggleButton>
+    <ToggleButton variant="secondary" icon size="small">
+      Small
+    </ToggleButton>
+    <ToggleButton variant="secondary" icon size="smaller">
+      Smaller
+    </ToggleButton>
+  </>
+)
+
+export const PrimaryWithoutText = () => (
+  <>
+    <ToggleButton icon />
+    <ToggleButton icon size="small" />
+    <ToggleButton icon size="smaller" />
+  </>
+)
+
+export const SecondaryWithoutText = () => (
+  <>
+    <ToggleButton variant="secondary" icon />
+    <ToggleButton variant="secondary" icon size="small" />
+    <ToggleButton variant="secondary" icon size="smaller" />
+  </>
+)
+
+export const Disabled = () => (
+  <>
+    <ToggleButton disabled={true} onClick={() => action('Clicked a disabled ToggleButton, this should not happen.')}>
+      Disabled
+    </ToggleButton>
+    <ToggleButton disabled={true} icon={true}>
+      Disabled with icon
+    </ToggleButton>
+    <ToggleButton disabled={true} icon />
+  </>
+)

+ 2 - 1
packages/app/src/shared/stories/17-ChannelPreview.stories.tsx

@@ -1,6 +1,6 @@
 import React from 'react'
 import { ChannelPreview, ChannelPreviewBase } from '../components'
-import { number, text, withKnobs } from '@storybook/addon-knobs'
+import { boolean, number, text, withKnobs } from '@storybook/addon-knobs'
 
 export default {
   title: 'ChannelPreview',
@@ -14,6 +14,7 @@ export const Primary = () => {
       name={text('Channel name', 'Test channel')}
       views={number('Channel views', 123456)}
       avatarURL={text('Channel avatar URL', 'https://source.unsplash.com/collection/781477/320x320')}
+      animated={boolean('animated', false)}
     />
   )
 }

+ 1 - 1
packages/app/src/views/VideoView/VideoView.tsx

@@ -49,7 +49,7 @@ const VideoView: React.FC<RouteComponentProps> = () => {
         <TitleActionsContainer>
           <Title>{title}</Title>
           <ActionsContainer>
-            <Button type="secondary">Share</Button>
+            <Button variant="secondary">Share</Button>
           </ActionsContainer>
         </TitleActionsContainer>
         <Meta>

+ 7 - 2
yarn.lock

@@ -5484,7 +5484,7 @@ babel-plugin-dynamic-import-node@^2.3.3:
   dependencies:
     object.assign "^4.1.0"
 
-babel-plugin-emotion@^10.0.20, babel-plugin-emotion@^10.0.27:
+babel-plugin-emotion@^10.0.20, babel-plugin-emotion@^10.0.27, babel-plugin-emotion@^10.0.33:
   version "10.0.33"
   resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz#ce1155dcd1783bbb9286051efee53f4e2be63e03"
   integrity sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ==
@@ -7631,11 +7631,16 @@ cssstyle@^2.0.0, cssstyle@^2.2.0:
   dependencies:
     cssom "~0.3.6"
 
-csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.10, csstype@^2.6.7:
+csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.7:
   version "2.6.11"
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.11.tgz#452f4d024149ecf260a852b025e36562a253ffc5"
   integrity sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==
 
+csstype@^3.0.0-beta.4:
+  version "3.0.0-beta.4"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.0-beta.4.tgz#f03dab508a9b47c8d582e653b7d43bb8c42002d4"
+  integrity sha512-g6BwpYNogM3LqFlfC4263ZM9Ag8LqGabfMEHD6Jn0kk/RDIbOaEp1iAwLwsQ2VOVrIcli3OHALWIfRbc3T3i/Q==
+
 currently-unhandled@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"