From cd51783ee6f59658ee6a8d3b01c29874b42a45eb Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 23 Jan 2019 14:49:39 +0100 Subject: [PATCH] add buttons and spinner --- src/components/atoms/Button.module.scss | 71 ++++++++++++++++++++++++ src/components/atoms/Button.test.js | 16 ++++++ src/components/atoms/Button.tsx | 34 ++++++++++++ src/components/atoms/Spinner.module.scss | 29 ++++++++++ src/components/atoms/Spinner.tsx | 6 ++ src/pages/Home.module.scss | 6 ++ src/pages/Home.tsx | 13 ++++- 7 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/components/atoms/Button.module.scss create mode 100644 src/components/atoms/Button.test.js create mode 100644 src/components/atoms/Button.tsx create mode 100644 src/components/atoms/Spinner.module.scss create mode 100644 src/components/atoms/Spinner.tsx diff --git a/src/components/atoms/Button.module.scss b/src/components/atoms/Button.module.scss new file mode 100644 index 0000000..1aa8a8f --- /dev/null +++ b/src/components/atoms/Button.module.scss @@ -0,0 +1,71 @@ +@import '../../styles/variables'; + +.button { + border: 0; + cursor: pointer; + outline: 0; + display: inline-block; + width: fit-content; + padding: $spacer / 4 $spacer; + font-family: $font-family-button; + font-size: $font-size-base; + font-weight: 600; + text-transform: uppercase; + border-radius: 2px; + transition: .2s ease-out; + color: $brand-white; + background: $brand-grey-light; + box-shadow: 0 9px 18px 0 rgba(0, 0, 0, .1); + min-height: 45px; + user-select: none; + + &:hover, + &:focus { + color: $brand-white; + background: $brand-grey-light; + text-decoration: none; + transform: translate3d(0, -.05rem, 0); + box-shadow: 0 12px 30px 0 rgba(0, 0, 0, .1); + } + + &:active { + background: $brand-grey-light; + transition: none; + transform: none; + box-shadow: 0 5px 18px 0 rgba(0, 0, 0, .1); + } + + &:disabled { + color: rgba($brand-white, .7); + cursor: not-allowed; + pointer-events: none; + opacity: .8; + } +} + +.buttonPrimary { + composes: button; + background: $brand-gradient; + + &:hover, + &:focus { + background: $brand-gradient; + } + + &:active { + background: $brand-gradient; + } +} + +.link { + border: 0; + outline: 0; + display: inline-block; + width: fit-content; + background: 0; + padding: 0; + color: $brand-pink; + font-size: $font-size-base; + box-shadow: none; + cursor: pointer; +} diff --git a/src/components/atoms/Button.test.js b/src/components/atoms/Button.test.js new file mode 100644 index 0000000..2be2aef --- /dev/null +++ b/src/components/atoms/Button.test.js @@ -0,0 +1,16 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import Button from './Button' + +it('Button renders without crashing', () => { + const div = document.createElement('div') + ReactDOM.render( + <> + + + + , + div + ) + ReactDOM.unmountComponentAtNode(div) +}) diff --git a/src/components/atoms/Button.tsx b/src/components/atoms/Button.tsx new file mode 100644 index 0000000..7e94297 --- /dev/null +++ b/src/components/atoms/Button.tsx @@ -0,0 +1,34 @@ +import React, { PureComponent } from 'react' +import styles from './Button.module.scss' + +interface IButtonProps { + children: string + primary?: boolean + link?: boolean + href?: string +} + +export default class Button extends PureComponent { + public render() { + let classes + const { primary, link, href, children } = this.props + + if (primary) { + classes = styles.buttonPrimary + } else if (link) { + classes = styles.link + } else { + classes = styles.button + } + + return href ? ( + + {children} + + ) : ( + + ) + } +} diff --git a/src/components/atoms/Spinner.module.scss b/src/components/atoms/Spinner.module.scss new file mode 100644 index 0000000..0467c58 --- /dev/null +++ b/src/components/atoms/Spinner.module.scss @@ -0,0 +1,29 @@ +@import '../../styles/variables'; + +.spinner { + position: relative; + text-align: center; + margin-bottom: $spacer / 2; + + &:before { + content: ''; + box-sizing: border-box; + position: absolute; + top: 0; + left: 50%; + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + border-radius: 50%; + border: 2px solid $brand-purple; + border-top-color: $brand-violet; + animation: spinner .6s linear infinite; + } +} + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} diff --git a/src/components/atoms/Spinner.tsx b/src/components/atoms/Spinner.tsx new file mode 100644 index 0000000..14e53de --- /dev/null +++ b/src/components/atoms/Spinner.tsx @@ -0,0 +1,6 @@ +import React from 'react' +import styles from './Spinner.module.scss' + +const Spinner = () =>
+ +export default Spinner diff --git a/src/pages/Home.module.scss b/src/pages/Home.module.scss index e9beb20..824db4f 100644 --- a/src/pages/Home.module.scss +++ b/src/pages/Home.module.scss @@ -7,4 +7,10 @@ display: flex; align-items: center; justify-content: center; + flex-wrap: wrap; + + > div { + text-align: center; + width: 100%; + } } diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 9284a3f..6560f21 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,9 +1,20 @@ import React, { Component } from 'react' +import Button from '../components/atoms/Button' import styles from './Home.module.scss' class Home extends Component { public render() { - return
Home
+ return ( +
+
Home
+ + + + +
+ ) } }