Skip to content
This repository has been archived by the owner on Nov 2, 2019. It is now read-only.

Commit

Permalink
Merge pull request #140 from jamesplease/menu
Browse files Browse the repository at this point in the history
Adding Menu Component
  • Loading branch information
jamesplease authored Jun 9, 2018
2 parents d38d838 + 3f75b47 commit df23179
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 0 deletions.
8 changes: 8 additions & 0 deletions docs/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ export default [
'Elevations create a sense of depth by applying a drop shadow to an element.',
component: 'src/components/component-doc',
},
{
name: 'Menu',
url: 'menu',
componentKey: 'menu',
description:
'Menus represent a list of items. They can be used within selects or dropdowns.',
component: 'src/components/component-doc',
},
{
name: 'Chips',
url: 'chips',
Expand Down
16 changes: 16 additions & 0 deletions docs/examples/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class MenuExample extends Component {
render() {
return (
<Menu>
<Menu.Item>Option one</Menu.Item>
<Menu.Item>Option two</Menu.Item>
<Menu.Item separator>Option three</Menu.Item>
<Menu.Item>Option four</Menu.Item>
<Menu.Item>Option five</Menu.Item>
<Menu.Item>Option six</Menu.Item>
</Menu>
);
}
}

return <MenuExample />;
36 changes: 36 additions & 0 deletions docs/readmes/menu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Usage

```jsx
import { Menu } from 'materialish';
import 'materialish/menu.css';
```

# `Menu`

## Props

| Prop Name | Default Value | Required | Description |
| --------- | ------------- | -------- | ----------------------------------------------------------------- |
| className | | No | Additional class name(s) to add to the menu |
| ...rest | | No | Other props are placed on the underlying `ul` element of the menu |

## CSS Variables

| Variable | Default Value | Description |
| ---------------------- | ------------- | ----------------------------------------- |
| --mt-baseFontSize | 1rem | The size of text within the menu |
| --mt-fontFamily | 'Roboto' | The font family to use for text |
| --mt-menuItemMinHeight | | The minimum allowed height for menu items |

# `Menu.Item`

## Props

| Prop Name | Default Value | Required | Description |
| --------- | ------------- | -------- | --------------------------------------------------------------------------- |
| className | | No | Additional class name(s) to add to the menu item |
| separator | false | No | Pass `true` to include a border-bottom to the menu item |
| selected | false | No | Whether or not this menu item is currently selected |
| ripple | true | No | Whether or not to display the "ripple" effect when the menu item is clicked |
| children | | No | The contents to render within the menu item |
| ...rest | | No | Other props are placed on the root element of the menu item |
2 changes: 2 additions & 0 deletions docs/static.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const readmes = {
radio: fs.readFileSync('./readmes/radio.md', fsOptions),
dialog: fs.readFileSync('./readmes/dialog.md', fsOptions),
elevation: fs.readFileSync('./readmes/elevation.md', fsOptions),
menu: fs.readFileSync('./readmes/menu.md', fsOptions),
'action-chip': fs.readFileSync('./readmes/action-chip.md', fsOptions),
'filter-chip': fs.readFileSync('./readmes/filter-chip.md', fsOptions),
'choice-chip': fs.readFileSync('./readmes/choice-chip.md', fsOptions),
Expand All @@ -33,6 +34,7 @@ const examples = {
radio: fs.readFileSync('./examples/radio.js', fsOptions),
dialog: fs.readFileSync('./examples/dialog.js', fsOptions),
elevation: fs.readFileSync('./examples/elevation.js', fsOptions),
menu: fs.readFileSync('./examples/menu.js', fsOptions),
'action-chip': fs.readFileSync('./examples/action-chip.js', fsOptions),
'filter-chip': fs.readFileSync('./examples/filter-chip.js', fsOptions),
'choice-chip': fs.readFileSync('./examples/choice-chip.js', fsOptions),
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Elevation from './elevation/elevation';
import ActionChip from './action-chip/action-chip';
import ChoiceChip from './choice-chip/choice-chip';
import FilterChip from './filter-chip/filter-chip';
import Menu from './menu/menu';

export {
Avatar,
Expand All @@ -24,4 +25,5 @@ export {
ActionChip,
ChoiceChip,
FilterChip,
Menu,
};
55 changes: 55 additions & 0 deletions src/menu/menu.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.mt-menu {
--mt-ripple-color: #666;
all: initial;
font-size: calc(var(--mt-baseFontSize, 1rem) * 0.875);
font-family: var(--mt-fontFamily, 'Roboto');
position: relative;
box-sizing: border-box;
border-radius: 2px;
text-align: left;
margin: 0;
padding: 0.55em 0;
display: inline-block;
background-color: #fff;
min-width: 10em;
overflow: hidden;
}

.mt-menu_item {
position: relative;
box-sizing: border-box;
display: block;
min-height: var(--mt-menuItemMinHeight);
margin: 0;
padding: 1.1em 1.7em;
z-index: 0;
cursor: pointer;
}

.mt-menu_item:after {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #eee;
z-index: -1;
opacity: 0;
will-change: opacity;
transition: opacity 0.1s ease-in-out;
}

.mt-menu_item:hover:after {
opacity: 1;
}

.mt-menu_item-separator {
border-bottom: 1px solid #e3e2e2;
}

.mt-menu_item-selected:after {
background-color: #e1e0e0;
opacity: 1;
}
68 changes: 68 additions & 0 deletions src/menu/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Ripple from '../ripple/ripple';
import Elevation from '../elevation/elevation';

export default class Menu extends Component {
render() {
const { className = '', ...props } = this.props;
return (
<Elevation depth={1}>
<ul className={`mt-menu ${className}`} {...props} />
</Elevation>
);
}
}

Menu.propTypes = {
className: PropTypes.string,
};

class Item extends Component {
render() {
const {
className = '',
separator = false,
selected = false,
ripple = true,
children,
...props
} = this.props;
return (
<div
className={`mt-menu_item ${separator ? 'mt-menu_item-separator' : ''} ${
selected ? 'mt-menu_item-selected' : ''
} ${className}`}
{...props}
onClick={this.onClick}>
{children}
{ripple && <Ripple ref={this.getRippleRef} />}
</div>
);
}

getRippleRef = component => {
this.rippleComponent = component;
};

onClick = e => {
const { onClick } = this.props;

if (this.rippleComponent) {
this.rippleComponent.onClick(e);
}

if (onClick) {
onClick();
}
};
}

Item.propTypes = {
className: PropTypes.string,
separator: PropTypes.bool,
selected: PropTypes.bool,
ripple: PropTypes.bool,
};

Menu.Item = Item;
21 changes: 21 additions & 0 deletions stories/menu.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { setOptions } from '@storybook/addon-options';
import '../src/menu/menu.css';
import { Menu } from '../src/index';

setOptions({
name: 'Materialish',
addonPanelInRight: true,
});

storiesOf('Menu', module).add('Regular', () => (
<Menu>
<Menu.Item>Option one</Menu.Item>
<Menu.Item>Option two</Menu.Item>
<Menu.Item separator>Option three</Menu.Item>
<Menu.Item>Option four</Menu.Item>
<Menu.Item>Option five</Menu.Item>
<Menu.Item>Option six</Menu.Item>
</Menu>
));

0 comments on commit df23179

Please sign in to comment.