Browse Source

Merge pull request #71 from meriadec/master

Sidebar style update & focus handling
master
Loëck Vézien 7 years ago
committed by GitHub
parent
commit
997c043b28
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      package.json
  2. 28
      src/components/SideBar/Item.js
  3. 46
      src/components/SideBar/index.js
  4. 12
      src/components/base/Bar/index.js
  5. 12
      src/components/base/Bar/stories.js
  6. 20
      src/components/base/Box/index.js
  7. 2
      src/styles/global.js
  8. 6
      yarn.lock

1
package.json

@ -39,6 +39,7 @@
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome": "^1.1.3", "@fortawesome/fontawesome": "^1.1.3",
"@fortawesome/fontawesome-free-brands": "^5.0.6",
"@fortawesome/fontawesome-free-regular": "^5.0.6", "@fortawesome/fontawesome-free-regular": "^5.0.6",
"@fortawesome/fontawesome-free-solid": "^5.0.6", "@fortawesome/fontawesome-free-solid": "^5.0.6",
"@fortawesome/react-fontawesome": "^0.0.17", "@fortawesome/react-fontawesome": "^0.0.17",

28
src/components/SideBar/Item.js

@ -12,7 +12,7 @@ import { openModal } from 'reducers/modals'
import type { MapStateToProps } from 'react-redux' import type { MapStateToProps } from 'react-redux'
import type { Location } from 'react-router' import type { Location } from 'react-router'
import Box from 'components/base/Box' import Box, { Tabbable } from 'components/base/Box'
import Text from 'components/base/Text' import Text from 'components/base/Text'
import Icon from 'components/base/Icon' import Icon from 'components/base/Icon'
@ -27,21 +27,21 @@ const mapDispatchToProps = {
openModal, openModal,
} }
const Container = styled(Box).attrs({ const Container = styled(Tabbable).attrs({
horizontal: true, horizontal: true,
align: 'center', align: 'center',
p: 2, px: 2,
py: 1,
flow: 2, flow: 2,
})` })`
border-radius: 5px;
cursor: pointer; cursor: pointer;
color: ${p => (p.isActive ? '#1d2027' : '#b8b8b8')}; color: ${p => (p.isActive ? p.theme.colors.shark : p.theme.colors.grey)};
background: ${p => (p.isActive ? 'rgba(255, 255, 255, 0.05)' : '')}; background: ${p => (p.isActive ? p.theme.colors.argile : '')};
box-shadow: ${p => outline: none;
p.isActive ? `${p.theme.colors.blue} 4px 0 0 inset` : `${p.theme.colors.blue} 0 0 0 inset`}; &:hover,
transition: ease-in-out 100ms box-shadow; &:focus {
background: ${p => (p.isActive ? p.theme.colors.argile : p.theme.colors.cream)};
&:hover {
background: rgba(255, 255, 255, 0.05);
} }
` `
@ -68,9 +68,11 @@ function Item({ children, desc, icon, linkTo, push, location, modal, openModal }
} }
isActive={isActive} isActive={isActive}
> >
{icon && <Icon fontSize={3} color={isActive ? 'blue' : void 0} name={icon} />} {icon && <Icon fontSize={2} color={isActive ? 'blue' : void 0} name={icon} />}
<div> <div>
<Text fontSize={1}>{children}</Text> <Text fontSize={1} fontWeight="bold">
{children}
</Text>
{desc && ( {desc && (
<Box color="steel" fontSize={0}> <Box color="steel" fontSize={0}>
{desc} {desc}

46
src/components/SideBar/index.js

@ -17,16 +17,17 @@ import { getVisibleAccounts } from 'reducers/accounts'
import { formatBTC } from 'helpers/format' import { formatBTC } from 'helpers/format'
import Box from 'components/base/Box' import Box, { Tabbable } from 'components/base/Box'
import Bar from 'components/base/Bar'
import GrowScroll from 'components/base/GrowScroll' import GrowScroll from 'components/base/GrowScroll'
import Icon from 'components/base/Icon' import Icon from 'components/base/Icon'
import Text from 'components/base/Text' import Text from 'components/base/Text'
import Item from './Item' import Item from './Item'
const CapsSubtitle = styled(Box).attrs({ const CapsSubtitle = styled(Box).attrs({
px: 2, px: 3,
fontSize: 0, fontSize: 0,
color: 'shark', color: 'grey',
})` })`
cursor: default; cursor: default;
text-transform: uppercase; text-transform: uppercase;
@ -46,6 +47,21 @@ const Connected = styled(Box).attrs({
width: 10px; width: 10px;
` `
const PlusBtn = styled(Tabbable).attrs({
p: 1,
m: -1,
})`
cursor: pointer;
outline: none;
&:hover,
&:focus {
background: ${p => p.theme.colors.cream};
}
&:active {
background: ${p => p.theme.colors.argile};
}
`
type Props = { type Props = {
t: T, t: T,
accounts: Accounts, accounts: Accounts,
@ -71,7 +87,7 @@ class SideBar extends PureComponent<Props> {
<Box flow={3} pt={4} grow> <Box flow={3} pt={4} grow>
<Box flow={2}> <Box flow={2}>
<CapsSubtitle>{t('sidebar.menu')}</CapsSubtitle> <CapsSubtitle>{t('sidebar.menu')}</CapsSubtitle>
<div> <Box px={2} flow={1}>
<Item icon="chart-bar" linkTo="/"> <Item icon="chart-bar" linkTo="/">
{t('dashboard.title')} {t('dashboard.title')}
</Item> </Item>
@ -84,22 +100,24 @@ class SideBar extends PureComponent<Props> {
<Item icon="cog" linkTo="/settings"> <Item icon="cog" linkTo="/settings">
{t('settings.title')} {t('settings.title')}
</Item> </Item>
</div> </Box>
</Box> </Box>
<Bar color="cream" mx={3} size={2} />
<Box flow={2} grow> <Box flow={2} grow>
<CapsSubtitle horizontal align="center"> <CapsSubtitle horizontal align="center">
<Box grow>{t('sidebar.accounts')}</Box> <Box grow>{t('sidebar.accounts')}</Box>
<Box> <PlusBtn onClick={() => openModal(MODAL_ADD_ACCOUNT)}>
<Icon <Icon name="plus-circle" />
name="plus-circle" </PlusBtn>
style={{ cursor: 'pointer' }}
onClick={() => openModal(MODAL_ADD_ACCOUNT)}
/>
</Box>
</CapsSubtitle> </CapsSubtitle>
<GrowScroll pb={2}> <GrowScroll pb={2} px={2} flow={1}>
{Object.entries(accounts).map(([id, account]: [string, any]) => ( {Object.entries(accounts).map(([id, account]: [string, any]) => (
<Item linkTo={`/account/${id}`} desc={formatBTC(account.data.balance)} key={id}> <Item
linkTo={`/account/${id}`}
desc={formatBTC(account.data.balance)}
key={id}
icon={{ iconName: 'btc', prefix: 'fab' }}
>
{account.name} {account.name}
</Item> </Item>
))} ))}

12
src/components/base/Bar/index.js

@ -0,0 +1,12 @@
// @flow
import styled from 'styled-components'
import Box from 'components/base/Box'
const Bar = styled(Box)`
background: ${p => p.theme.colors[p.color]};
height: ${p => p.size || 1}px;
`
export default Bar

12
src/components/base/Bar/stories.js

@ -0,0 +1,12 @@
// @flow
import React from 'react'
import { number } from '@storybook/addon-knobs'
import { storiesOf } from '@storybook/react'
import Bar from 'components/base/Bar'
const stories = storiesOf('Bar', module)
stories.add('basic', () => <Bar size={number('size', 1)} color="grey" />)

20
src/components/base/Box/index.js

@ -83,20 +83,34 @@ export const GrowScroll = (props: *) => (
</Box> </Box>
) )
export class Tabbable extends PureComponent<any> { type TabbableState = {
isFocused: boolean,
}
export class Tabbable extends PureComponent<any, TabbableState> {
state = {
isFocused: false,
}
componentDidMount() { componentDidMount() {
window.addEventListener('keydown', this.handleKeydown) window.addEventListener('keydown', this.handleKeydown)
} }
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener('keydown', this.handleKeydown) window.removeEventListener('keydown', this.handleKeydown)
} }
handleFocus = () => this.setState({ isFocused: true })
handleBlur = () => this.setState({ isFocused: false })
handleKeydown = (e: SyntheticKeyboardEvent<any>) => { handleKeydown = (e: SyntheticKeyboardEvent<any>) => {
if (e.which === 13 && this.props.onClick) { if (e.which === 13 && this.state.isFocused && this.props.onClick) {
this.props.onClick(e) this.props.onClick(e)
} }
} }
render() { render() {
return <Box tabIndex={0} {...this.props} /> return <Box tabIndex={0} onFocus={this.handleFocus} onBlur={this.handleBlur} {...this.props} />
} }
} }

2
src/styles/global.js

@ -3,8 +3,10 @@
/* eslint-disable no-unused-expressions */ /* eslint-disable no-unused-expressions */
import { injectGlobal } from 'styled-components' import { injectGlobal } from 'styled-components'
import '@fortawesome/fontawesome-free-solid' import '@fortawesome/fontawesome-free-solid'
import '@fortawesome/fontawesome-free-regular' import '@fortawesome/fontawesome-free-regular'
import '@fortawesome/fontawesome-free-brands'
injectGlobal` injectGlobal`
* { * {

6
yarn.lock

@ -97,6 +97,12 @@
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.1.2.tgz#d6aa075058f0c984d6e2ebcbc0052c1f7f9bea72" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.1.2.tgz#d6aa075058f0c984d6e2ebcbc0052c1f7f9bea72"
"@fortawesome/fontawesome-free-brands@^5.0.6":
version "5.0.6"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-brands/-/fontawesome-free-brands-5.0.6.tgz#fee054ce0c4d74019020f6353ca85cfb408de719"
dependencies:
"@fortawesome/fontawesome-common-types" "^0.1.2"
"@fortawesome/fontawesome-free-regular@^5.0.6": "@fortawesome/fontawesome-free-regular@^5.0.6":
version "5.0.6" version "5.0.6"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.6.tgz#fafc624025a247c1a1bbb5080b9902a490cd79f5" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.6.tgz#fafc624025a247c1a1bbb5080b9902a490cd79f5"

Loading…
Cancel
Save