Skip to content
This repository has been archived by the owner on Jan 15, 2021. It is now read-only.

Commit

Permalink
[V2] Button sizes (#1633)
Browse files Browse the repository at this point in the history
* wrap our base styled button in own theme provider and add size opt

* add proper types for button size

* Stories: add B I G and smol button stories

* misc.

1. make theme toggle button smol
2. add buttonFontSize to styles sheet

* enum > type for ButtonVariations

* incorrect darkMode button logo

* better prop names (#1637)

1. kind > $type
2. size > $size
  • Loading branch information
W3stside committed Nov 20, 2020
1 parent 8cd3167 commit 6c5ff70
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 48 deletions.
35 changes: 23 additions & 12 deletions src/components/common/Button/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,15 @@ import { Story, Meta } from '@storybook/react/types-6-0'
import { ThemeToggler } from 'storybook/decorators'

import { ButtonBase, ButtonBaseProps } from './'
import { ButtonVariations } from 'styles/common/StyledButton'

export default {
title: 'Common/Button',
component: ButtonBase,
decorators: [ThemeToggler],
argTypes: {
label: { control: 'text' },
kind: {
control: 'inline-radio',
options: ButtonVariations,
},
$type: { control: 'radio' },
$size: { control: 'inline-radio' },
as: { control: null },
theme: { control: null },
forwardedAs: { control: null },
Expand All @@ -30,42 +27,56 @@ const Template: Story<ButtonBaseProps & { label?: string | React.ReactNode }> =
export const PrimaryButton = Template.bind({})
PrimaryButton.args = {
label: 'Main Button',
kind: ButtonVariations.default,
$type: 'default',
}

export const SecondaryButton = Template.bind({})
SecondaryButton.args = {
label: 'Secondary Button',
kind: ButtonVariations.secondary,
$type: 'secondary',
}

export const SuccessButton = Template.bind({})
SuccessButton.args = {
label: 'Success Button',
kind: ButtonVariations.success,
$type: 'success',
}

export const WarningButton = Template.bind({})
WarningButton.args = {
label: 'Warning Button',
kind: ButtonVariations.warning,
$type: 'warning',
}

export const DangerButton = Template.bind({})
DangerButton.args = {
label: 'Danger Button',
kind: ButtonVariations.danger,
$type: 'danger',
}

export const CancelButton = Template.bind({})
CancelButton.args = {
label: 'Cancel Button',
kind: ButtonVariations.cancel,
$type: 'cancel',
}

export const DisabledButton = Template.bind({})
DisabledButton.args = {
label: 'Disabled Button',
kind: ButtonVariations.disabled,
$type: 'disabled',
disabled: true,
}

export const BigButton = Template.bind({})
BigButton.args = {
label: 'Big Button',
$type: 'primary',
$size: 'big',
}

export const SmolButton = Template.bind({})
SmolButton.args = {
label: 'Smol Button',
$type: 'primary',
$size: 'small',
}
9 changes: 5 additions & 4 deletions src/components/common/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'

import styled from 'styled-components'
import StyledButton, { ButtonVariations } from 'styles/common/StyledButton'
import StyledButton, { ButtonVariations, ButtonSizeVariations } from 'styles/common/StyledButton'
import styles from 'styles/styles'

export interface ButtonBaseProps extends React.ButtonHTMLAttributes<Element> {
kind?: keyof typeof ButtonVariations
$type?: ButtonVariations
$size?: ButtonSizeVariations
}

export const ButtonBase = styled(StyledButton)<ButtonBaseProps>`
Expand Down Expand Up @@ -39,11 +40,11 @@ const ThemeButtonToggleWrapper = styled.div<{ $mode: boolean }>`

export const ThemeButton: React.FC<
ButtonBaseProps & {
mode: boolean
$mode: boolean
}
> = (props) => {
return (
<ThemeButtonToggleWrapper $mode={props.mode}>
<ThemeButtonToggleWrapper $mode={props.$mode}>
<ButtonBase {...props} />
</ThemeButtonToggleWrapper>
)
Expand Down
5 changes: 2 additions & 3 deletions src/storybook/decorators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { ThemeButton } from 'components/common/Button'

import COLOURS from 'styles/colours'
import { ThemeProvider } from 'styled-components'
import { ButtonVariations } from 'styles/common/StyledButton'

export const ThemeToggler = (DecoratedStory: () => JSX.Element): JSX.Element => {
const [darkMode, setDarkMode] = React.useState(true)
Expand All @@ -30,8 +29,8 @@ export const ThemeToggler = (DecoratedStory: () => JSX.Element): JSX.Element =>
<ThemeProvider theme={theme}>
<Frame style={{ background: darkMode ? COLOURS.bgDark : COLOURS.bgLight }}>{DecoratedStory()}</Frame>
{/* Cheeky use of ButtonBase here :P */}
<ThemeButton kind={ButtonVariations.theme} onClick={handleDarkMode} mode={darkMode}>
<FontAwesomeIcon icon={darkMode ? faSun : faMoon} />
<ThemeButton $size="small" $type="theme" onClick={handleDarkMode} $mode={darkMode}>
<FontAwesomeIcon icon={darkMode ? faMoon : faSun} />
</ThemeButton>
<br />
<br />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import styled, { css } from 'styled-components'
import { ThemeValue, variants } from 'styled-theming'
import React from 'react'

import styled, { css, ThemeProvider } from 'styled-components'
import { ThemeMap, ThemeValue, variants } from 'styled-theming'

import ColourSheet from '../colours'
import StyleSheet from '../styles'
Expand All @@ -23,26 +25,32 @@ const {
disabledLightOpaque,
} = ColourSheet

const { buttonBorder } = StyleSheet
const { buttonBorder, buttonFontSize } = StyleSheet

type AppThemes = 'dark' | 'light'
interface ThemeMode {
mode: AppThemes
}

// Used in stories
// Good to keep around altough not required
export enum ButtonVariations {
default = 'default',
primary = 'primary',
secondary = 'secondary',
danger = 'danger',
success = 'success',
warning = 'warning',
cancel = 'cancel',
disabled = 'disabled',
theme = 'theme',
}
export type ButtonVariations =
| 'default'
| 'primary'
| 'secondary'
| 'danger'
| 'success'
| 'warning'
| 'cancel'
| 'disabled'
| 'theme'

export type ButtonSizeVariations = 'default' | 'small' | 'big'

// Create our variated Button Theme
// 'kind' refers to a prop on button
// <ButtonBase kind="danger" />
export const ButtonTheme = variants<'kind', keyof typeof ButtonVariations>('mode', 'kind', {
export const ButtonTheme = variants<'$type', ButtonVariations>('mode', '$type', {
default: {
light: css`
color: ${white};
Expand Down Expand Up @@ -195,22 +203,41 @@ export const ButtonTheme = variants<'kind', keyof typeof ButtonVariations>('mode
},
})

/*
TODO: consider adding:
&.small {
font-size: 0.6rem;
padding: 0.3rem 0.5rem;
}
&.big {
font-size: 1.2rem;
padding: 0.65rem 1rem;
}
*/
// Created a 'size' prop on buttons, default | small | big
const ButtonSizes = variants('component', '$size', {
default: {
buttons: '',
},
small: {
buttons: css`
font-size: 0.6rem;
padding: 0.3rem 0.5rem;
`,
},
big: {
buttons: css`
font-size: 1.4rem;
padding: 0.65rem 1rem;
`,
},
})

export default styled.button`
const ColouredButtonBase = styled.button`
border: ${buttonBorder};
/* Fold in theme css above */
${ButtonTheme}
`

const ColouredAndSizedButtonBase = styled(ColouredButtonBase)`
font-size: ${buttonFontSize};
${ButtonSizes}
`
// Wrap ColouredAndSizedButtonsBase in it's own ThemeProvider which takes the toplevel app theme
// ThemeProvider and interpolate over it's props
const ThemedButtonBase: React.FC<React.ButtonHTMLAttributes<Element>> = (props) => (
<ThemeProvider theme={({ mode }: ThemeMode): ThemeMap => ({ mode, component: 'buttons' })}>
<ColouredAndSizedButtonBase {...props} />
</ThemeProvider>
)

export default ThemedButtonBase
1 change: 1 addition & 0 deletions src/styles/styles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
buttonBorder: '0.1rem solid transparent',
borderRadius: '1.6rem',
buttonFontSize: '1rem',
}

0 comments on commit 6c5ff70

Please sign in to comment.