|
1 |
| -# quip-react-menu |
| 1 | +# quip-react-toolbar |
| 2 | + |
| 3 | +`quip-react-toolbar` is a rendereless React component for quickly and easily using the [document menu and toolbar](https://salesforce.quip.com/dev/liveapps/documentation#menus-configuring-menu-commands) in [Quip Live Apps](https://salesforce.quip.com/dev/liveapps/documentation). This component is designed to be declarative and reactive, taking advantage of React's built-in state management and update technology. |
| 4 | + |
| 5 | +This component allows developers to easily create and update the toolbar without needing to use [`quip.apps.updateToolbar`](https://salesforce.quip.com/dev/liveapps/documentation#menus-updating-the-toolbar). Instead, React will automatically update the toolbar if the component state -- and thus, the toolbar state -- changes. |
2 | 6 |
|
3 | 7 | ## Installation
|
4 | 8 | ```
|
5 |
| -npm install https://github.com/herrevilkitten/quip-react-menu.git |
| 9 | +npm install https://github.com/herrevilkitten/quip-react-toolbar.git |
6 | 10 | ```
|
7 | 11 |
|
8 | 12 | ## Usage
|
9 | 13 | ```
|
10 |
| -import { MenuBar, Menu, MainMenu, MenuSeparator } from 'quip-react-menu'; |
11 |
| -``` |
| 14 | +import { MenuBar, Menu, MainMenu, MenuSeparator } from 'quip-react-toolbar'; |
| 15 | +
|
| 16 | +export default class App extends React.Component { |
| 17 | + constructor(props) { |
| 18 | + super(props); |
| 19 | + this.state = { |
| 20 | + label: 'Hello', |
| 21 | + highlighted: false, |
| 22 | + disabled: false, |
| 23 | + }; |
| 24 | +
|
| 25 | + this.handleChange = this.handleChange.bind(this); |
| 26 | + } |
| 27 | +
|
| 28 | + handleChange(event) { |
| 29 | + const target = event.target; |
| 30 | + const value = target.type === 'checkbox' ? target.checked : target.value; |
| 31 | + const name = target.name; |
| 32 | +
|
| 33 | + this.setState({ |
| 34 | + [name]: value |
| 35 | + }); |
| 36 | + } |
| 37 | +
|
| 38 | + menuHandler() { |
| 39 | + console.log('I am a menu that has been handled!'); |
| 40 | + } |
| 41 | +
|
| 42 | + render() { |
| 43 | + return ( |
| 44 | + <div> |
| 45 | + <div> |
| 46 | + <input |
| 47 | + name="highlighted" |
| 48 | + type="checkbox" |
| 49 | + checked={this.state.highlighted} |
| 50 | + onChange={this.handleChange} /> |
| 51 | + Highlighted |
| 52 | + </div> |
| 53 | + <div> |
| 54 | + <input |
| 55 | + name="disabled" |
| 56 | + type="checkbox" |
| 57 | + checked={this.state.disabled} |
| 58 | + onChange={this.handleChange} /> |
| 59 | + Disabled |
| 60 | + </div> |
| 61 | + <div> |
| 62 | + <input name="label" type="text" value={this.state.label} onChange={this.handleChange} /> |
| 63 | + </div> |
| 64 | + <MenuBar> |
| 65 | + <MainMenu> |
| 66 | + <Menu highlighted={this.state.highlighted} label={this.state.label}> |
| 67 | + <Menu id="submenu" label="Submenu" handler={this.menuHandler}></Menu> |
| 68 | + </Menu> |
| 69 | + <MenuSeparator></MenuSeparator> |
| 70 | + </MainMenu> |
| 71 | + <MainMenu> |
| 72 | + <Menu label="Submenu" handler={this.menuHandler} sublabel="hello"></Menu> |
| 73 | + </MainMenu> |
| 74 | + <Menu highlighted={!this.state.highlighted} label={this.state.label + " !Highlighted"} handler={this.menuHandler}></Menu> |
| 75 | + <Menu disabled={this.state.disabled} label={this.state.label + " Disabled"} handler={this.menuHandler}></Menu> |
| 76 | + </MenuBar> |
| 77 | + </div> |
| 78 | + ); |
| 79 | + } |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +### Configuring the Toolbar and Menu |
| 84 | + |
| 85 | +The root of the menu system is the `MenuBar` component. All of the menu entries must be placed within it. The `MenuBar` can accept all of the other components in order to build the menu system. The menu is configured in the order that the components are defined in the JSX. |
| 86 | + |
| 87 | +Any components that are inside of a `MainMenu` component will be placed into the live app's document menu. Separate `MainMenu` entries will be merged into a single menu tree. Anything that is a direct descendent of |
| 88 | + |
| 89 | +#### Headers and Separators |
| 90 | + |
| 91 | +In addition to defining headers with a `Menu`, HTML elements can be used. This is done to keep the component tree a little cleaner. Any "simple" HTML element (such as `<b>` or `<em>`) and plain text will be turned into a header or separator. For example: |
| 92 | + |
| 93 | +``` |
| 94 | +<MenuBar> |
| 95 | + <b>This is a header</b> |
| 96 | + <b>This is another header</b> |
| 97 | +</MenuBar> |
| 98 | +``` |
| 99 | + |
| 100 | +will create two headers inside of the live app's toolbar. If the header's label is `---` or `----`, it will create a separator instead. |
| 101 | + |
| 102 | +``` |
| 103 | +<MenuBar> |
| 104 | + <b>This is a header</b> |
| 105 | + ---- |
| 106 | + <b>This is another header</b> |
| 107 | +</MenuBar> |
| 108 | +``` |
| 109 | + |
| 110 | +### `MenuBar` |
| 111 | + |
| 112 | +This is the root component of the menu system. It handles updating the toolbar and main menu based on the state of its child components. |
| 113 | + |
| 114 | +### `MainMenu` |
| 115 | + |
| 116 | +This component can only be used as a director child of `MenuBar`. Children of `MainMenu` will be placed into the live app's document menu as `subCommands` of `quip.apps.DocumentMenuCommands.MENU_MAIN`. |
| 117 | + |
| 118 | +### `Menu` |
| 119 | +This component represents a [`quip.apps.MenuCommand`](https://salesforce.quip.com/dev/liveapps/documentation#menus-configuring-menu-commands) and shares most of the properties with it. There are some important differences, however. |
| 120 | + |
| 121 | +#### Properties |
| 122 | +`id: string [optional]` -- a unique identifier for the menu. If one is not provided, it will be automatically generated by the component using a simple algorithm. |
| 123 | + |
| 124 | +`label: string [optional]` -- No change from the Quip documentation. |
| 125 | + |
| 126 | +`sublabel: string [optional]` -- No change from the Quip documentation. |
| 127 | + |
| 128 | +`handler: function(string, Object, ?) [optional]` -- No change from the Quip documentation. |
| 129 | + |
| 130 | +`isHeader: boolean [optional, default=False]` -- indicates whether or not this menu should be displayed as a header. If a `handler` property is not set and the component has no child menus, this property will be automatically set. |
| 131 | + |
| 132 | +`actionId: string [optional]` -- No change from the Quip documentation. |
| 133 | + |
| 134 | +`actionParams: Object [optional]` -- No change from the Quip documentation. |
| 135 | + |
| 136 | +`actionStarted: function() [optional]` -- No change from the Quip documentation. |
| 137 | + |
| 138 | +`highlighted: boolean [optional]` -- indicates whether this menu entry should be "highlighted" by adding the menu to [`highlightedCommandIds`](https://salesforce.quip.com/dev/liveapps/documentation#menus-updating-the-toolbar). |
| 139 | + |
| 140 | +`disabled: boolean [optional]` -- indicates whether this menu entry is disabled by adding the menu to [`disabledCommandIds`](https://salesforce.quip.com/dev/liveapps/documentation#menus-updating-the-toolbar). |
| 141 | + |
| 142 | +The `subCommands` configuration is automatically built from the component tree and will not be used if it is defined. |
| 143 | + |
| 144 | +### `MenuSeparator` |
| 145 | + |
| 146 | +This adds a `quip.apps.DocumentMenuCommands.SEPARATOR` to the menu. |
0 commit comments