aboutsummaryrefslogtreecommitdiffstats
path: root/packages/react-shared/src/components/nested_sidebar_menu.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/react-shared/src/components/nested_sidebar_menu.tsx')
-rw-r--r--packages/react-shared/src/components/nested_sidebar_menu.tsx180
1 files changed, 75 insertions, 105 deletions
diff --git a/packages/react-shared/src/components/nested_sidebar_menu.tsx b/packages/react-shared/src/components/nested_sidebar_menu.tsx
index c8bddb59a..196c91af1 100644
--- a/packages/react-shared/src/components/nested_sidebar_menu.tsx
+++ b/packages/react-shared/src/components/nested_sidebar_menu.tsx
@@ -1,149 +1,119 @@
+import { ObjectMap } from '@0x/types';
import * as _ from 'lodash';
import MenuItem from 'material-ui/MenuItem';
import * as React from 'react';
-import { Link as ScrollLink } from 'react-scroll';
-import { MenuSubsectionsBySection, Styles } from '../types';
+import { ALink, Styles } from '../types';
import { colors } from '../utils/colors';
-import { constants } from '../utils/constants';
import { utils } from '../utils/utils';
-import { VersionDropDown } from './version_drop_down';
+import { Link } from './link';
export interface NestedSidebarMenuProps {
- topLevelMenu: { [topLevel: string]: string[] };
- menuSubsectionsBySection: MenuSubsectionsBySection;
+ sectionNameToLinks: ObjectMap<ALink[]>;
sidebarHeader?: React.ReactNode;
- shouldDisplaySectionHeaders?: boolean;
- onMenuItemClick?: () => void;
- selectedVersion?: string;
- versions?: string[];
- onVersionSelected?: (semver: string) => void;
+ shouldReformatMenuItemNames?: boolean;
}
-export interface NestedSidebarMenuState {}
+export interface NestedSidebarMenuState {
+ scrolledToId?: string;
+}
const styles: Styles = {
- menuItemWithHeaders: {
+ menuItem: {
minHeight: 0,
+ paddingLeft: 8,
+ borderRadius: 6,
},
- menuItemWithoutHeaders: {
- minHeight: 48,
- },
- menuItemInnerDivWithHeaders: {
+ menuItemInnerDiv: {
color: colors.grey800,
fontSize: 14,
lineHeight: 2,
padding: 0,
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
},
};
export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, NestedSidebarMenuState> {
public static defaultProps: Partial<NestedSidebarMenuProps> = {
- shouldDisplaySectionHeaders: true,
- onMenuItemClick: _.noop.bind(_),
+ shouldReformatMenuItemNames: true,
};
+ private _urlIntervalCheckId: number | undefined = undefined;
+ constructor(props: NestedSidebarMenuProps) {
+ super(props);
+ this.state = {};
+ }
+ public componentDidMount(): void {
+ this._urlIntervalCheckId = window.setInterval(() => {
+ const scrollId = location.hash.slice(1);
+ if (scrollId !== this.state.scrolledToId) {
+ this.setState({
+ scrolledToId: scrollId,
+ });
+ }
+ }, 200);
+ }
+ public componentWillUnmount(): void {
+ window.clearInterval(this._urlIntervalCheckId);
+ }
public render(): React.ReactNode {
- const navigation = _.map(this.props.topLevelMenu, (menuItems: string[], sectionName: string) => {
+ const navigation = _.map(this.props.sectionNameToLinks, (links: ALink[], sectionName: string) => {
const finalSectionName = utils.convertCamelCaseToSpaces(sectionName);
- if (this.props.shouldDisplaySectionHeaders) {
- // tslint:disable-next-line:no-unused-variable
- const id = utils.getIdFromName(sectionName);
- return (
- <div key={`section-${sectionName}`} className="py1" style={{ color: colors.grey800 }}>
- <div style={{ fontWeight: 'bold', fontSize: 15 }} className="py1">
- {finalSectionName.toUpperCase()}
- </div>
- {this._renderMenuItems(menuItems)}
+ // tslint:disable-next-line:no-unused-variable
+ return (
+ <div key={`section-${sectionName}`} className="py1" style={{ color: colors.greyTheme }}>
+ <div style={{ fontSize: 14, letterSpacing: 0.5 }} className="py1 pl1">
+ {finalSectionName.toUpperCase()}
</div>
- );
- } else {
- return <div key={`section-${sectionName}`}>{this._renderMenuItems(menuItems)}</div>;
- }
+ {this._renderMenuItems(links)}
+ </div>
+ );
});
- const maxWidthWithScrollbar = 307;
return (
<div>
{this.props.sidebarHeader}
- {!_.isUndefined(this.props.versions) &&
- !_.isUndefined(this.props.selectedVersion) &&
- !_.isUndefined(this.props.onVersionSelected) && (
- <div style={{ maxWidth: maxWidthWithScrollbar }}>
- <VersionDropDown
- selectedVersion={this.props.selectedVersion}
- versions={this.props.versions}
- onVersionSelected={this.props.onVersionSelected}
- />
- </div>
- )}
- <div className="pl1">{navigation}</div>
+ <div>{navigation}</div>
</div>
);
}
- private _renderMenuItems(menuItemNames: string[]): React.ReactNode[] {
- const menuItemStyles = this.props.shouldDisplaySectionHeaders
- ? styles.menuItemWithHeaders
- : styles.menuItemWithoutHeaders;
- const menuItemInnerDivStyles = this.props.shouldDisplaySectionHeaders ? styles.menuItemInnerDivWithHeaders : {};
- const menuItems = _.map(menuItemNames, menuItemName => {
- const finalMenuItemName = utils.convertDashesToSpaces(menuItemName);
- const id = utils.getIdFromName(menuItemName);
+ private _renderMenuItems(links: ALink[]): React.ReactNode[] {
+ const scrolledToId = this.state.scrolledToId;
+ const menuItems = _.map(links, link => {
+ const finalMenuItemName = this.props.shouldReformatMenuItemNames
+ ? utils.convertDashesToSpaces(link.title)
+ : link.title;
+ let menuItemStyle = styles.menuItem;
+ let menuItemInnerDivStyle = styles.menuItemInnerDiv;
+ const isScrolledTo = link.to === scrolledToId;
+ if (isScrolledTo) {
+ menuItemStyle = {
+ ...menuItemStyle,
+ backgroundColor: colors.lightLinkBlue,
+ };
+ menuItemInnerDivStyle = {
+ ...menuItemInnerDivStyle,
+ color: colors.white,
+ fontWeight: 'bold',
+ };
+ }
return (
- <div key={menuItemName}>
- <ScrollLink
- key={`menuItem-${menuItemName}`}
- to={id}
- offset={0}
- hashSpy={true}
- duration={constants.DOCS_SCROLL_DURATION_MS}
- containerId={constants.DOCS_CONTAINER_ID}
- >
- <MenuItem style={menuItemStyles} innerDivStyle={menuItemInnerDivStyles}>
- <span style={{ textTransform: 'capitalize' }}>{finalMenuItemName}</span>
+ <div key={`menuItem-${finalMenuItemName}`}>
+ <Link to={link.to} shouldOpenInNewTab={link.shouldOpenInNewTab}>
+ <MenuItem style={menuItemStyle} innerDivStyle={menuItemInnerDivStyle}>
+ <span
+ style={{
+ textTransform: this.props.shouldReformatMenuItemNames ? 'capitalize' : 'none',
+ }}
+ >
+ {finalMenuItemName}
+ </span>
</MenuItem>
- </ScrollLink>
- {this._renderMenuItemSubsections(menuItemName)}
+ </Link>
</div>
);
});
return menuItems;
}
- private _renderMenuItemSubsections(menuItemName: string): React.ReactNode {
- if (_.isUndefined(this.props.menuSubsectionsBySection[menuItemName])) {
- return null;
- }
- return this._renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]);
- }
- private _renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode {
- return (
- <ul style={{ margin: 0, listStyleType: 'none', paddingLeft: 0 }} key={menuItemName}>
- {_.map(entityNames, entityName => {
- const name = `${menuItemName}-${entityName}`;
- const id = utils.getIdFromName(name);
- return (
- <li key={`menuSubsectionItem-${name}`}>
- <ScrollLink
- to={id}
- offset={0}
- hashSpy={true}
- duration={constants.DOCS_SCROLL_DURATION_MS}
- containerId={constants.DOCS_CONTAINER_ID}
- >
- <MenuItem
- style={{ minHeight: 35 }}
- innerDivStyle={{
- paddingLeft: 16,
- fontSize: 14,
- lineHeight: '35px',
- }}
- >
- {entityName}
- </MenuItem>
- </ScrollLink>
- </li>
- );
- })}
- </ul>
- );
- }
}