-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(mobile): mobile menus: horizontal, select, level
- Loading branch information
Sergey Yuferev
committed
Mar 20, 2019
1 parent
6b07bb5
commit bda9f54
Showing
12 changed files
with
529 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
## Horizontal menu | ||
|
||
Горизонтальное меню с прокруткой через touch-события. Используется как первый уровень меню. | ||
|
||
```jsx | ||
class HorizontalMenuDemo extends React.Component { | ||
constructor() { | ||
super() | ||
this.state = { | ||
activeId: 'requests', | ||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
<HorizontalMenu | ||
id="kassa-menu-first" | ||
activeId={this.state.activeId} | ||
onClick={item => this.setState({activeId: item.id})} | ||
items={[ | ||
{ | ||
title: 'Услуги', | ||
id: 'merchants', | ||
}, | ||
{ | ||
title: 'Заявки', | ||
id: 'requests', | ||
}, | ||
|
||
{ | ||
title: 'Пользователи', | ||
id: 'users', | ||
}, | ||
|
||
{ | ||
title: 'Поддержка', | ||
id: 'support', | ||
}, | ||
]} | ||
/> | ||
) | ||
} | ||
} | ||
;<Spacer size="xl"> | ||
<HorizontalMenuDemo /> | ||
</Spacer> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import {BaseMenuItem, ButtonControl, styled} from '@qiwi/pijma-core' | ||
import React, {ReactNode} from 'react' | ||
|
||
import {HorizontalMenuItem} from './HorizontalMenuItem' | ||
|
||
export interface HorizontalMenuRenderItemProps<Item extends BaseMenuItem> { | ||
/** | ||
* Html item id | ||
*/ | ||
id: string | ||
item: Item | ||
active: boolean | ||
onClick: () => void | ||
} | ||
|
||
const horizontalMenuRenderItemDefault = <Item extends BaseMenuItem>({ | ||
item, | ||
active, | ||
id, | ||
onClick, | ||
}: HorizontalMenuRenderItemProps<Item>): ReactNode => ( | ||
<ButtonControl | ||
key={item.id} | ||
onClick={onClick} | ||
children={renderProps => ( | ||
<HorizontalMenuItem | ||
active={active} | ||
onClick={renderProps.onClick} | ||
id={id} | ||
children={item.title} | ||
/> | ||
)} | ||
/> | ||
) | ||
|
||
// @see https://iamsteve.me/blog/entry/using-flexbox-for-horizontal-scrolling-navigation | ||
export const HorizontalMenuContainer = styled('nav')(({theme}) => ({ | ||
display: 'flex', | ||
flexWrap: 'nowrap', | ||
overflowX: 'auto', | ||
webkitOverflowScrolling: 'auto', | ||
msOverflowStyle: '-ms-autohiding-scrollbar', | ||
'&::-webkit-scrollbar': { | ||
display: 'none', | ||
}, | ||
'&:last-child': { | ||
marginRight: 0, | ||
}, | ||
paddingLeft: '16px', | ||
paddingRight: '16px', | ||
borderBottom: '1px solid ' + theme.color.gray.light, | ||
})) | ||
|
||
export interface HorizontalMenuProps<Item extends BaseMenuItem = BaseMenuItem> { | ||
/** | ||
* Menu html id and item ids prefix | ||
*/ | ||
id: string | ||
/** | ||
* Active menu item id | ||
*/ | ||
activeId: string | ||
items: Item[] | ||
onClick: (item: Item) => void | ||
renderItem: (props: HorizontalMenuRenderItemProps<Item>) => ReactNode | ||
} | ||
|
||
// Do not use React.FC | ||
// See https://github.com/sw-yx/react-typescript-cheatsheet#typing-defaultprops | ||
export const HorizontalMenu = <Item extends BaseMenuItem = BaseMenuItem>({ | ||
items, | ||
renderItem, | ||
onClick, | ||
activeId, | ||
id, | ||
}: HorizontalMenuProps<Item>) => ( | ||
<HorizontalMenuContainer | ||
id={id} | ||
children={items.map(item => | ||
renderItem({ | ||
item, | ||
id: `${id}-${item.id}`, | ||
active: item.id === activeId, | ||
onClick: onClick.bind(null, item), | ||
}) | ||
)} | ||
/> | ||
) | ||
HorizontalMenu.defaultProps = { | ||
renderItem: horizontalMenuRenderItemDefault, | ||
} |
28 changes: 28 additions & 0 deletions
28
packages/mobile/src/horizontal-menu/HorizontalMenuItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import {styled, Typo} from '@qiwi/pijma-core' | ||
|
||
export interface HorizontalMenuItemProps { | ||
active: boolean | ||
id: string | ||
href?: string | ||
target?: string | ||
reverse?: boolean | ||
onClick?: (e: React.MouseEvent) => void | ||
} | ||
|
||
export const HorizontalMenuItem = styled(Typo.withComponent('a'), { | ||
shouldForwardProp: prop => prop !== 'active', | ||
})<HorizontalMenuItemProps>(({active, theme}) => ({ | ||
cursor: 'pointer', | ||
fontWeight: theme.font.weight.normal, | ||
flexShrink: 0, | ||
flexGrow: 0, | ||
whiteSpace: 'nowrap', | ||
paddingBottom: '4px', | ||
marginRight: '24px', | ||
borderBottomWidth: '4px', | ||
borderBottomStyle: 'solid', | ||
borderBottomColor: active ? theme.color.brand : 'transparent', | ||
'&:hover, &:active, &:focus': { | ||
borderBottomColor: theme.color.brand, | ||
}, | ||
})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './HorizontalMenu' | ||
export * from './HorizontalMenuItem' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
## Level menu | ||
|
||
Горизонтальное меню + вертикальное меню. | ||
|
||
```jsx | ||
class LevelMenuDemo extends React.Component { | ||
constructor() { | ||
super() | ||
this.state = { | ||
activeId: 't2', | ||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
<LevelMenu | ||
id="kassa-menus" | ||
activeId={this.state.activeId} | ||
onClick={item => this.setState({activeId: item.id})} | ||
items={[ | ||
{ | ||
title: 'Услуги', | ||
id: 'merchants', | ||
sub: [ | ||
{ | ||
title: 'Транзакции', | ||
id: 'transactions', | ||
sub: [ | ||
{ | ||
title: 'Что-то там 1', | ||
id: 't1', | ||
}, | ||
{ | ||
title: 'Что-то там 2', | ||
id: 't2', | ||
}, | ||
], | ||
}, | ||
{ | ||
title: 'Акты', | ||
id: 'reports', | ||
}, | ||
{ | ||
title: 'Реестры', | ||
id: 'registry', | ||
}, | ||
], | ||
}, | ||
{ | ||
title: 'Заявки', | ||
id: 'requests', | ||
sub: [ | ||
{ | ||
title: 'Список 1', | ||
id: 'list1', | ||
}, | ||
{ | ||
title: 'Список 2', | ||
id: 'list2', | ||
}, | ||
], | ||
}, | ||
|
||
{ | ||
title: 'Пользователи', | ||
id: 'users', | ||
}, | ||
|
||
{ | ||
title: 'Поддержка', | ||
id: 'support', | ||
}, | ||
]} | ||
/> | ||
) | ||
} | ||
} | ||
;<Spacer size="xl"> | ||
<LevelMenuDemo /> | ||
</Spacer> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import {BaseMenuItem, Box, MenuLevelBuilder} from '@qiwi/pijma-core' | ||
import React, {Component} from 'react' | ||
|
||
import {HorizontalMenu} from '../horizontal-menu' | ||
import {SelectMenu} from '../select-menu' | ||
|
||
export interface LevelMenuProps<Item extends BaseMenuItem> { | ||
id: string | ||
activeId: string | ||
items: Item[] | ||
onClick: (item: Item) => void | ||
} | ||
|
||
export class LevelMenu<Item extends BaseMenuItem> extends Component< | ||
LevelMenuProps<Item> | ||
> { | ||
render() { | ||
const { | ||
props: {id, onClick, activeId, items}, | ||
} = this | ||
const levels = new MenuLevelBuilder(items).levels(activeId) | ||
const level0 = levels[0] | ||
const level1 = levels[1] | ||
const level2 = levels[2] | ||
return ( | ||
<div id={id}> | ||
{level0 && ( | ||
<HorizontalMenu | ||
id={`${id}-0`} | ||
items={level0.items} | ||
onClick={onClick} | ||
activeId={level0.activeId} | ||
/> | ||
)} | ||
{level1 && ( | ||
<Box id={`${id}-1-wrapper`} mt={4}> | ||
<SelectMenu | ||
id={`${id}-1`} | ||
items={level1.items} | ||
onClick={onClick} | ||
activeId={level1.activeId} | ||
/> | ||
</Box> | ||
)} | ||
{level2 && ( | ||
<Box id={`${id}-2-wrapper`} mt={4}> | ||
<SelectMenu | ||
id={`${id}-2`} | ||
items={level2.items} | ||
onClick={onClick} | ||
activeId={level2.activeId} | ||
/> | ||
</Box> | ||
)} | ||
</div> | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './LevelMenu' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
## Select menu | ||
|
||
Вертикальное меню, похожее на dropdown. Используется как второй уровень. | ||
|
||
```jsx | ||
class SelectMenuDemo extends React.Component { | ||
constructor() { | ||
super() | ||
this.state = { | ||
activeId: 'transactions', | ||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
<SelectMenu | ||
id="kassa-menu-second" | ||
activeId={this.state.activeId} | ||
onClick={item => this.setState({activeId: item.id})} | ||
items={[ | ||
{ | ||
title: 'Транзакции и отчеты', | ||
id: 'transactions', | ||
}, | ||
{ | ||
title: 'Реестры', | ||
id: 'registry', | ||
}, | ||
|
||
{ | ||
title: 'Акты', | ||
id: 'reports', | ||
}, | ||
]} | ||
/> | ||
) | ||
} | ||
} | ||
;<Spacer size="xl"> | ||
<SelectMenuDemo /> | ||
</Spacer> | ||
``` |
Oops, something went wrong.