aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorKadinsky <kandinsky454@protonmail.ch>2018-10-18 19:20:50 +0800
committerGitHub <noreply@github.com>2018-10-18 19:20:50 +0800
commit325af82217e994fdde8e904b93a76e6e3461f85a (patch)
treec51543ab9038ce0a3d42e4f0b7f6e257a2368c08 /packages
parentea65fa4f6560264b8aee6b4b1c9272a0efa82b12 (diff)
parent47dc384ea36fecbcf01eb9b3f20936331b43a0c6 (diff)
downloaddexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.tar
dexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.tar.gz
dexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.tar.bz2
dexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.tar.lz
dexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.tar.xz
dexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.tar.zst
dexon-0x-contracts-325af82217e994fdde8e904b93a76e6e3461f85a.zip
Merge pull request #1154 from 0xProject/dev-section-redesign
[BASE_BRANCH] Developer section redesign
Diffstat (limited to 'packages')
-rw-r--r--packages/ethereum-types/CHANGELOG.json10
-rw-r--r--packages/react-docs/package.json6
-rw-r--r--packages/react-docs/src/components/comment.tsx4
-rw-r--r--packages/react-docs/src/components/doc_reference.tsx (renamed from packages/react-docs/src/components/documentation.tsx)177
-rw-r--r--packages/react-docs/src/components/signature_block.tsx2
-rw-r--r--packages/react-docs/src/components/source_link.tsx8
-rw-r--r--packages/react-docs/src/components/type.tsx73
-rw-r--r--packages/react-docs/src/components/type_definition.tsx1
-rw-r--r--packages/react-docs/src/docs_info.ts70
-rw-r--r--packages/react-docs/src/index.ts2
-rw-r--r--packages/react-docs/src/utils/typedoc_utils.ts10
-rw-r--r--packages/react-shared/CHANGELOG.json12
-rw-r--r--packages/react-shared/package.json9
-rw-r--r--packages/react-shared/src/components/anchor_title.tsx76
-rw-r--r--packages/react-shared/src/components/link.tsx131
-rw-r--r--packages/react-shared/src/components/markdown_paragraph_block.tsx10
-rw-r--r--packages/react-shared/src/components/markdown_section.tsx38
-rw-r--r--packages/react-shared/src/components/nested_sidebar_menu.tsx180
-rw-r--r--packages/react-shared/src/components/version_drop_down.tsx37
-rw-r--r--packages/react-shared/src/index.ts3
-rw-r--r--packages/react-shared/src/types.ts16
-rw-r--r--packages/react-shared/src/utils/colors.ts10
-rw-r--r--packages/react-shared/src/utils/constants.ts3
-rw-r--r--packages/website/less/all.less13
-rw-r--r--packages/website/package.json4
-rw-r--r--packages/website/public/css/basscss_responsive_custom.css12
-rw-r--r--packages/website/public/images/developers/tutorials/0x_order_basics.svg1
-rw-r--r--packages/website/public/images/developers/tutorials/build_a_relayer.svg3
-rw-r--r--packages/website/public/images/developers/tutorials/build_a_trading_bot.svg6
-rw-r--r--packages/website/public/images/developers/tutorials/develop_on_ethereum.svg4
-rw-r--r--packages/website/public/images/developers/tutorials/use_shared_liquidity.svg3
-rw-r--r--packages/website/public/images/docs_logo.svg24
-rw-r--r--packages/website/translations/chinese.json21
-rw-r--r--packages/website/translations/english.json21
-rw-r--r--packages/website/translations/korean.json21
-rw-r--r--packages/website/translations/russian.json21
-rw-r--r--packages/website/translations/spanish.json21
-rw-r--r--packages/website/ts/components/documentation/docs_logo.tsx20
-rw-r--r--packages/website/ts/components/documentation/docs_top_bar.tsx108
-rw-r--r--packages/website/ts/components/documentation/overview_content.tsx134
-rw-r--r--packages/website/ts/components/documentation/sidebar_header.tsx57
-rw-r--r--packages/website/ts/components/documentation/tutorial_button.tsx59
-rw-r--r--packages/website/ts/components/documentation/version_drop_down.tsx80
-rw-r--r--packages/website/ts/components/dropdowns/developers_drop_down.tsx164
-rw-r--r--packages/website/ts/components/fill_order.tsx5
-rw-r--r--packages/website/ts/components/footer.tsx110
-rw-r--r--packages/website/ts/components/inputs/token_amount_input.tsx6
-rw-r--r--packages/website/ts/components/portal/back_button.tsx6
-rw-r--r--packages/website/ts/components/portal/drawer_menu.tsx2
-rw-r--r--packages/website/ts/components/portal/menu.tsx6
-rw-r--r--packages/website/ts/components/portal/portal.tsx10
-rw-r--r--packages/website/ts/components/sidebar_header.tsx35
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx288
-rw-r--r--packages/website/ts/components/top_bar/top_bar_menu_item.tsx23
-rw-r--r--packages/website/ts/components/ui/button.tsx7
-rw-r--r--packages/website/ts/components/ui/container.tsx4
-rw-r--r--packages/website/ts/components/ui/custom_menu_item.tsx (renamed from packages/website/ts/components/ui/menu_item.tsx)15
-rw-r--r--packages/website/ts/components/ui/drop_down.tsx12
-rw-r--r--packages/website/ts/components/ui/simple_menu.tsx4
-rw-r--r--packages/website/ts/components/ui/text.tsx4
-rw-r--r--packages/website/ts/containers/asset_buyer_documentation.ts4
-rw-r--r--packages/website/ts/containers/connect_documentation.ts7
-rw-r--r--packages/website/ts/containers/contract_wrappers_documentation.ts7
-rw-r--r--packages/website/ts/containers/docs_home.ts31
-rw-r--r--packages/website/ts/containers/ethereum_types_documentation.ts8
-rw-r--r--packages/website/ts/containers/json_schemas_documentation.ts10
-rw-r--r--packages/website/ts/containers/order_utils_documentation.ts7
-rw-r--r--packages/website/ts/containers/order_watcher_documentation.ts7
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.ts4
-rw-r--r--packages/website/ts/containers/sol_compiler_documentation.ts8
-rw-r--r--packages/website/ts/containers/sol_cov_documentation.ts8
-rw-r--r--packages/website/ts/containers/subproviders_documentation.ts8
-rw-r--r--packages/website/ts/containers/web3_wrapper_documentation.ts15
-rw-r--r--packages/website/ts/containers/wiki.ts3
-rw-r--r--packages/website/ts/containers/zero_ex_js_documentation.ts14
-rw-r--r--packages/website/ts/index.tsx2
-rw-r--r--packages/website/ts/pages/about/about.tsx5
-rw-r--r--packages/website/ts/pages/documentation/developers_page.tsx182
-rw-r--r--packages/website/ts/pages/documentation/doc_page.tsx104
-rw-r--r--packages/website/ts/pages/documentation/docs_home.tsx384
-rw-r--r--packages/website/ts/pages/landing/landing.tsx15
-rw-r--r--packages/website/ts/pages/wiki/wiki.tsx217
-rw-r--r--packages/website/ts/types.ts35
-rw-r--r--packages/website/ts/utils/constants.ts29
-rw-r--r--packages/website/ts/utils/translate.ts7
85 files changed, 2257 insertions, 1086 deletions
diff --git a/packages/ethereum-types/CHANGELOG.json b/packages/ethereum-types/CHANGELOG.json
index 60fb8c806..ffc4742b1 100644
--- a/packages/ethereum-types/CHANGELOG.json
+++ b/packages/ethereum-types/CHANGELOG.json
@@ -1,6 +1,6 @@
[
{
- "version": "1.1.0",
+ "version": "1.1.1",
"changes": [
{
"note": "Add `JSONRPCResponseError` and error field on `JSONRPCResponsePayload`.",
@@ -9,6 +9,14 @@
]
},
{
+ "version": "1.1.0",
+ "changes": [
+ {
+ "note": "Unpublished package."
+ }
+ ]
+ },
+ {
"timestamp": 1538693146,
"version": "1.0.11",
"changes": [
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index b1e80d1b6..6830a2101 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -27,6 +27,7 @@
"@0xproject/dev-utils": "^1.0.12",
"@0xproject/tslint-config": "^1.0.8",
"@types/compare-versions": "^3.0.0",
+ "@types/styled-components": "^4.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "^5.9.1",
@@ -49,9 +50,10 @@
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-markdown": "^3.2.2",
- "react-scroll": "0xproject/react-scroll#similar-to-pr-330",
+ "react-scroll": "0xproject/react-scroll#similar-to-pr-330-but-with-replace-state",
"react-tooltip": "^3.2.7",
- "semver": "5.5.0"
+ "semver": "5.5.0",
+ "styled-components": "^3.3.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/react-docs/src/components/comment.tsx b/packages/react-docs/src/components/comment.tsx
index c3687c510..9c866e62c 100644
--- a/packages/react-docs/src/components/comment.tsx
+++ b/packages/react-docs/src/components/comment.tsx
@@ -1,4 +1,4 @@
-import { MarkdownCodeBlock } from '@0xproject/react-shared';
+import { colors, MarkdownCodeBlock } from '@0xproject/react-shared';
import * as React from 'react';
import * as ReactMarkdown from 'react-markdown';
@@ -13,7 +13,7 @@ const defaultProps = {
export const Comment: React.SFC<CommentProps> = (props: CommentProps) => {
return (
- <div className={`${props.className} comment`}>
+ <div className={`${props.className} comment`} style={{ color: colors.greyTheme }}>
<ReactMarkdown source={props.comment} renderers={{ code: MarkdownCodeBlock }} />
</div>
);
diff --git a/packages/react-docs/src/components/documentation.tsx b/packages/react-docs/src/components/doc_reference.tsx
index a23111297..5fdcdd2d9 100644
--- a/packages/react-docs/src/components/documentation.tsx
+++ b/packages/react-docs/src/components/doc_reference.tsx
@@ -2,11 +2,11 @@ import {
colors,
constants as sharedConstants,
EtherscanLinkSuffixes,
+ HeaderSizes,
+ Link,
MarkdownSection,
- NestedSidebarMenu,
Networks,
SectionHeader,
- Styles,
utils as sharedUtils,
} from '@0xproject/react-shared';
import {
@@ -20,7 +20,6 @@ import {
TypescriptMethod,
} from '@0xproject/types';
import * as _ from 'lodash';
-import CircularProgress from 'material-ui/CircularProgress';
import * as React from 'react';
import * as semver from 'semver';
@@ -42,142 +41,42 @@ const networkNameToColor: { [network: string]: string } = {
[Networks.Rinkeby]: colors.darkYellow,
};
-export interface DocumentationProps {
+export interface DocReferenceProps {
selectedVersion: string;
availableVersions: string[];
docsInfo: DocsInfo;
sourceUrl: string;
- onVersionSelected: (semver: string) => void;
docAgnosticFormat?: DocAgnosticFormat;
- sidebarHeader?: React.ReactNode;
- topBarHeight?: number;
}
-export interface DocumentationState {
- isHoveringSidebar: boolean;
-}
+export interface DocReferenceState {}
-export class Documentation extends React.Component<DocumentationProps, DocumentationState> {
- public static defaultProps: Partial<DocumentationProps> = {
- topBarHeight: 0,
- };
- constructor(props: DocumentationProps) {
- super(props);
- this.state = {
- isHoveringSidebar: false,
- };
- }
+export class DocReference extends React.Component<DocReferenceProps, DocReferenceState> {
public componentDidMount(): void {
window.addEventListener('hashchange', this._onHashChanged.bind(this), false);
}
public componentWillUnmount(): void {
window.removeEventListener('hashchange', this._onHashChanged.bind(this), false);
}
- public componentDidUpdate(prevProps: DocumentationProps, _prevState: DocumentationState): void {
+ public componentDidUpdate(prevProps: DocReferenceProps, _prevState: DocReferenceState): void {
if (!_.isEqual(prevProps.docAgnosticFormat, this.props.docAgnosticFormat)) {
const hash = window.location.hash.slice(1);
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
}
}
public render(): React.ReactNode {
- const styles: Styles = {
- mainContainers: {
- position: 'absolute',
- top: 1,
- left: 0,
- bottom: 0,
- right: 0,
- overflowX: 'hidden',
- overflowY: 'scroll',
- minHeight: `calc(100vh - ${this.props.topBarHeight}px)`,
- WebkitOverflowScrolling: 'touch',
- },
- menuContainer: {
- borderColor: colors.grey300,
- maxWidth: 330,
- marginLeft: 20,
- },
- };
- const menuSubsectionsBySection = this.props.docsInfo.getMenuSubsectionsBySection(this.props.docAgnosticFormat);
- return (
- <div>
- {_.isUndefined(this.props.docAgnosticFormat) ? (
- this._renderLoading(styles.mainContainers)
- ) : (
- <div style={{ width: '100%', height: '100%', backgroundColor: colors.gray40 }}>
- <div
- className="mx-auto max-width-4 flex"
- style={{ color: colors.grey800, height: `calc(100vh - ${this.props.topBarHeight}px)` }}
- >
- <div
- className="relative sm-hide xs-hide"
- style={{ width: '36%', height: `calc(100vh - ${this.props.topBarHeight}px)` }}
- >
- <div
- className="border-right absolute"
- style={{
- ...styles.menuContainer,
- ...styles.mainContainers,
- height: `calc(100vh - ${this.props.topBarHeight}px)`,
- overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden',
- }}
- onMouseEnter={this._onSidebarHover.bind(this)}
- onMouseLeave={this._onSidebarHoverOff.bind(this)}
- >
- <NestedSidebarMenu
- selectedVersion={this.props.selectedVersion}
- versions={this.props.availableVersions}
- sidebarHeader={this.props.sidebarHeader}
- topLevelMenu={this.props.docsInfo.menu}
- menuSubsectionsBySection={menuSubsectionsBySection}
- onVersionSelected={this.props.onVersionSelected}
- />
- </div>
- </div>
- <div
- className="relative col lg-col-9 md-col-9 sm-col-12 col-12"
- style={{ backgroundColor: colors.white }}
- >
- <div
- id={sharedConstants.SCROLL_CONTAINER_ID}
- style={styles.mainContainers}
- className="absolute px1"
- >
- <div id={sharedConstants.SCROLL_TOP_ID} />
- {this._renderDocumentation()}
- </div>
- </div>
- </div>
- </div>
- )}
- </div>
- );
- }
- private _renderLoading(mainContainersStyles: React.CSSProperties): React.ReactNode {
- return (
- <div className="col col-12" style={mainContainersStyles}>
- <div
- className="relative sm-px2 sm-pt2 sm-m1"
- style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
- >
- <div className="center pb2">
- <CircularProgress size={40} thickness={5} />
- </div>
- <div className="center pt2" style={{ paddingBottom: 11 }}>
- Loading documentation...
- </div>
- </div>
- </div>
- );
- }
- private _renderDocumentation(): React.ReactNode {
- const subMenus = _.values(this.props.docsInfo.menu);
+ const subMenus = _.values(this.props.docsInfo.markdownMenu);
const orderedSectionNames = _.flatten(subMenus);
const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.props.docAgnosticFormat);
const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName));
- return renderedSections;
+ return (
+ <div>
+ <div id={sharedConstants.SCROLL_TOP_ID} />
+ {renderedSections}
+ </div>
+ );
}
private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
const markdownVersions = _.keys(this.props.docsInfo.sectionNameToMarkdownByVersion);
@@ -195,11 +94,16 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
const closestVersion = sortedEligibleVersions[0];
const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdownByVersion[closestVersion][sectionName];
if (!_.isUndefined(markdownFileIfExists)) {
+ // Special-case replace the `introduction` sectionName with the package name
+ const isIntroductionSection = sectionName === 'introduction';
+ const headerSize = isIntroductionSection ? HeaderSizes.H1 : HeaderSizes.H3;
return (
<MarkdownSection
key={`markdown-section-${sectionName}`}
sectionName={sectionName}
+ headerSize={headerSize}
markdownContent={markdownFileIfExists}
+ alternativeSectionTitle={isIntroductionSection ? this.props.docsInfo.displayName : undefined}
/>
);
}
@@ -290,7 +194,9 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
)}
{!_.isEmpty(docSection.functions) && (
<div>
- {!isExportedFunctionSection && <h2 style={headerStyle}>Functions</h2>}
+ {!isExportedFunctionSection && (
+ <div style={{ ...headerStyle, fontSize: '1.5em' }}>Functions</div>
+ )}
<div>{functionDefs}</div>
</div>
)}
@@ -309,6 +215,15 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
<div>{typeDefs}</div>
</div>
)}
+ <div
+ style={{
+ width: '100%',
+ height: 1,
+ backgroundColor: colors.grey300,
+ marginTop: 32,
+ marginBottom: 12,
+ }}
+ />
</div>
);
}
@@ -318,9 +233,9 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
<div className="pt2" key={`external-export-${exportName}`}>
<code className={`hljs ${constants.TYPE_TO_SYNTAX[this.props.docsInfo.type]}`}>
{`import { `}
- <a href={link} target="_blank" style={{ color: colors.lightBlueA700, textDecoration: 'none' }}>
+ <Link to={link} shouldOpenInNewTab={true} fontColor={colors.lightBlueA700}>
{exportName}
- </a>
+ </Link>
{` } from '${this.props.docsInfo.packageName}'`}
</code>
</div>
@@ -349,14 +264,16 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
EtherscanLinkSuffixes.Address,
);
return (
- <a
- key={`badge-${networkName}-${sectionName}`}
- href={linkIfExists}
- target="_blank"
- style={{ color: colors.white, textDecoration: 'none', marginTop: 8 }}
- >
- <Badge title={networkName} backgroundColor={networkNameToColor[networkName]} />
- </a>
+ <div style={{ marginTop: 8 }}>
+ <Link
+ key={`badge-${networkName}-${sectionName}`}
+ to={linkIfExists}
+ shouldOpenInNewTab={true}
+ fontColor={colors.white}
+ >
+ <Badge title={networkName} backgroundColor={networkNameToColor[networkName]} />
+ </Link>
+ </div>
);
},
);
@@ -406,16 +323,6 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
/>
);
}
- private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
- this.setState({
- isHoveringSidebar: true,
- });
- }
- private _onSidebarHoverOff(): void {
- this.setState({
- isHoveringSidebar: false,
- });
- }
private _onHashChanged(_event: any): void {
const hash = window.location.hash.slice(1);
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
diff --git a/packages/react-docs/src/components/signature_block.tsx b/packages/react-docs/src/components/signature_block.tsx
index 5ec82983a..819311953 100644
--- a/packages/react-docs/src/components/signature_block.tsx
+++ b/packages/react-docs/src/components/signature_block.tsx
@@ -55,7 +55,7 @@ export class SignatureBlock extends React.Component<SignatureBlockProps, Signatu
<div
id={`${this.props.sectionName}-${method.name}`}
style={{ overflow: 'hidden', width: '100%' }}
- className="pb4"
+ className="pb4 pt2"
onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
diff --git a/packages/react-docs/src/components/source_link.tsx b/packages/react-docs/src/components/source_link.tsx
index 3096ad8d5..c6dd09adb 100644
--- a/packages/react-docs/src/components/source_link.tsx
+++ b/packages/react-docs/src/components/source_link.tsx
@@ -1,4 +1,4 @@
-import { colors } from '@0xproject/react-shared';
+import { colors, Link } from '@0xproject/react-shared';
import { Source } from '@0xproject/types';
import * as React from 'react';
@@ -13,9 +13,9 @@ export const SourceLink = (props: SourceLinkProps) => {
const sourceCodeUrl = `${props.sourceUrl}/${src.fileName}#L${src.line}`;
return (
<div className="pt2" style={{ fontSize: 14 }}>
- <a href={sourceCodeUrl} target="_blank" className="underline" style={{ color: colors.grey }}>
- Source
- </a>
+ <Link to={sourceCodeUrl} shouldOpenInNewTab={true} textDecoration="underline" fontColor={colors.grey}>
+ {'Source'}
+ </Link>
</div>
);
};
diff --git a/packages/react-docs/src/components/type.tsx b/packages/react-docs/src/components/type.tsx
index 5c018f5dd..d579449f4 100644
--- a/packages/react-docs/src/components/type.tsx
+++ b/packages/react-docs/src/components/type.tsx
@@ -1,4 +1,4 @@
-import { colors, constants as sharedConstants, utils as sharedUtils } from '@0xproject/react-shared';
+import { colors, constants as sharedConstants, Link, utils as sharedUtils } from '@0xproject/react-shared';
import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '@0xproject/types';
import { errorUtils } from '@0xproject/utils';
import * as _ from 'lodash';
@@ -204,15 +204,12 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => {
const isExportedClassReference = !!props.type.isExportedClassReference;
const typeNameUrlIfExists = !_.isUndefined(props.type.externalLink) ? props.type.externalLink : undefined;
if (!_.isUndefined(typeNameUrlIfExists)) {
- typeName = (
- <a
- href={typeNameUrlIfExists}
- target="_blank"
- className="text-decoration-none"
- style={{ color: colors.lightBlueA700 }}
- >
+ typeName = props.isInPopover ? (
+ <span style={{ color: colors.lightBlueA700, cursor: 'pointer' }}>{typeName}</span>
+ ) : (
+ <Link to={typeNameUrlIfExists} shouldOpenInNewTab={true} fontColor={colors.lightBlueA700}>
{typeName}
- </a>
+ </Link>
);
} else if (
(isReference || isArray) &&
@@ -223,39 +220,41 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => {
? props.type.name
: `${props.docsInfo.typeSectionName}-${typeName}`;
typeName = (
- <ScrollLink
- to={typeDefinitionAnchorId}
- offset={0}
- hashSpy={true}
- duration={sharedConstants.DOCS_SCROLL_DURATION_MS}
- containerId={sharedConstants.DOCS_CONTAINER_ID}
- >
+ <span>
{sharedUtils.isUserOnMobile() || props.isInPopover || isExportedClassReference ? (
<span style={{ color: colors.lightBlueA700, cursor: 'pointer' }}>{typeName}</span>
) : (
- <span
- data-tip={true}
- data-for={id}
- style={{
- color: colors.lightBlueA700,
- cursor: 'pointer',
- display: 'inline-block',
- }}
+ <ScrollLink
+ to={typeDefinitionAnchorId}
+ offset={0}
+ hashSpy={true}
+ duration={sharedConstants.DOCS_SCROLL_DURATION_MS}
+ containerId={sharedConstants.SCROLL_CONTAINER_ID}
>
- {typeName}
- <ReactTooltip type="light" effect="solid" id={id} className="typeTooltip">
- <TypeDefinition
- sectionName={props.sectionName}
- customType={props.typeDefinitionByName[typeName as string]}
- shouldAddId={false}
- docsInfo={props.docsInfo}
- typeDefinitionByName={props.typeDefinitionByName}
- isInPopover={true}
- />
- </ReactTooltip>
- </span>
+ <span
+ data-tip={true}
+ data-for={id}
+ style={{
+ color: colors.lightBlueA700,
+ cursor: 'pointer',
+ display: 'inline-block',
+ }}
+ >
+ {typeName}
+ <ReactTooltip type="light" effect="solid" id={id} className="typeTooltip">
+ <TypeDefinition
+ sectionName={props.sectionName}
+ customType={props.typeDefinitionByName[typeName as string]}
+ shouldAddId={false}
+ docsInfo={props.docsInfo}
+ typeDefinitionByName={props.typeDefinitionByName}
+ isInPopover={true}
+ />
+ </ReactTooltip>
+ </span>
+ </ScrollLink>
)}
- </ScrollLink>
+ </span>
);
}
return (
diff --git a/packages/react-docs/src/components/type_definition.tsx b/packages/react-docs/src/components/type_definition.tsx
index 9a3e50a1b..3b64247f2 100644
--- a/packages/react-docs/src/components/type_definition.tsx
+++ b/packages/react-docs/src/components/type_definition.tsx
@@ -124,6 +124,7 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
title={`${typePrefix} ${customType.name}`}
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
shouldShowAnchor={this.state.shouldShowAnchor}
+ isDisabled={this.props.isInPopover}
/>
<div style={{ fontSize: 16 }}>
<pre>
diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts
index 092a8c266..08e7703df 100644
--- a/packages/react-docs/src/docs_info.ts
+++ b/packages/react-docs/src/docs_info.ts
@@ -1,5 +1,5 @@
-import { MenuSubsectionsBySection } from '@0xproject/react-shared';
-import { DocAgnosticFormat, TypeDefinitionByName } from '@0xproject/types';
+import { ALink, utils as sharedUtils } from '@0xproject/react-shared';
+import { DocAgnosticFormat, ObjectMap, TypeDefinitionByName } from '@0xproject/types';
import * as _ from 'lodash';
import {
@@ -17,7 +17,7 @@ export class DocsInfo {
public displayName: string;
public packageName: string;
public packageUrl: string;
- public menu: DocsMenu;
+ public markdownMenu: DocsMenu;
public typeSectionName: string;
public sections: SectionsMap;
public sectionNameToMarkdownByVersion: SectionNameToMarkdownByVersion;
@@ -25,7 +25,7 @@ export class DocsInfo {
constructor(config: DocsInfoConfig) {
this.id = config.id;
this.type = config.type;
- this.menu = config.markdownMenu;
+ this.markdownMenu = config.markdownMenu;
this.displayName = config.displayName;
this.packageName = config.packageName;
this.packageUrl = config.packageUrl;
@@ -34,10 +34,31 @@ export class DocsInfo {
this.sectionNameToMarkdownByVersion = config.sectionNameToMarkdownByVersion;
this.contractsByVersionByNetworkId = config.contractsByVersionByNetworkId;
}
- public getMenuSubsectionsBySection(docAgnosticFormat?: DocAgnosticFormat): MenuSubsectionsBySection {
- const menuSubsectionsBySection = {} as MenuSubsectionsBySection;
+ public getTypeDefinitionsByName(docAgnosticFormat: DocAgnosticFormat): ObjectMap<TypeDefinitionByName> {
+ if (_.isUndefined(docAgnosticFormat[this.typeSectionName])) {
+ return {};
+ }
+
+ const section = docAgnosticFormat[this.typeSectionName];
+ const typeDefinitionByName = _.keyBy(section.types, 'name') as any;
+ return typeDefinitionByName;
+ }
+ public getSectionNameToLinks(docAgnosticFormat: DocAgnosticFormat): ObjectMap<ALink[]> {
+ const sectionNameToLinks: ObjectMap<ALink[]> = {};
+ _.each(this.markdownMenu, (linkTitles, sectionName) => {
+ sectionNameToLinks[sectionName] = [];
+ _.each(linkTitles, linkTitle => {
+ const to = sharedUtils.getIdFromName(linkTitle);
+ const links = sectionNameToLinks[sectionName];
+ links.push({
+ title: linkTitle,
+ to,
+ });
+ });
+ });
+
if (_.isUndefined(docAgnosticFormat)) {
- return menuSubsectionsBySection;
+ return sectionNameToLinks;
}
const docSections = _.keys(this.sections);
@@ -58,7 +79,13 @@ export class DocsInfo {
if (sectionName === this.typeSectionName) {
const sortedTypesNames = _.sortBy(docSection.types, 'name');
const typeNames = _.map(sortedTypesNames, t => t.name);
- menuSubsectionsBySection[sectionName] = typeNames;
+ const typeLinks = _.map(typeNames, typeName => {
+ return {
+ to: `${sectionName}-${typeName}`,
+ title: typeName,
+ };
+ });
+ sectionNameToLinks[sectionName] = typeLinks;
} else if (isExportedFunctionSection) {
// Noop so that we don't have the method listed underneath itself.
} else {
@@ -73,23 +100,18 @@ export class DocsInfo {
const methodNames = _.map(methodsSortedByName, m => m.name);
const sortedFunctionNames = _.sortBy(docSection.functions, 'name');
const functionNames = _.map(sortedFunctionNames, m => m.name);
- menuSubsectionsBySection[sectionName] = [
- ...eventNames,
- ...propertyNames,
- ...functionNames,
- ...methodNames,
- ];
+ const names = [...eventNames, ...propertyNames, ...functionNames, ...methodNames];
+
+ const links = _.map(names, name => {
+ return {
+ to: `${sectionName}-${name}`,
+ title: name,
+ };
+ });
+
+ sectionNameToLinks[sectionName] = links;
}
});
- return menuSubsectionsBySection;
- }
- public getTypeDefinitionsByName(docAgnosticFormat: DocAgnosticFormat): { [name: string]: TypeDefinitionByName } {
- if (_.isUndefined(docAgnosticFormat[this.typeSectionName])) {
- return {};
- }
-
- const section = docAgnosticFormat[this.typeSectionName];
- const typeDefinitionByName = _.keyBy(section.types, 'name') as any;
- return typeDefinitionByName;
+ return sectionNameToLinks;
}
}
diff --git a/packages/react-docs/src/index.ts b/packages/react-docs/src/index.ts
index f9382940c..504091b34 100644
--- a/packages/react-docs/src/index.ts
+++ b/packages/react-docs/src/index.ts
@@ -5,7 +5,7 @@ export { DocAgnosticFormat, GeneratedDocJson } from '@0xproject/types';
export { Badge } from './components/badge';
export { Comment } from './components/comment';
export { CustomEnum } from './components/custom_enum';
-export { Documentation } from './components/documentation';
+export { DocReference } from './components/doc_reference';
export { Enum } from './components/enum';
export { EventDefinition } from './components/event_definition';
export { Interface } from './components/interface';
diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts
index 19605d497..05c9dae55 100644
--- a/packages/react-docs/src/utils/typedoc_utils.ts
+++ b/packages/react-docs/src/utils/typedoc_utils.ts
@@ -95,7 +95,9 @@ export class TypeDocUtils {
if (!_.isEmpty(this._externalExportToLink)) {
this._docsInfo.sections[constants.EXTERNAL_EXPORTS_SECTION_NAME] = constants.EXTERNAL_EXPORTS_SECTION_NAME;
- this._docsInfo.menu[constants.EXTERNAL_EXPORTS_SECTION_NAME] = [constants.EXTERNAL_EXPORTS_SECTION_NAME];
+ this._docsInfo.markdownMenu[constants.EXTERNAL_EXPORTS_SECTION_NAME] = [
+ constants.EXTERNAL_EXPORTS_SECTION_NAME,
+ ];
const docSection: DocSection = {
comment: 'This package also re-exports some third-party libraries for your convenience.',
constructors: [],
@@ -119,7 +121,7 @@ export class TypeDocUtils {
case KindString.ObjectLiteral: {
sectionName = child.name;
this._docsInfo.sections[sectionName] = sectionName;
- this._docsInfo.menu[sectionName] = [sectionName];
+ this._docsInfo.markdownMenu[sectionName] = [sectionName];
const entities = child.children;
const commentObj = child.comment;
const sectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : '';
@@ -136,7 +138,7 @@ export class TypeDocUtils {
case KindString.Function: {
sectionName = child.name;
this._docsInfo.sections[sectionName] = sectionName;
- this._docsInfo.menu[sectionName] = [sectionName];
+ this._docsInfo.markdownMenu[sectionName] = [sectionName];
const entities = [child];
const commentObj = child.comment;
const SectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : '';
@@ -158,7 +160,7 @@ export class TypeDocUtils {
});
if (!_.isEmpty(typeEntities)) {
this._docsInfo.sections[constants.TYPES_SECTION_NAME] = constants.TYPES_SECTION_NAME;
- this._docsInfo.menu[constants.TYPES_SECTION_NAME] = [constants.TYPES_SECTION_NAME];
+ this._docsInfo.markdownMenu[constants.TYPES_SECTION_NAME] = [constants.TYPES_SECTION_NAME];
const docSection = this._convertEntitiesToDocSection(typeEntities, constants.TYPES_SECTION_NAME);
docAgnosticFormat[constants.TYPES_SECTION_NAME] = docSection;
}
diff --git a/packages/react-shared/CHANGELOG.json b/packages/react-shared/CHANGELOG.json
index d1907e785..ee0352561 100644
--- a/packages/react-shared/CHANGELOG.json
+++ b/packages/react-shared/CHANGELOG.json
@@ -1,7 +1,6 @@
[
{
- "timestamp": 1538693146,
- "version": "1.0.15",
+ "version": "1.0.17",
"changes": [
{
"note": "Dependencies updated"
@@ -9,6 +8,15 @@
]
},
{
+ "timestamp": 1538693146,
+ "version": "1.0.16",
+ "changes": [
+ {
+ "note": "Unpublished package"
+ }
+ ]
+ },
+ {
"timestamp": 1538475601,
"version": "1.0.14",
"changes": [
diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json
index afed68c42..847946eb1 100644
--- a/packages/react-shared/package.json
+++ b/packages/react-shared/package.json
@@ -33,6 +33,7 @@
"typescript": "3.0.1"
},
"dependencies": {
+ "@0xproject/types": "^1.1.2",
"@material-ui/core": "^3.0.1",
"@types/is-mobile": "0.3.0",
"@types/lodash": "4.14.104",
@@ -40,7 +41,10 @@
"@types/node": "*",
"@types/react": "*",
"@types/react-dom": "*",
+ "@types/react-router-dom": "^4.0.4",
"@types/react-scroll": "1.5.3",
+ "@types/valid-url": "^1.0.2",
+ "@types/styled-components": "^4.0.0",
"basscss": "^8.0.3",
"change-case": "^3.0.2",
"is-mobile": "^0.2.2",
@@ -50,7 +54,10 @@
"react-dom": "^16.4.2",
"react-highlight": "0xproject/react-highlight#2f40a42e0a3f0ad126f9f42d505b97b603fc7162",
"react-markdown": "^3.2.2",
- "react-scroll": "0xproject/react-scroll#similar-to-pr-330"
+ "react-scroll": "0xproject/react-scroll#similar-to-pr-330-but-with-replace-state",
+ "react-router-dom": "^4.1.1",
+ "styled-components": "^3.3.0",
+ "valid-url": "^1.0.9"
},
"publishConfig": {
"access": "public"
diff --git a/packages/react-shared/src/components/anchor_title.tsx b/packages/react-shared/src/components/anchor_title.tsx
index 8f7e4af27..bd99edcab 100644
--- a/packages/react-shared/src/components/anchor_title.tsx
+++ b/packages/react-shared/src/components/anchor_title.tsx
@@ -1,7 +1,9 @@
import * as React from 'react';
import { Link as ScrollLink } from 'react-scroll';
+import styled from 'styled-components';
import { HeaderSizes, Styles } from '../types';
+import { colors } from '../utils/colors';
import { constants } from '../utils/constants';
const headerSizeToScrollOffset: { [headerSize: string]: number } = {
@@ -14,20 +16,14 @@ export interface AnchorTitleProps {
id: string;
headerSize: HeaderSizes;
shouldShowAnchor: boolean;
+ isDisabled: boolean;
}
-export interface AnchorTitleState {
- isHovering: boolean;
-}
+export interface AnchorTitleState {}
const styles: Styles = {
- anchor: {
- fontSize: 20,
- transform: 'rotate(45deg)',
- cursor: 'pointer',
- },
h1: {
- fontSize: '1.8em',
+ fontSize: '1.875em',
},
h2: {
fontSize: '1.5em',
@@ -38,18 +34,28 @@ const styles: Styles = {
},
};
+interface AnchorIconProps {
+ shouldShowAnchor: boolean;
+}
+
+const AnchorIcon =
+ styled.i <
+ AnchorIconProps >
+ `
+ opacity: ${props => (props.shouldShowAnchor ? 1 : 0)};
+ &:hover {
+ opacity: ${props => (props.shouldShowAnchor ? 0.6 : 0)};
+ }
+ font-size: 20px;
+ transform: rotate(45deg);
+ cursor: pointer;
+ `;
+
export class AnchorTitle extends React.Component<AnchorTitleProps, AnchorTitleState> {
- constructor(props: AnchorTitleProps) {
- super(props);
- this.state = {
- isHovering: false,
- };
- }
+ public static defaultProps: Partial<AnchorTitleProps> = {
+ isDisabled: false,
+ };
public render(): React.ReactNode {
- let opacity = 0;
- if (this.props.shouldShowAnchor) {
- opacity = this.state.isHovering ? 0.6 : 1;
- }
return (
<div
className="relative flex"
@@ -63,29 +69,21 @@ export class AnchorTitle extends React.Component<AnchorTitleProps, AnchorTitleSt
} as any
}
>
- <div className="inline-block" style={{ paddingRight: 4 }}>
+ <div className="inline-block" style={{ paddingRight: 4, color: colors.darkestGrey }}>
{this.props.title}
</div>
- <ScrollLink
- to={this.props.id}
- hashSpy={true}
- offset={headerSizeToScrollOffset[this.props.headerSize]}
- duration={constants.DOCS_SCROLL_DURATION_MS}
- containerId={constants.DOCS_CONTAINER_ID}
- >
- <i
- className="zmdi zmdi-link"
- style={{ ...styles.anchor, opacity }}
- onMouseOver={this._setHoverState.bind(this, true)}
- onMouseOut={this._setHoverState.bind(this, false)}
- />
- </ScrollLink>
+ {!this.props.isDisabled && (
+ <ScrollLink
+ to={this.props.id}
+ hashSpy={true}
+ offset={headerSizeToScrollOffset[this.props.headerSize]}
+ duration={constants.DOCS_SCROLL_DURATION_MS}
+ containerId={constants.SCROLL_CONTAINER_ID}
+ >
+ <AnchorIcon className="zmdi zmdi-link" shouldShowAnchor={this.props.shouldShowAnchor} />
+ </ScrollLink>
+ )}
</div>
);
}
- private _setHoverState(isHovering: boolean): void {
- this.setState({
- isHovering,
- });
- }
}
diff --git a/packages/react-shared/src/components/link.tsx b/packages/react-shared/src/components/link.tsx
new file mode 100644
index 000000000..5a456109b
--- /dev/null
+++ b/packages/react-shared/src/components/link.tsx
@@ -0,0 +1,131 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+import { Link as ReactRounterLink } from 'react-router-dom';
+import { Link as ScrollLink } from 'react-scroll';
+import * as validUrl from 'valid-url';
+
+import { LinkType } from '../types';
+import { constants } from '../utils/constants';
+
+interface LinkProps {
+ to: string;
+ shouldOpenInNewTab?: boolean;
+ className?: string;
+ onMouseOver?: (event: React.MouseEvent<HTMLElement>) => void;
+ onMouseLeave?: (event: React.MouseEvent<HTMLElement>) => void;
+ onMouseEnter?: (event: React.MouseEvent<HTMLElement>) => void;
+ textDecoration?: string;
+ fontColor?: string;
+}
+
+export interface LinkState {}
+
+/**
+ * A generic link component which let's the developer render internal, external and scroll-to-hash links, and
+ * their associated behaviors with a single link component. Many times we want a menu including a combination of
+ * internal, external and scroll links and the abstraction of the differences of rendering each types of link
+ * makes it much easier to do so.
+ */
+export class Link extends React.Component<LinkProps, LinkState> {
+ public static defaultProps: Partial<LinkProps> = {
+ shouldOpenInNewTab: false,
+ className: '',
+ onMouseOver: _.noop.bind(_),
+ onMouseLeave: _.noop.bind(_),
+ onMouseEnter: _.noop.bind(_),
+ textDecoration: 'none',
+ fontColor: 'inherit',
+ };
+ private _outerReactScrollSpan: HTMLSpanElement | null;
+ constructor(props: LinkProps) {
+ super(props);
+ this._outerReactScrollSpan = null;
+ }
+ public render(): React.ReactNode {
+ let type: LinkType;
+ const isReactRoute = _.startsWith(this.props.to, '/');
+ const isExternal = validUrl.isWebUri(this.props.to) || _.startsWith(this.props.to, 'mailto:');
+ if (isReactRoute) {
+ type = LinkType.ReactRoute;
+ } else if (isExternal) {
+ type = LinkType.External;
+ } else {
+ type = LinkType.ReactScroll;
+ }
+
+ if (type === LinkType.ReactScroll && this.props.shouldOpenInNewTab) {
+ throw new Error(`Cannot open LinkType.ReactScroll links in new tab. link.to: ${this.props.to}`);
+ }
+
+ const styleWithDefault = {
+ textDecoration: this.props.textDecoration,
+ cursor: 'pointer',
+ color: this.props.fontColor,
+ };
+
+ switch (type) {
+ case LinkType.External:
+ return (
+ <a
+ target={this.props.shouldOpenInNewTab ? '_blank' : ''}
+ className={this.props.className}
+ style={styleWithDefault}
+ href={this.props.to}
+ onMouseOver={this.props.onMouseOver}
+ onMouseEnter={this.props.onMouseEnter}
+ onMouseLeave={this.props.onMouseLeave}
+ >
+ {this.props.children}
+ </a>
+ );
+ case LinkType.ReactRoute:
+ return (
+ <ReactRounterLink
+ to={this.props.to}
+ className={this.props.className}
+ style={styleWithDefault}
+ target={this.props.shouldOpenInNewTab ? '_blank' : ''}
+ onMouseOver={this.props.onMouseOver}
+ onMouseEnter={this.props.onMouseEnter}
+ onMouseLeave={this.props.onMouseLeave}
+ >
+ {this.props.children}
+ </ReactRounterLink>
+ );
+ case LinkType.ReactScroll:
+ return (
+ <span
+ ref={input => (this._outerReactScrollSpan = input)}
+ onMouseOver={this.props.onMouseOver}
+ onMouseEnter={this.props.onMouseEnter}
+ onMouseLeave={this.props.onMouseLeave}
+ >
+ <ScrollLink
+ to={this.props.to}
+ offset={0}
+ hashSpy={true}
+ duration={constants.DOCS_SCROLL_DURATION_MS}
+ containerId={constants.SCROLL_CONTAINER_ID}
+ className={this.props.className}
+ style={styleWithDefault}
+ >
+ <span onClick={this._onClickPropagateClickEventAroundScrollLink.bind(this)}>
+ {this.props.children}
+ </span>
+ </ScrollLink>
+ </span>
+ );
+ default:
+ throw new Error(`Unrecognized LinkType: ${type}`);
+ }
+ }
+ // HACK(fabio): For some reason, the react-scroll link decided to stop the propagation of click events.
+ // We do however rely on these events being propagated in certain scenarios (e.g when the link
+ // is within a dropdown we want to close upon being clicked). Because of this, we register the
+ // click event of an inner span, and pass it around the react-scroll link to an outer span.
+ private _onClickPropagateClickEventAroundScrollLink(): void {
+ if (!_.isNull(this._outerReactScrollSpan)) {
+ this._outerReactScrollSpan.click();
+ }
+ }
+}
diff --git a/packages/react-shared/src/components/markdown_paragraph_block.tsx b/packages/react-shared/src/components/markdown_paragraph_block.tsx
new file mode 100644
index 000000000..eeaef8571
--- /dev/null
+++ b/packages/react-shared/src/components/markdown_paragraph_block.tsx
@@ -0,0 +1,10 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { colors } from '../utils/colors';
+
+export interface MarkdownParagraphBlockProps {}
+
+export const MarkdownParagraphBlock: React.StatelessComponent<MarkdownParagraphBlockProps> = ({ children }) => {
+ return <span style={{ color: colors.greyTheme, lineHeight: '26px' }}>{children}</span>;
+};
diff --git a/packages/react-shared/src/components/markdown_section.tsx b/packages/react-shared/src/components/markdown_section.tsx
index 09b214548..e6a7d80d5 100644
--- a/packages/react-shared/src/components/markdown_section.tsx
+++ b/packages/react-shared/src/components/markdown_section.tsx
@@ -8,14 +8,17 @@ import { colors } from '../utils/colors';
import { utils } from '../utils/utils';
import { AnchorTitle } from './anchor_title';
+import { Link } from './link';
import { MarkdownCodeBlock } from './markdown_code_block';
import { MarkdownLinkBlock } from './markdown_link_block';
+import { MarkdownParagraphBlock } from './markdown_paragraph_block';
export interface MarkdownSectionProps {
sectionName: string;
markdownContent: string;
headerSize?: HeaderSizes;
githubLink?: string;
+ alternativeSectionTitle?: string;
}
interface DefaultMarkdownSectionProps {
@@ -42,20 +45,23 @@ export class MarkdownSection extends React.Component<MarkdownSectionProps, Markd
const { sectionName, markdownContent, headerSize, githubLink } = this.props as PropsWithDefaults;
const id = utils.getIdFromName(sectionName);
- const finalSectionName = utils.convertCamelCaseToSpaces(sectionName);
+ const formattedSectionName = utils.convertCamelCaseToSpaces(sectionName);
+ const title = !_.isUndefined(this.props.alternativeSectionTitle)
+ ? this.props.alternativeSectionTitle
+ : formattedSectionName;
return (
<div
className="md-px1 sm-px2 overflow-hidden"
onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
- <ScrollElement name={id}>
- <div className="clearfix pt3">
+ <ScrollElement name={id} style={{ paddingBottom: 20 }}>
+ <div className="clearfix" style={{ paddingTop: 30, paddingBottom: 20 }}>
<div className="col lg-col-8 md-col-8 sm-col-12">
- <span style={{ textTransform: 'capitalize', color: colors.grey700 }}>
+ <span style={{ color: colors.grey700 }}>
<AnchorTitle
headerSize={headerSize}
- title={finalSectionName}
+ title={_.capitalize(title)}
id={id}
shouldShowAnchor={this.state.shouldShowAnchor}
/>
@@ -63,23 +69,29 @@ export class MarkdownSection extends React.Component<MarkdownSectionProps, Markd
</div>
<div className="col col-4 sm-hide xs-hide right-align pr3" style={{ height: 28 }}>
{!_.isUndefined(githubLink) && (
- <a
- href={githubLink}
- target="_blank"
- style={{ color: colors.linkBlue, textDecoration: 'none', lineHeight: 2.1 }}
- >
- Edit on Github
- </a>
+ <div style={{ lineHeight: 2.1 }}>
+ <Link to={githubLink} shouldOpenInNewTab={true} fontColor={colors.linkBlue}>
+ Edit on Github
+ </Link>
+ </div>
)}
</div>
</div>
- <hr style={{ border: `1px solid ${colors.lightestGrey}` }} />
<ReactMarkdown
source={markdownContent}
escapeHtml={false}
renderers={{
code: MarkdownCodeBlock,
link: MarkdownLinkBlock,
+ paragraph: MarkdownParagraphBlock,
+ }}
+ />
+ <div
+ style={{
+ width: '100%',
+ height: 1,
+ backgroundColor: colors.grey300,
+ marginTop: 32,
}}
/>
</ScrollElement>
diff --git a/packages/react-shared/src/components/nested_sidebar_menu.tsx b/packages/react-shared/src/components/nested_sidebar_menu.tsx
index c8bddb59a..f734dc654 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 '@0xproject/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>
- );
- }
}
diff --git a/packages/react-shared/src/components/version_drop_down.tsx b/packages/react-shared/src/components/version_drop_down.tsx
deleted file mode 100644
index 5ff4bed54..000000000
--- a/packages/react-shared/src/components/version_drop_down.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import MenuItem from '@material-ui/core/MenuItem';
-import Select from '@material-ui/core/Select';
-import * as _ from 'lodash';
-import * as React from 'react';
-
-export interface VersionDropDownProps {
- selectedVersion: string;
- versions: string[];
- onVersionSelected: (semver: string) => void;
-}
-
-export interface VersionDropDownState {}
-
-export class VersionDropDown extends React.Component<VersionDropDownProps, VersionDropDownState> {
- public render(): React.ReactNode {
- return (
- <div className="mx-auto" style={{ width: 120 }}>
- <Select value={this.props.selectedVersion} onChange={this._updateSelectedVersion.bind(this)}>
- {this._renderDropDownItems()}
- </Select>
- </div>
- );
- }
- private _renderDropDownItems(): React.ReactNode[] {
- const items = _.map(this.props.versions, version => {
- return (
- <MenuItem key={version} value={version}>
- v{version}
- </MenuItem>
- );
- });
- return items;
- }
- private _updateSelectedVersion(event: React.ChangeEvent<HTMLSelectElement>): void {
- this.props.onVersionSelected(event.target.value);
- }
-}
diff --git a/packages/react-shared/src/index.ts b/packages/react-shared/src/index.ts
index 3b50c0117..e33b09f19 100644
--- a/packages/react-shared/src/index.ts
+++ b/packages/react-shared/src/index.ts
@@ -4,8 +4,9 @@ export { MarkdownCodeBlock } from './components/markdown_code_block';
export { MarkdownSection } from './components/markdown_section';
export { NestedSidebarMenu } from './components/nested_sidebar_menu';
export { SectionHeader } from './components/section_header';
+export { Link } from './components/link';
-export { HeaderSizes, Styles, MenuSubsectionsBySection, EtherscanLinkSuffixes, Networks } from './types';
+export { HeaderSizes, Styles, EtherscanLinkSuffixes, Networks, ALink } from './types';
export { utils } from './utils/utils';
export { constants } from './utils/constants';
diff --git a/packages/react-shared/src/types.ts b/packages/react-shared/src/types.ts
index 88fadcc09..9e8dcb6b6 100644
--- a/packages/react-shared/src/types.ts
+++ b/packages/react-shared/src/types.ts
@@ -8,10 +8,6 @@ export enum HeaderSizes {
H3 = 'h3',
}
-export interface MenuSubsectionsBySection {
- [section: string]: string[];
-}
-
export enum EtherscanLinkSuffixes {
Address = 'address',
Tx = 'tx',
@@ -23,3 +19,15 @@ export enum Networks {
Ropsten = 'Ropsten',
Rinkeby = 'Rinkeby',
}
+
+export enum LinkType {
+ External = 'EXTERNAL',
+ ReactScroll = 'REACT_SCROLL',
+ ReactRoute = 'REACT_ROUTE',
+}
+
+export interface ALink {
+ title: string;
+ to: string;
+ shouldOpenInNewTab?: boolean;
+}
diff --git a/packages/react-shared/src/utils/colors.ts b/packages/react-shared/src/utils/colors.ts
index 7d047a50e..a4dd7fefa 100644
--- a/packages/react-shared/src/utils/colors.ts
+++ b/packages/react-shared/src/utils/colors.ts
@@ -8,13 +8,17 @@ const baseColors = {
greyishPink: '#E6E5E5',
grey300: '#E0E0E0',
beigeWhite: '#E4E4E4',
- grey350: '#cacaca',
+ lightBgGrey: '#EDEDED',
+ grey325: '#dfdfdf',
+ grey350: '#CACACA',
grey400: '#BDBDBD',
lightGrey: '#BBBBBB',
grey500: '#9E9E9E',
grey: '#A5A5A5',
darkGrey: '#818181',
landingLinkGrey: '#919191',
+ linkSectionGrey: '#999999',
+ greyTheme: '#666666',
grey700: '#616161',
grey750: '#515151',
grey800: '#424242',
@@ -22,10 +26,12 @@ const baseColors = {
heroGrey: '#404040',
projectsGrey: '#343333',
darkestGrey: '#272727',
+ lightestBlue: '#E7F1FD',
lightBlue: '#60A4F4',
lightBlueA700: '#0091EA',
- linkBlue: '#1D5CDE',
+ lightLinkBlue: '#3289F1',
mediumBlue: '#488AEA',
+ linkBlue: '#1D5CDE',
darkBlue: '#4D5481',
lightTurquois: '#aefcdc',
turquois: '#058789',
diff --git a/packages/react-shared/src/utils/constants.ts b/packages/react-shared/src/utils/constants.ts
index 562ab776b..2dca1a078 100644
--- a/packages/react-shared/src/utils/constants.ts
+++ b/packages/react-shared/src/utils/constants.ts
@@ -2,8 +2,7 @@ import { Networks } from '../types';
export const constants = {
DOCS_SCROLL_DURATION_MS: 0,
- DOCS_CONTAINER_ID: 'documentation',
- SCROLL_CONTAINER_ID: 'documentation',
+ SCROLL_CONTAINER_ID: 'scroll_container',
SCROLL_TOP_ID: 'pageScrollTop',
NETWORK_NAME_BY_ID: {
1: Networks.Mainnet,
diff --git a/packages/website/less/all.less b/packages/website/less/all.less
index c62db0d20..3747e4860 100644
--- a/packages/website/less/all.less
+++ b/packages/website/less/all.less
@@ -34,17 +34,7 @@ a {
}
}
-#documentation {
- p {
- line-height: 1.5;
- }
-
- .comment {
- p {
- margin: 0px;
- }
- }
-
+#scroll_container {
.typeTooltip {
border: 1px solid lightgray;
opacity: 1;
@@ -83,6 +73,7 @@ a {
code {
border: 1px solid #e3eefe;
+ border-radius: 4px;
font-family: 'Roboto Mono';
background-color: #f2f6ff !important; // lightBlue
}
diff --git a/packages/website/package.json b/packages/website/package.json
index efab95c80..4af556b5f 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -53,8 +53,7 @@
"react-helmet": "^5.2.0",
"react-popper": "^1.0.0-beta.6",
"react-redux": "^5.0.3",
- "react-router-dom": "^4.1.1",
- "react-scroll": "0xproject/react-scroll#similar-to-pr-330",
+ "react-scroll": "0xproject/react-scroll#similar-to-pr-330-but-with-replace-state",
"react-tooltip": "^3.2.7",
"react-typist": "^2.0.4",
"redux": "^3.6.0",
@@ -83,7 +82,6 @@
"@types/react-dom": "^16.0.7",
"@types/react-helmet": "^5.0.6",
"@types/react-redux": "^4.4.37",
- "@types/react-router-dom": "^4.0.4",
"@types/react-scroll": "1.5.3",
"@types/react-tap-event-plugin": "0.0.30",
"@types/redux": "^3.6.0",
diff --git a/packages/website/public/css/basscss_responsive_custom.css b/packages/website/public/css/basscss_responsive_custom.css
index 5f8bd9117..92a681cb1 100644
--- a/packages/website/public/css/basscss_responsive_custom.css
+++ b/packages/website/public/css/basscss_responsive_custom.css
@@ -26,6 +26,10 @@
.sm-right {
float: right;
}
+ .sm-justify-end {
+ ms-flex-pack: end;
+ justify-content: flex-end;
+ }
}
@media (min-width: 52em) {
@@ -54,6 +58,10 @@
.md-right {
float: right;
}
+ .md-justify-end {
+ ms-flex-pack: end;
+ justify-content: flex-end;
+ }
}
@media (min-width: 64em) {
@@ -82,4 +90,8 @@
.lg-right {
float: right;
}
+ .lg-justify-end {
+ ms-flex-pack: end;
+ justify-content: flex-end;
+ }
}
diff --git a/packages/website/public/images/developers/tutorials/0x_order_basics.svg b/packages/website/public/images/developers/tutorials/0x_order_basics.svg
new file mode 100644
index 000000000..57b04dfa5
--- /dev/null
+++ b/packages/website/public/images/developers/tutorials/0x_order_basics.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72"><defs><style>.cls-1{fill:#3289f1;}.cls-2{fill:#fff;}</style></defs><title>Artboard 1</title><path class="cls-1" d="M62.64,26.77a0,0,0,0,0,0,0A2.44,2.44,0,0,0,62,25.28L48.2,11.43a2.38,2.38,0,0,0-1.53-.71H35.45a16.12,16.12,0,0,1,.44,3.5H45v9.26a5,5,0,0,0,5,5h9.15V65.41A2.16,2.16,0,0,1,57,67.57H21.8a2.16,2.16,0,0,1-2.15-2.16V31.46H19a16.81,16.81,0,0,1-2.86-.24V65.41a5.67,5.67,0,0,0,5.65,5.66H57a5.67,5.67,0,0,0,5.66-5.66V27A1.48,1.48,0,0,0,62.64,26.77ZM50,25a1.49,1.49,0,0,1-1.49-1.49V16.71L56.69,25Z"/><path class="cls-1" d="M48,11.23a1.75,1.75,0,0,0-1.34-.51,2.38,2.38,0,0,1,1.53.71ZM62.14,25.47,62,25.28a2.44,2.44,0,0,1,.69,1.46A1.71,1.71,0,0,0,62.14,25.47Z"/><path class="cls-2" d="M17.26,12.83V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Z"/><path class="cls-2" d="M17.26,12.83V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Zm0,0V13a1.33,1.33,0,0,1,.14-.19Z"/><path class="cls-1" d="M32.65,14.21a13.47,13.47,0,0,0-.55-3.5,13.66,13.66,0,1,0-16,17.23,13.47,13.47,0,0,0,2.86.3c.22,0,.43,0,.64,0a13.67,13.67,0,0,0,13-13.64C32.66,14.46,32.66,14.33,32.65,14.21Zm-13,10.51-.64,0a9.94,9.94,0,0,1-2.86-.41A10.15,10.15,0,1,1,28.39,10.71a9.92,9.92,0,0,1,.76,3.5c0,.12,0,.25,0,.37A10.17,10.17,0,0,1,19.65,24.72Z"/><path class="cls-1" d="M25,12.83v3.5H20.76v4.22h-3.5V16.33H13v-3.5h4.22V13a1.33,1.33,0,0,1,.14-.19h-.14V8.61h3.5v4.22Z"/><path class="cls-1" d="M17.4,12.83a1.33,1.33,0,0,0-.14.19v-.19Z"/><path class="cls-1" d="M17.4,12.83a1.33,1.33,0,0,0-.14.19v-.19Z"/><rect class="cls-1" x="27.4" y="35.38" width="22" height="3.5"/><rect class="cls-1" x="27.4" y="55.38" width="22" height="3.5"/><rect class="cls-1" x="27.4" y="45.38" width="16" height="3.5"/></svg> \ No newline at end of file
diff --git a/packages/website/public/images/developers/tutorials/build_a_relayer.svg b/packages/website/public/images/developers/tutorials/build_a_relayer.svg
new file mode 100644
index 000000000..afda40d88
--- /dev/null
+++ b/packages/website/public/images/developers/tutorials/build_a_relayer.svg
@@ -0,0 +1,3 @@
+<svg width="76" height="76" viewBox="0 0 76 76" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M70.0766 46.9825C70.3778 45.294 70.4782 43.6054 70.4782 41.8174C70.4782 30.8913 64.9564 20.8591 55.72 14.8993C54.8164 14.3034 53.712 14.6013 53.1096 15.4953C52.5073 16.3892 52.8085 17.4819 53.6116 18.0778C61.8441 23.3423 66.6631 32.2819 66.6631 41.9168C66.6631 43.208 66.5627 44.4993 66.362 45.7906C65.7596 45.6913 65.0568 45.592 64.4544 45.592C58.1295 45.592 52.9089 50.6577 52.9089 57.0148C52.9089 63.3718 58.0291 68.4376 64.4544 68.4376C70.8798 68.4376 76 63.3718 76 57.0148C76 52.6443 73.5905 48.9691 70.0766 46.9825ZM64.4544 64.6631C60.1374 64.6631 56.7239 61.1866 56.7239 57.0148C56.7239 52.7436 60.2378 49.3664 64.4544 49.3664C68.7715 49.3664 72.1849 52.843 72.1849 57.0148C72.2853 61.1866 68.7715 64.6631 64.4544 64.6631ZM50.3989 67.5436C46.4835 69.4309 42.2668 70.3248 37.9498 70.3248C31.5244 70.3248 25.2999 68.2389 20.2801 64.2658C21.9868 62.2792 23.0912 59.6966 23.0912 56.8161C23.0912 50.5584 17.9709 45.3933 11.5456 45.3933C5.22061 45.3933 6.1277e-06 50.4591 6.1277e-06 56.8161C6.1277e-06 63.1731 5.12022 68.2389 11.5456 68.2389C13.6539 68.2389 15.5614 67.6429 17.2682 66.6497C23.0912 71.4174 30.3197 74 37.8494 74C42.7688 74 47.4875 72.9074 51.9049 70.8215C52.8085 70.4242 53.21 69.2322 52.8085 68.3383C52.5073 67.5436 51.3025 67.1463 50.3989 67.5436ZM3.81505 56.9154C3.81505 52.6443 7.32894 49.2671 11.5456 49.2671C15.7622 49.2671 19.2761 52.7436 19.2761 56.9154C19.2761 61.1866 15.7622 64.5638 11.5456 64.5638C7.32894 64.5638 3.81505 61.1866 3.81505 56.9154ZM7.42933 42.5128C7.42933 42.5128 7.52972 42.5128 7.42933 42.5128C8.53369 42.5128 9.33685 41.7181 9.33685 40.7248C9.63804 31.0899 14.8586 22.349 23.1915 17.3826C24.3963 16.6873 25.6011 16.0913 26.8058 15.5946C28.5126 19.7664 32.6288 22.8456 37.5482 22.8456C43.8732 22.8456 49.0938 17.7799 49.0938 11.4228C49.0938 5.06578 43.9736 1.21251e-05 37.5482 1.21251e-05C31.2233 1.21251e-05 26.0026 5.06578 26.0026 11.4228C26.0026 11.6215 26.0026 11.7208 26.0026 11.9195C24.3963 12.6148 22.79 13.3101 21.1836 14.3034C11.7464 19.9651 5.92339 29.7987 5.5218 40.7248C5.6222 41.6188 6.42536 42.5128 7.42933 42.5128ZM37.5482 3.67516C41.8653 3.67516 45.2787 7.15168 45.2787 11.3235C45.2787 15.5946 41.7649 18.9718 37.5482 18.9718C33.2312 18.9718 29.8177 15.4953 29.8177 11.3235C29.8177 7.15168 33.3316 3.67516 37.5482 3.67516Z" fill="#3289F1"/>
+</svg>
diff --git a/packages/website/public/images/developers/tutorials/build_a_trading_bot.svg b/packages/website/public/images/developers/tutorials/build_a_trading_bot.svg
new file mode 100644
index 000000000..960616bfe
--- /dev/null
+++ b/packages/website/public/images/developers/tutorials/build_a_trading_bot.svg
@@ -0,0 +1,6 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M72 36.63C72 35.1978 71.4436 33.8243 70.4532 32.8116C69.4628 31.7989 68.1195 31.23 66.7188 31.23H65.6626V23.76C65.6626 21.8504 64.9207 20.0191 63.6002 18.6688C62.2796 17.3186 60.4886 16.56 58.621 16.56H37.7604V1.8C37.7604 1.32261 37.5749 0.864774 37.2448 0.527208C36.9146 0.189643 36.4669 0 36 0C35.5331 0 35.0854 0.189643 34.7552 0.527208C34.4251 0.864774 34.2396 1.32261 34.2396 1.8V16.56H13.379C11.5114 16.56 9.72038 17.3186 8.39983 18.6688C7.07929 20.0191 6.33741 21.8504 6.33741 23.76V31.23H5.28117C3.88052 31.23 2.53723 31.7989 1.54682 32.8116C0.556407 33.8243 3.35768e-07 35.1978 3.35768e-07 36.63V47.25C3.35768e-07 48.6822 0.556407 50.0557 1.54682 51.0684C2.53723 52.0811 3.88052 52.65 5.28117 52.65H6.33741V64.8C6.33741 66.7096 7.07929 68.5409 8.39983 69.8912C9.72038 71.2414 11.5114 72 13.379 72H58.621C60.4886 72 62.2796 71.2414 63.6002 69.8912C64.9207 68.5409 65.6626 66.7096 65.6626 64.8V52.65H66.7188C68.1195 52.65 69.4628 52.0811 70.4532 51.0684C71.4436 50.0557 72 48.6822 72 47.25V36.63ZM68.4792 47.25C68.4792 47.7274 68.2937 48.1852 67.9636 48.5228C67.6335 48.8604 67.1857 49.05 66.7188 49.05H63.9022C63.4353 49.05 62.9876 49.2396 62.6574 49.5772C62.3273 49.9148 62.1418 50.3726 62.1418 50.85V64.8C62.1418 65.7548 61.7709 66.6705 61.1106 67.3456C60.4503 68.0207 59.5548 68.4 58.621 68.4H13.379C12.4452 68.4 11.5497 68.0207 10.8894 67.3456C10.2291 66.6705 9.85819 65.7548 9.85819 64.8V50.85C9.85819 50.3726 9.67272 49.9148 9.34258 49.5772C9.01245 49.2396 8.56468 49.05 8.0978 49.05H5.28117C4.81429 49.05 4.36653 48.8604 4.03639 48.5228C3.70625 48.1852 3.52078 47.7274 3.52078 47.25V36.63C3.52078 36.1526 3.70625 35.6948 4.03639 35.3572C4.36653 35.0196 4.81429 34.83 5.28117 34.83H8.0978C8.56468 34.83 9.01245 34.6404 9.34258 34.3028C9.67272 33.9652 9.85819 33.5074 9.85819 33.03V23.76C9.85819 22.8052 10.2291 21.8895 10.8894 21.2144C11.5497 20.5393 12.4452 20.16 13.379 20.16H58.621C59.5548 20.16 60.4503 20.5393 61.1106 21.2144C61.7709 21.8895 62.1418 22.8052 62.1418 23.76V33.03C62.1418 33.5074 62.3273 33.9652 62.6574 34.3028C62.9876 34.6404 63.4353 34.83 63.9022 34.83H66.7188C67.1857 34.83 67.6335 35.0196 67.9636 35.3572C68.2937 35.6948 68.4792 36.1526 68.4792 36.63V47.25Z" fill="#3289F1"/>
+<path d="M32.2998 38.5204C32.2998 36.9718 31.8507 35.458 31.0092 34.1703C30.1678 32.8827 28.9718 31.8791 27.5726 31.2865C26.1733 30.6938 24.6336 30.5388 23.1481 30.8409C21.6627 31.143 20.2982 31.8887 19.2273 32.9838C18.1563 34.0788 17.427 35.474 17.1315 36.9929C16.836 38.5117 16.9877 40.0861 17.5673 41.5168C18.1469 42.9476 19.1284 44.1705 20.3877 45.0308C21.647 45.8912 23.1275 46.3504 24.6421 46.3504C26.673 46.3504 28.6208 45.5255 30.0569 44.0571C31.493 42.5887 32.2998 40.5971 32.2998 38.5204ZM24.6421 42.7504C24.0988 42.7504 23.5609 42.641 23.0589 42.4284C22.557 42.2159 22.101 41.9043 21.7168 41.5115C21.3327 41.1187 21.028 40.6524 20.8201 40.1392C20.6122 39.626 20.5052 39.0759 20.5052 38.5204C20.5052 37.3986 20.941 36.3226 21.7168 35.5294C22.4927 34.7361 23.5449 34.2904 24.6421 34.2904C25.7393 34.2904 26.7915 34.7361 27.5673 35.5294C28.3431 36.3226 28.779 37.3986 28.779 38.5204C28.779 39.6423 28.3431 40.7182 27.5673 41.5115C26.7915 42.3048 25.7393 42.7504 24.6421 42.7504Z" fill="#3289F1"/>
+<path d="M47.3533 30.6001C45.8177 30.5823 44.3116 31.0316 43.0263 31.8909C41.741 32.7503 40.7345 33.9809 40.1347 35.4264C39.5349 36.8719 39.3689 38.4671 39.6578 40.0093C39.9466 41.5515 40.6773 42.9711 41.757 44.0878C42.8367 45.2045 44.2166 45.9678 45.7215 46.2807C47.2264 46.5937 48.7882 46.4422 50.2087 45.8455C51.6292 45.2487 52.8442 44.2338 53.6992 42.9294C54.5543 41.6251 55.0109 40.0904 55.011 38.5201C55.0226 37.4843 54.8331 36.4565 54.4535 35.4961C54.0739 34.5357 53.5117 33.6618 52.7994 32.9252C52.0872 32.1886 51.2391 31.6037 50.3042 31.2046C49.3694 30.8055 48.3664 30.6001 47.3533 30.6001ZM47.3533 42.7501C46.2561 42.7501 45.2039 42.3045 44.428 41.5112C43.6522 40.7179 43.2164 39.642 43.2164 38.5201C43.2164 37.9646 43.3234 37.4146 43.5313 36.9014C43.7392 36.3882 44.0439 35.9218 44.428 35.5291C44.8122 35.1363 45.2682 34.8247 45.7701 34.6121C46.2721 34.3995 46.81 34.2901 47.3533 34.2901C47.8965 34.2901 48.4345 34.3995 48.9364 34.6121C49.4383 34.8247 49.8944 35.1363 50.2785 35.5291C50.6627 35.9218 50.9674 36.3882 51.1753 36.9014C51.3832 37.4146 51.4902 37.9646 51.4902 38.5201C51.4902 39.642 51.0543 40.7179 50.2785 41.5112C49.5027 42.3045 48.4505 42.7501 47.3533 42.7501Z" fill="#3289F1"/>
+<path d="M46.7424 55.7109H25.2656V59.3109H46.7424V55.7109Z" fill="#3289F1"/>
+</svg>
diff --git a/packages/website/public/images/developers/tutorials/develop_on_ethereum.svg b/packages/website/public/images/developers/tutorials/develop_on_ethereum.svg
new file mode 100644
index 000000000..e2c492ecd
--- /dev/null
+++ b/packages/website/public/images/developers/tutorials/develop_on_ethereum.svg
@@ -0,0 +1,4 @@
+<svg width="76" height="76" viewBox="0 0 76 76" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.0349 38.5774C14.0366 38.5844 14.0366 38.5914 14.0383 38.5975C14.0459 38.6273 14.0595 38.6553 14.0688 38.6842C14.079 38.7148 14.085 38.7463 14.0977 38.7761C14.1003 38.7813 14.1045 38.7848 14.1062 38.7901C14.1461 38.8802 14.1979 38.9625 14.2582 39.0387C14.2752 39.0597 14.293 39.0781 14.3109 39.0973C14.3627 39.1534 14.4187 39.2041 14.4816 39.2488C14.4994 39.2619 14.5164 39.2768 14.5351 39.289C14.5436 39.2943 14.5503 39.3013 14.5588 39.3065L36.3144 52.3229C36.4876 52.4262 36.6812 52.4779 36.874 52.4779C36.9173 52.4779 36.9589 52.4656 37.0014 52.4603C37.0439 52.4656 37.0863 52.4779 37.1288 52.4779C37.3224 52.4779 37.5152 52.4262 37.6884 52.3229L59.444 39.3065C59.703 39.1516 59.8898 38.896 59.9645 38.5975C60.0384 38.299 59.9934 37.9821 59.8389 37.7178L38.0859 0.552394C37.8659 0.177746 37.4642 -0.0148298 37.0515 0.014932C36.6065 -0.0594723 36.1564 0.147984 35.9195 0.552394L14.1631 37.7187C14.1487 37.7432 14.1402 37.7703 14.1274 37.7966C14.1087 37.8351 14.0884 37.8718 14.0739 37.9121C14.0629 37.9427 14.0569 37.9751 14.0476 38.0075C14.0366 38.0478 14.0247 38.0881 14.0179 38.1292C14.0128 38.1607 14.0128 38.1931 14.0102 38.2255C14.0068 38.2684 14.0026 38.3104 14.0043 38.3542C14.0051 38.3874 14.0111 38.4198 14.0153 38.4531C14.0213 38.4942 14.0247 38.5354 14.0349 38.5774ZM38.2455 5.27838L56.1991 35.9496L38.2455 27.7826V5.27838ZM38.2455 30.2957L56.3197 38.5179L38.2455 49.3319V30.2957ZM35.759 5.27838V27.6662L17.898 35.7912L35.759 5.27838ZM35.759 30.1802V49.331L17.5744 38.4522L35.759 30.1802Z" fill="#3289F1"/>
+<path d="M58.3132 42.4975L36.9993 55.5568L15.6854 42.4975C15.2327 42.2192 14.651 42.3076 14.2943 42.7076C13.9368 43.1085 13.9011 43.7125 14.2085 44.1546L35.9641 75.5182C36.1772 75.8263 36.5186 75.9996 36.8719 75.9996C36.9144 75.9996 36.9568 75.9839 36.9993 75.9786C37.0418 75.9839 37.0842 75.9996 37.1267 75.9996C37.48 75.9996 37.8205 75.8263 38.0345 75.5182L59.79 44.1546C60.0975 43.7125 60.0609 43.1085 59.7043 42.7076C59.3467 42.3076 58.7659 42.22 58.3132 42.4975ZM35.756 71.2649L19.1145 47.2743L35.756 57.4703V71.2649ZM38.2426 71.2649V57.4703L54.884 47.2743L38.2426 71.2649Z" fill="#3289F1"/>
+</svg>
diff --git a/packages/website/public/images/developers/tutorials/use_shared_liquidity.svg b/packages/website/public/images/developers/tutorials/use_shared_liquidity.svg
new file mode 100644
index 000000000..c402964aa
--- /dev/null
+++ b/packages/website/public/images/developers/tutorials/use_shared_liquidity.svg
@@ -0,0 +1,3 @@
+<svg width="70" height="74" viewBox="0 0 70 74" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M47.5152 52.7109C46.8864 53.3447 46.3452 54.0413 45.8772 54.7779L25.1416 42.092C25.69 40.7084 26.0008 39.2038 26.0008 37.6255C26.0008 36.0472 25.69 34.5426 25.1428 33.159L45.8832 20.5699C48.0132 23.9418 51.7475 26.1889 56.0002 26.1889C62.6169 26.1889 68 20.7634 68 14.0945C68 7.42558 62.6169 2 56.0002 2C49.3835 2 44.0004 7.42558 44.0004 14.0945C44.0004 15.6135 44.292 17.0625 44.8008 18.4025L24.0328 31.0086C21.8872 27.7141 18.1937 25.531 13.9998 25.531C7.3831 25.531 2 30.9566 2 37.6255C2 44.2944 7.3831 49.72 13.9998 49.72C18.1937 49.72 21.886 47.5369 24.0316 44.2424L44.796 56.9452C44.28 58.307 43.9992 59.762 43.9992 61.2629C43.9992 64.4934 45.2472 67.5315 47.514 69.8149C49.8527 72.1721 52.9259 73.3513 55.999 73.3513C59.0722 73.3513 62.1453 72.1721 64.4841 69.8149C66.7508 67.5303 67.9988 64.4934 67.9988 61.2629C67.9988 58.0325 66.7508 54.9944 64.4841 52.7109C59.8054 47.9941 52.1939 47.9941 47.5152 52.7109ZM56.0002 4.41889C61.2933 4.41889 65.6 8.7596 65.6 14.0945C65.6 19.4293 61.2933 23.7701 56.0002 23.7701C50.7071 23.7701 46.4004 19.4293 46.4004 14.0945C46.4004 8.7596 50.7059 4.41889 56.0002 4.41889ZM14.001 47.3011C8.70788 47.3011 4.40116 42.9604 4.40116 37.6255C4.40116 32.2906 8.70788 27.9499 14.001 27.9499C19.2941 27.9499 23.6008 32.2906 23.6008 37.6255C23.6008 42.9604 19.2941 47.3011 14.001 47.3011ZM62.7873 68.1048C59.0446 71.877 52.9547 71.877 49.2119 68.1048C47.3988 66.2773 46.4004 63.8463 46.4004 61.2629C46.4004 58.6795 47.3988 56.2486 49.2119 54.4211C51.0839 52.5343 53.5415 51.5922 56.0002 51.5922C58.459 51.5922 60.9165 52.5343 62.7885 54.4211C64.6017 56.2486 65.6 58.6795 65.6 61.2629C65.6 63.8463 64.6017 66.2773 62.7873 68.1048Z" fill="#3289F1" stroke="#3289F1" stroke-width="0.5"/>
+</svg>
diff --git a/packages/website/public/images/docs_logo.svg b/packages/website/public/images/docs_logo.svg
new file mode 100644
index 000000000..e3c4b628b
--- /dev/null
+++ b/packages/website/public/images/docs_logo.svg
@@ -0,0 +1,24 @@
+<svg width="278" height="72" viewBox="0 0 278 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="139" height="35.9999" fill="black" fill-opacity="0" transform="scale(2)"/>
+<rect width="74.0872" height="35.9999" fill="black" fill-opacity="0" transform="scale(2)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M115.234 33.6875L105.219 40.5522C105.477 44.3244 107.146 46.2101 110.226 46.2101C113.565 46.2101 115.234 43.9618 115.234 39.4642V33.6875ZM105.176 36.8338L115.191 29.9691C115.076 28.0041 114.607 26.5499 113.783 25.6069C112.959 24.6642 111.759 24.1924 110.183 24.1924C108.507 24.1924 107.253 24.7398 106.422 25.8345C105.591 26.9293 105.176 28.6109 105.176 30.8789V36.8338ZM120.394 38.6336C120.394 40.4934 120.16 42.1322 119.695 43.5498C119.229 44.9677 118.559 46.1546 117.686 47.1106C116.812 48.067 115.744 48.7892 114.483 49.277C113.222 49.7647 111.804 50.0089 110.228 50.0089C108.666 50.0089 107.255 49.7647 105.994 49.277C104.733 48.7892 103.662 48.067 102.781 47.1106C101.9 46.1546 101.22 44.9677 100.74 43.5498C100.259 42.1322 100.02 40.4934 100.02 38.6336V31.7491C100.02 29.8895 100.256 28.2511 100.729 26.8332C101.202 25.4156 101.879 24.2285 102.76 23.2721C103.641 22.3161 104.708 21.5941 105.962 21.1059C107.215 20.6182 108.623 20.374 110.185 20.374C111.761 20.374 113.179 20.6182 114.44 21.1059C115.701 21.5941 116.772 22.3161 117.653 23.2721C118.535 24.2285 119.212 25.4156 119.684 26.8332C120.157 28.2511 120.394 29.8895 120.394 31.7491V38.6336Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M137.01 35.3006L142.385 27.7822H147.925L139.968 38.7311L148.175 50.0084H142.655L137.073 42.2232L131.511 50.0084H125.949L134.156 38.7311L126.199 27.7822H131.719L137.01 35.3006Z" fill="black"/>
+<rect width="36" height="35.9999" fill="black" fill-opacity="0" transform="scale(2)"/>
+<rect width="22.5701" height="11.8348" fill="black" fill-opacity="0" transform="translate(18.0508 48.3301) scale(2)"/>
+<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="18" y="48" width="46" height="24">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0508 71.9997H63.191V48.3301H18.0508V71.9997Z" fill="white"/>
+</mask>
+<g mask="url(#mask0)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0508 67.1184C22.6601 69.8386 27.9385 71.5522 33.6161 71.9239C41.4577 72.4369 48.8759 70.3221 55.038 66.3361C58.1021 64.354 60.8534 61.9089 63.191 59.0905C61.2524 56.3622 59.1896 53.547 57.0111 50.6788L55.2311 48.3301C52.8884 52.0707 49.5201 55.0686 45.5555 56.9441L39.4742 50.9207L18.0508 67.1184Z" fill="black"/>
+</g>
+<rect width="11.6916" height="22.7346" fill="black" fill-opacity="0" transform="translate(0 18.6299) scale(2)"/>
+<mask id="mask1" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="18" width="24" height="47">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M0 18.6299V64.099H23.3833V18.6299L0 18.6299Z" fill="white"/>
+</mask>
+<g mask="url(#mask1)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.72039 18.6299C2.09283 23.2496 0.437543 28.5247 0.0749777 34.193C-0.432648 42.134 1.66198 49.6455 5.60982 55.8826C7.56303 58.9691 9.97065 61.7416 12.7445 64.099C15.4422 62.1375 18.2268 60.0505 21.0641 57.847L23.3833 56.0501C19.6922 53.6805 16.7332 50.2769 14.8817 46.271L20.8743 40.0586L4.72039 18.6299Z" fill="black"/>
+</g>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M54.0006 4.9803C49.4018 2.20541 44.1346 0.455949 38.4679 0.0772542C30.6434 -0.445638 23.2417 1.71125 17.096 5.77624C14.0546 7.78768 11.3231 10.2669 9 13.123C10.9328 15.9011 12.9892 18.7682 15.1602 21.69L16.9306 24.0783C19.2665 20.2759 22.622 17.2279 26.5714 15.3216L26.5759 15.3196L32.2882 21.07L54.0006 4.9803Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M67.3574 53.7131C69.9376 49.2175 71.5681 44.0992 71.9269 38.5992C72.4342 30.8203 70.3437 23.4613 66.4027 17.3486C64.4432 14.3092 62.0259 11.58 59.2397 9.26074C56.5427 11.1839 53.7595 13.2301 50.9238 15.3915L48.6016 17.1569C52.3061 19.4848 55.2749 22.8335 57.1283 26.7755L57.1639 26.8575L51.3951 32.7948L67.3574 53.7131Z" fill="black"/>
+<path d="M164.041 38.1836C164.041 34.6172 164.886 31.7526 166.576 29.5898C168.266 27.4128 170.479 26.3242 173.215 26.3242C175.936 26.3242 178.092 27.2552 179.682 29.1172V17H183.656V50H180.004L179.811 47.5078C178.221 49.4557 176.008 50.4297 173.172 50.4297C170.479 50.4297 168.281 49.3268 166.576 47.1211C164.886 44.9154 164.041 42.0365 164.041 38.4844V38.1836ZM168.016 38.6348C168.016 41.2702 168.56 43.3327 169.648 44.8223C170.737 46.3118 172.241 47.0566 174.16 47.0566C176.681 47.0566 178.521 45.9251 179.682 43.6621V32.9844C178.493 30.793 176.667 29.6973 174.203 29.6973C172.255 29.6973 170.737 30.4492 169.648 31.9531C168.56 33.457 168.016 35.6842 168.016 38.6348ZM188.791 38.1621C188.791 35.8848 189.235 33.8366 190.123 32.0176C191.025 30.1986 192.271 28.7949 193.861 27.8066C195.465 26.8184 197.292 26.3242 199.34 26.3242C202.505 26.3242 205.062 27.4199 207.01 29.6113C208.972 31.8027 209.953 34.7174 209.953 38.3555V38.6348C209.953 40.8978 209.516 42.9316 208.643 44.7363C207.783 46.5267 206.544 47.9232 204.926 48.9258C203.322 49.9284 201.474 50.4297 199.383 50.4297C196.232 50.4297 193.675 49.334 191.713 47.1426C189.765 44.9512 188.791 42.0508 188.791 38.4414V38.1621ZM192.787 38.6348C192.787 41.2129 193.382 43.2826 194.57 44.8438C195.773 46.4049 197.378 47.1855 199.383 47.1855C201.402 47.1855 203.007 46.3978 204.195 44.8223C205.384 43.2324 205.979 41.0124 205.979 38.1621C205.979 35.6126 205.37 33.5501 204.152 31.9746C202.949 30.3848 201.345 29.5898 199.34 29.5898C197.378 29.5898 195.795 30.3704 194.592 31.9316C193.389 33.4928 192.787 35.7272 192.787 38.6348ZM224.262 47.1855C225.68 47.1855 226.919 46.7559 227.979 45.8965C229.038 45.0371 229.626 43.9629 229.74 42.6738H233.5C233.428 44.0059 232.97 45.2734 232.125 46.4766C231.28 47.6797 230.148 48.6393 228.73 49.3555C227.327 50.0716 225.837 50.4297 224.262 50.4297C221.096 50.4297 218.576 49.377 216.699 47.2715C214.837 45.1517 213.906 42.2585 213.906 38.5918V37.9258C213.906 35.6628 214.322 33.6504 215.152 31.8887C215.983 30.127 217.172 28.7591 218.719 27.7852C220.28 26.8112 222.12 26.3242 224.24 26.3242C226.847 26.3242 229.01 27.1048 230.729 28.666C232.462 30.2272 233.385 32.2539 233.5 34.7461H229.74C229.626 33.2422 229.053 32.0104 228.021 31.0508C227.005 30.0768 225.744 29.5898 224.24 29.5898C222.221 29.5898 220.652 30.3203 219.535 31.7812C218.432 33.2279 217.881 35.3262 217.881 38.0762V38.8281C217.881 41.5065 218.432 43.569 219.535 45.0156C220.638 46.4622 222.214 47.1855 224.262 47.1855ZM251.504 43.834C251.504 42.7598 251.096 41.929 250.279 41.3418C249.477 40.7402 248.066 40.2246 246.047 39.7949C244.042 39.3652 242.445 38.8496 241.256 38.248C240.081 37.6465 239.208 36.9303 238.635 36.0996C238.076 35.2689 237.797 34.2806 237.797 33.1348C237.797 31.2298 238.599 29.6185 240.203 28.3008C241.822 26.9831 243.884 26.3242 246.391 26.3242C249.026 26.3242 251.16 27.0046 252.793 28.3652C254.44 29.7259 255.264 31.4661 255.264 33.5859H251.268C251.268 32.4974 250.802 31.5592 249.871 30.7715C248.954 29.9837 247.794 29.5898 246.391 29.5898C244.944 29.5898 243.812 29.9049 242.996 30.5352C242.18 31.1654 241.771 31.9889 241.771 33.0059C241.771 33.9655 242.151 34.6888 242.91 35.1758C243.669 35.6628 245.037 36.1283 247.014 36.5723C249.005 37.0163 250.616 37.5462 251.848 38.1621C253.079 38.778 253.989 39.5228 254.576 40.3965C255.178 41.2559 255.479 42.3086 255.479 43.5547C255.479 45.6315 254.648 47.3001 252.986 48.5605C251.325 49.8066 249.169 50.4297 246.52 50.4297C244.658 50.4297 243.01 50.1003 241.578 49.4414C240.146 48.7826 239.021 47.8659 238.205 46.6914C237.403 45.5026 237.002 44.2207 237.002 42.8457H240.977C241.048 44.1777 241.578 45.2376 242.566 46.0254C243.569 46.7988 244.887 47.1855 246.52 47.1855C248.023 47.1855 249.227 46.8848 250.129 46.2832C251.046 45.6673 251.504 44.8509 251.504 43.834Z" fill="#666666"/>
+</svg>
diff --git a/packages/website/translations/chinese.json b/packages/website/translations/chinese.json
index ed1a6044a..2d3ad6974 100644
--- a/packages/website/translations/chinese.json
+++ b/packages/website/translations/chinese.json
@@ -78,5 +78,24 @@
"WEBSITE": "网站",
"DEVELOPERS": "首页",
"HOME": "Rocket.chat",
- "ROCKETCHAT": "开发人员"
+ "ROCKETCHAT": "开发人员",
+ "BUILD_A_RELAYER": "build a relayer",
+ "BUILD_A_RELAYER_DESCRIPTION": "Learn more about building applications ontop of Ethereum",
+ "DEVELOP_ON_ETHEREUM": "develop on Ethereum",
+ "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn how to build your own 0x relayer from scratch",
+ "ORDER_BASICS": "0x order basics",
+ "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x",
+ "USE_SHARED_LIQUIDITY": "use shared liquidity",
+ "USE_SHARED_LIQUIDITY_DESCRIPTION": "Access the shared liquidity pool using the Standard Relayer API",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github",
+ "LIVE_CHAT": "live chat",
+ "LIBRARIES_AND_TOOLS": "Libraries & Tools",
+ "LIBRARIES_AND_TOOLS_DESCRIPTION":
+ "A list of available tools maintained by the 0x core developers and wider community for building on top of 0x Protocol and Ethereum",
+ "MORE": "more",
+ "START_BUILDING_ON_0X": "Start building on 0x",
+ "START_BUILDING_ON_0X_DESCRIPTION":
+ "Follow one of our \"Getting started\" guides to learn more about building ontop of 0x."
}
diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json
index ac8e4900a..fab8ed56b 100644
--- a/packages/website/translations/english.json
+++ b/packages/website/translations/english.json
@@ -83,11 +83,30 @@
"HOME": "home",
"ROCKETCHAT": "rocket.chat",
"TRADE_CALL_TO_ACTION": "trade on 0x",
+ "BUILD_A_RELAYER": "build a relayer",
+ "BUILD_A_RELAYER_DESCRIPTION": "Learn more about building applications ontop of Ethereum",
+ "DEVELOP_ON_ETHEREUM": "develop on Ethereum",
+ "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn how to build your own 0x relayer from scratch",
+ "ORDER_BASICS": "0x order basics",
+ "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x",
+ "USE_SHARED_LIQUIDITY": "use shared liquidity",
+ "USE_SHARED_LIQUIDITY_DESCRIPTION": "Learn how to tap into shared liquidity using the Standard Relayer API",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github",
+ "LIVE_CHAT": "live chat",
+ "LIBRARIES_AND_TOOLS": "Libraries & Tools",
+ "LIBRARIES_AND_TOOLS_DESCRIPTION":
+ "A list of available tools maintained by the 0x core developers and wider community for building on top of 0x Protocol and Ethereum",
+ "MORE": "more",
"OUR_MISSION_AND_VALUES": "our mission & values",
"GAMING_AND_COLLECTABLES": "gaming & collectables",
"GAMING_AND_COLLECTABLES_DESCRIPTION":
"artists and game makers are tokenizing digital art and in-game items known as non-fungible tokens (NFTs). 0x enables these creators to add exchange functionality to give access and the ability to build marketplaces for NFT trading.",
"ORDER_BOOKS": "order books",
"ORDER_BOOKS_DESCRIPTION":
- "there are thousands of decentralized apps that have native utility tokens. 0x provides market makers and professional exchanges an ability to host order books to facilitate the exchange of these assets."
+ "there are thousands of decentralized apps that have native utility tokens. 0x provides market makers and professional exchanges an ability to host order books to facilitate the exchange of these assets.",
+ "START_BUILDING_ON_0X": "Start building on 0x",
+ "START_BUILDING_ON_0X_DESCRIPTION":
+ "Follow one of our \"Getting started\" guides to learn more about building ontop of 0x."
}
diff --git a/packages/website/translations/korean.json b/packages/website/translations/korean.json
index 8892f2dee..8470bf9a0 100644
--- a/packages/website/translations/korean.json
+++ b/packages/website/translations/korean.json
@@ -78,5 +78,24 @@
"WEBSITE": "Website",
"HOME": "홈",
"ROCKETCHAT": "Rocket.chat",
- "DEVELOPERS": "개발자"
+ "DEVELOPERS": "개발자",
+ "BUILD_A_RELAYER": "build a relayer",
+ "BUILD_A_RELAYER_DESCRIPTION": "Learn more about building applications ontop of Ethereum",
+ "DEVELOP_ON_ETHEREUM": "develop on Ethereum",
+ "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn how to build your own 0x relayer from scratch",
+ "ORDER_BASICS": "0x order basics",
+ "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x",
+ "USE_SHARED_LIQUIDITY": "use shared liquidity",
+ "USE_SHARED_LIQUIDITY_DESCRIPTION": "Learn how to tap into shared liquidity using the Standard Relayer API",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github",
+ "LIVE_CHAT": "live chat",
+ "LIBRARIES_AND_TOOLS": "Libraries & Tools",
+ "LIBRARIES_AND_TOOLS_DESCRIPTION":
+ "A list of available tools maintained by the 0x core developers and wider community for building on top of 0x Protocol and Ethereum",
+ "MORE": "more",
+ "START_BUILDING_ON_0X": "Start building on 0x",
+ "START_BUILDING_ON_0X_DESCRIPTION":
+ "Follow one of our \"Getting started\" guides to learn more about building ontop of 0x."
}
diff --git a/packages/website/translations/russian.json b/packages/website/translations/russian.json
index 41a7a990d..b2bc151ab 100644
--- a/packages/website/translations/russian.json
+++ b/packages/website/translations/russian.json
@@ -78,5 +78,24 @@
"WEBSITE": "Веб-сайт",
"DEVELOPERS": "Домашняя страница",
"HOME": "Rocket.chat",
- "ROCKETCHAT": "Для разработчиков"
+ "ROCKETCHAT": "Для разработчиков",
+ "BUILD_A_RELAYER": "build a relayer",
+ "BUILD_A_RELAYER_DESCRIPTION": "Learn more about building applications ontop of Ethereum",
+ "DEVELOP_ON_ETHEREUM": "develop on Ethereum",
+ "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn how to build your own 0x relayer from scratch",
+ "ORDER_BASICS": "0x order basics",
+ "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x",
+ "USE_SHARED_LIQUIDITY": "use shared liquidity",
+ "USE_SHARED_LIQUIDITY_DESCRIPTION": "Learn how to tap into shared liquidity using the Standard Relayer API",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github",
+ "LIVE_CHAT": "live chat",
+ "LIBRARIES_AND_TOOLS": "Libraries & Tools",
+ "LIBRARIES_AND_TOOLS_DESCRIPTION":
+ "A list of available tools maintained by the 0x core developers and wider community for building on top of 0x Protocol and Ethereum",
+ "MORE": "more",
+ "START_BUILDING_ON_0X": "Start building on 0x",
+ "START_BUILDING_ON_0X_DESCRIPTION":
+ "Follow one of our \"Getting started\" guides to learn more about building ontop of 0x."
}
diff --git a/packages/website/translations/spanish.json b/packages/website/translations/spanish.json
index 7780190ac..fefb92447 100644
--- a/packages/website/translations/spanish.json
+++ b/packages/website/translations/spanish.json
@@ -79,5 +79,24 @@
"WEBSITE": "website",
"DEVELOPERS": "inicio",
"HOME": "rocket.chat",
- "ROCKETCHAT": "desarrolladores"
+ "ROCKETCHAT": "desarrolladores",
+ "BUILD_A_RELAYER": "build a relayer",
+ "BUILD_A_RELAYER_DESCRIPTION": "Learn more about building applications ontop of Ethereum",
+ "DEVELOP_ON_ETHEREUM": "develop on Ethereum",
+ "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn how to build your own 0x relayer from scratch",
+ "ORDER_BASICS": "0x order basics",
+ "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x",
+ "USE_SHARED_LIQUIDITY": "use shared liquidity",
+ "USE_SHARED_LIQUIDITY_DESCRIPTION": "Learn how to tap into shared liquidity using the Standard Relayer API",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github",
+ "LIVE_CHAT": "live chat",
+ "LIBRARIES_AND_TOOLS": "Libraries & Tools",
+ "LIBRARIES_AND_TOOLS_DESCRIPTION":
+ "A list of available tools maintained by the 0x core developers and wider community for building on top of 0x Protocol and Ethereum",
+ "MORE": "more",
+ "START_BUILDING_ON_0X": "Start building on 0x",
+ "START_BUILDING_ON_0X_DESCRIPTION":
+ "Follow one of our \"Getting started\" guides to learn more about building ontop of 0x."
}
diff --git a/packages/website/ts/components/documentation/docs_logo.tsx b/packages/website/ts/components/documentation/docs_logo.tsx
new file mode 100644
index 000000000..b727fea36
--- /dev/null
+++ b/packages/website/ts/components/documentation/docs_logo.tsx
@@ -0,0 +1,20 @@
+import { Link } from '@0xproject/react-shared';
+import * as React from 'react';
+import { WebsitePaths } from 'ts/types';
+
+export interface DocsLogoProps {
+ height: number;
+ containerStyle?: React.CSSProperties;
+}
+
+export const DocsLogo: React.StatelessComponent<DocsLogoProps> = props => {
+ return (
+ <Link to={WebsitePaths.Docs}>
+ <img src="/images/docs_logo.svg" height={props.height} />
+ </Link>
+ );
+};
+
+DocsLogo.defaultProps = {
+ containerStyle: {},
+};
diff --git a/packages/website/ts/components/documentation/docs_top_bar.tsx b/packages/website/ts/components/documentation/docs_top_bar.tsx
new file mode 100644
index 000000000..9a9b9a616
--- /dev/null
+++ b/packages/website/ts/components/documentation/docs_top_bar.tsx
@@ -0,0 +1,108 @@
+import { ALink, colors, Link } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import Drawer from 'material-ui/Drawer';
+import * as React from 'react';
+import { DocsLogo } from 'ts/components/documentation/docs_logo';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { Deco, Key, ScreenWidths } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { Translate } from 'ts/utils/translate';
+
+export interface DocsTopBarProps {
+ location: Location;
+ screenWidth: ScreenWidths;
+ translate: Translate;
+ sidebar?: React.ReactNode;
+}
+
+interface DocsTopBarState {
+ isDrawerOpen: boolean;
+}
+
+export class DocsTopBar extends React.Component<DocsTopBarProps, DocsTopBarState> {
+ constructor(props: DocsTopBarProps) {
+ super(props);
+ this.state = {
+ isDrawerOpen: false,
+ };
+ }
+ public componentWillReceiveProps(nextProps: DocsTopBarProps): void {
+ if (nextProps.location.pathname !== this.props.location.pathname) {
+ this.setState({
+ isDrawerOpen: false,
+ });
+ }
+ }
+ public render(): React.ReactNode {
+ return (
+ <Container height={80}>
+ <Container
+ className="flex items-center lg-pt3 md-pt3 sm-pt1 lg-mt1 md-mt1 sm-mt0 lg-justify-end md-justify-end sm-justify-start"
+ width="100%"
+ >
+ <Container className="sm-hide xs-hide">
+ <Container className="flex items-center justify-between right" width="300px">
+ {this._renderMenuItems(constants.DEVELOPER_TOPBAR_LINKS)}
+ </Container>
+ </Container>
+ <Container className="lg-hide md-hide">
+ <Container paddingTop="6px">
+ <DocsLogo height={30} />
+ </Container>
+ </Container>
+ <Container className="md-hide lg-hide absolute" right="18px" top="12px">
+ <i
+ className="zmdi zmdi-menu"
+ style={{
+ color: colors.grey700,
+ fontSize: 30,
+ cursor: 'pointer',
+ }}
+ onClick={this._onMenuButtonClick.bind(this)}
+ />
+ </Container>
+ </Container>
+ <Container width={'100%'} height={'1px'} backgroundColor={colors.grey300} marginTop={'13px'} />
+ {this.props.screenWidth === ScreenWidths.Sm && this._renderDrawer()}
+ </Container>
+ );
+ }
+ private _renderMenuItems(menuItemLinks: ALink[]): React.ReactNode {
+ const menuItems = _.map(menuItemLinks, menuItemInfo => {
+ return (
+ <Link
+ key={`menu-item-${menuItemInfo.title}`}
+ to={menuItemInfo.to}
+ shouldOpenInNewTab={menuItemInfo.shouldOpenInNewTab}
+ >
+ <Container className="flex items-center" paddingLeft="4px">
+ <Text fontSize="16px" fontColor={colors.lightLinkBlue} fontWeight="bold">
+ {this.props.translate.get(menuItemInfo.title as Key, Deco.Cap)}
+ </Text>
+ </Container>
+ </Link>
+ );
+ });
+ return menuItems;
+ }
+ private _renderDrawer(): React.ReactNode {
+ return (
+ <Drawer
+ open={this.state.isDrawerOpen}
+ docked={false}
+ openSecondary={true}
+ onRequestChange={this._onMenuButtonClick.bind(this)}
+ >
+ <Container className="clearfix pl1 pt2" onClick={this._onMenuButtonClick.bind(this)}>
+ {this.props.sidebar}
+ </Container>
+ </Drawer>
+ );
+ }
+ private _onMenuButtonClick(): void {
+ this.setState({
+ isDrawerOpen: !this.state.isDrawerOpen,
+ });
+ }
+}
diff --git a/packages/website/ts/components/documentation/overview_content.tsx b/packages/website/ts/components/documentation/overview_content.tsx
new file mode 100644
index 000000000..6999e039a
--- /dev/null
+++ b/packages/website/ts/components/documentation/overview_content.tsx
@@ -0,0 +1,134 @@
+import { colors, Link, MarkdownLinkBlock, utils as sharedUtils } from '@0xproject/react-shared';
+import { ObjectMap } from '@0xproject/types';
+import * as _ from 'lodash';
+import * as React from 'react';
+import * as ReactMarkdown from 'react-markdown';
+import { Element as ScrollElement } from 'react-scroll';
+import { TutorialButton } from 'ts/components/documentation/tutorial_button';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { Deco, Key, Package, TutorialInfo } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+
+export interface OverviewContentProps {
+ translate: Translate;
+ tutorials: TutorialInfo[];
+ categoryToPackages: ObjectMap<Package[]>;
+}
+
+export interface OverviewContentState {}
+
+export class OverviewContent extends React.Component<OverviewContentProps, OverviewContentState> {
+ public render(): React.ReactNode {
+ return (
+ <Container>
+ {this._renderSectionTitle(this.props.translate.get(Key.StartBuildOn0x, Deco.Cap))}
+ <Container paddingTop="12px">
+ {this._renderSectionDescription(this.props.translate.get(Key.StartBuildOn0xDescription, Deco.Cap))}
+ <Container marginTop="36px">
+ {_.map(this.props.tutorials, tutorialInfo => (
+ <ScrollElement
+ name={sharedUtils.getIdFromName(
+ this.props.translate.get(tutorialInfo.link.title as Key, Deco.Cap),
+ )}
+ key={`tutorial-${tutorialInfo.link.title}`}
+ >
+ <TutorialButton translate={this.props.translate} tutorialInfo={tutorialInfo} />
+ </ScrollElement>
+ ))}
+ </Container>
+ </Container>
+ <Container marginTop="32px" paddingBottom="100px">
+ {this._renderSectionTitle(this.props.translate.get(Key.LibrariesAndTools, Deco.CapWords))}
+ <Container paddingTop="12px">
+ {this._renderSectionDescription(
+ this.props.translate.get(Key.LibrariesAndToolsDescription, Deco.Cap),
+ )}
+ <Container marginTop="36px">
+ {_.map(this.props.categoryToPackages, (pkgs, category) =>
+ this._renderPackageCategory(category, pkgs),
+ )}
+ </Container>
+ </Container>
+ </Container>
+ </Container>
+ );
+ }
+ private _renderPackageCategory(category: string, pkgs: Package[]): React.ReactNode {
+ return (
+ <Container key={`category-${category}`}>
+ <Text fontSize="18px">{category}</Text>
+ <Container>{_.map(pkgs, pkg => this._renderPackage(pkg))}</Container>
+ </Container>
+ );
+ }
+ private _renderPackage(pkg: Package): React.ReactNode {
+ const id = sharedUtils.getIdFromName(pkg.link.title);
+ return (
+ <ScrollElement name={id} key={`package-${pkg.link.title}`}>
+ <Container className="pb2">
+ <Container width="100%" height="1px" backgroundColor={colors.grey300} marginTop="11px" />
+ <Container className="clearfix mt2 pt1">
+ <Container className="md-col lg-col md-col-4 lg-col-4">
+ <Link
+ to={pkg.link.to}
+ fontColor={colors.lightLinkBlue}
+ shouldOpenInNewTab={!!pkg.link.shouldOpenInNewTab}
+ >
+ <Text Tag="div" fontColor={colors.lightLinkBlue} fontWeight="bold">
+ {pkg.link.title}
+ </Text>
+ </Link>
+ </Container>
+ <Container className="md-col lg-col md-col-6 lg-col-6 sm-py2">
+ <Text fontColor={colors.grey700}>
+ <ReactMarkdown
+ source={pkg.description}
+ renderers={{
+ link: MarkdownLinkBlock,
+ paragraph: 'span',
+ }}
+ />
+ </Text>
+ </Container>
+ <Container className="md-col lg-col md-col-2 lg-col-2 sm-pb2 relative">
+ <Container position="absolute" right="0px">
+ <Link
+ to={pkg.link.to}
+ fontColor={colors.lightLinkBlue}
+ shouldOpenInNewTab={!!pkg.link.shouldOpenInNewTab}
+ >
+ <Container className="flex">
+ <Container>{this.props.translate.get(Key.More, Deco.Cap)}</Container>
+ <Container paddingTop="1px" paddingLeft="6px">
+ <i
+ className="zmdi zmdi-chevron-right bold"
+ style={{ fontSize: 18, color: colors.lightLinkBlue }}
+ />
+ </Container>
+ </Container>
+ </Link>
+ </Container>
+ </Container>
+ </Container>
+ </Container>
+ </ScrollElement>
+ );
+ }
+ private _renderSectionTitle(text: string): React.ReactNode {
+ return (
+ <Container paddingTop="30px">
+ <Text fontColor={colors.projectsGrey} fontSize="30px" fontWeight="bold">
+ {text}
+ </Text>
+ </Container>
+ );
+ }
+ private _renderSectionDescription(text: string): React.ReactNode {
+ return (
+ <Text fontColor={colors.linkSectionGrey} fontSize="16px" fontFamily="Roboto Mono">
+ {text}
+ </Text>
+ );
+ }
+} // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/components/documentation/sidebar_header.tsx b/packages/website/ts/components/documentation/sidebar_header.tsx
new file mode 100644
index 000000000..ec0ada8bd
--- /dev/null
+++ b/packages/website/ts/components/documentation/sidebar_header.tsx
@@ -0,0 +1,57 @@
+import { colors } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import { VersionDropDown } from 'ts/components/documentation/version_drop_down';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { ScreenWidths } from 'ts/types';
+
+export interface SidebarHeaderProps {
+ screenWidth: ScreenWidths;
+ title: string;
+ docsVersion?: string;
+ availableDocVersions?: string[];
+ onVersionSelected?: () => void;
+}
+
+export const SidebarHeader: React.StatelessComponent<SidebarHeaderProps> = ({
+ screenWidth,
+ title,
+ docsVersion,
+ availableDocVersions,
+ onVersionSelected,
+}) => {
+ return (
+ <Container>
+ <Container className="flex justify-bottom">
+ <Container className="left pl1" width="150px">
+ <Text
+ fontColor={colors.lightLinkBlue}
+ fontSize={screenWidth === ScreenWidths.Sm ? '20px' : '22px'}
+ fontWeight="bold"
+ >
+ {title}
+ </Text>
+ </Container>
+ {!_.isUndefined(docsVersion) &&
+ !_.isUndefined(availableDocVersions) &&
+ !_.isUndefined(onVersionSelected) && (
+ <div className="right" style={{ alignSelf: 'flex-end' }}>
+ <VersionDropDown
+ selectedVersion={docsVersion}
+ versions={availableDocVersions}
+ onVersionSelected={onVersionSelected}
+ />
+ </div>
+ )}
+ </Container>
+ <Container
+ width={'100%'}
+ height={'1px'}
+ backgroundColor={colors.grey300}
+ marginTop="20px"
+ marginBottom="27px"
+ />
+ </Container>
+ );
+};
diff --git a/packages/website/ts/components/documentation/tutorial_button.tsx b/packages/website/ts/components/documentation/tutorial_button.tsx
new file mode 100644
index 000000000..dc00bf743
--- /dev/null
+++ b/packages/website/ts/components/documentation/tutorial_button.tsx
@@ -0,0 +1,59 @@
+import { colors, Link } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { Deco, Key, TutorialInfo } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+
+import { styled } from 'ts/style/theme';
+
+export interface TutorialButtonProps {
+ className?: string;
+ translate: Translate;
+ tutorialInfo: TutorialInfo;
+}
+
+const PlainTutorialButton: React.StatelessComponent<TutorialButtonProps> = ({ translate, tutorialInfo, className }) => (
+ <Container className={className}>
+ <Link to={tutorialInfo.link.to} shouldOpenInNewTab={tutorialInfo.link.shouldOpenInNewTab}>
+ <div className="flex relative">
+ <div className="col col-1 flex items-center sm-pr3">
+ <img src={tutorialInfo.iconUrl} height={40} />
+ </div>
+ <div className="lg-pl2 md-pl2 sm-pl3 col col-10">
+ <Text Tag="div" fontSize="18" fontColor={colors.lightLinkBlue} fontWeight="bold">
+ {translate.get(tutorialInfo.link.title as Key, Deco.Cap)}
+ </Text>
+ <Text Tag="div" fontColor={colors.grey750} fontSize="16">
+ {translate.get(tutorialInfo.description as Key, Deco.Cap)}
+ </Text>
+ </div>
+ <div className="col col-1 flex items-center justify-end">
+ <div className="right">
+ <i
+ className="zmdi zmdi-chevron-right bold"
+ style={{ fontSize: 26, color: colors.lightLinkBlue }}
+ />
+ </div>
+ </div>
+ </div>
+ </Link>
+ </Container>
+);
+
+export const TutorialButton = styled(PlainTutorialButton)`
+ border-radius: 4px;
+ border: 1px solid ${colors.grey325};
+ background-color: ${colors.white};
+ &:hover {
+ border: 1px solid ${colors.lightLinkBlue};
+ background-color: ${colors.lightestBlue};
+ }
+ padding: 20px;
+ margin-bottom: 15px;
+`;
+
+TutorialButton.defaultProps = {};
+
+TutorialButton.displayName = 'TutorialButton';
diff --git a/packages/website/ts/components/documentation/version_drop_down.tsx b/packages/website/ts/components/documentation/version_drop_down.tsx
new file mode 100644
index 000000000..ec1c99f7b
--- /dev/null
+++ b/packages/website/ts/components/documentation/version_drop_down.tsx
@@ -0,0 +1,80 @@
+import { colors } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import { Button } from 'ts/components/ui/button';
+import { Container } from 'ts/components/ui/container';
+import { DropDown, DropdownMouseEvent } from 'ts/components/ui/drop_down';
+import { Text } from 'ts/components/ui/text';
+import { styled } from 'ts/style/theme';
+
+interface ActiveNodeProps {
+ className?: string;
+ selectedVersion: string;
+}
+
+const PlainActiveNode: React.StatelessComponent<ActiveNodeProps> = ({ className, selectedVersion }) => (
+ <Container className={className}>
+ <Container className="flex justify-center">
+ <Text fontColor={colors.grey700} fontSize="12px">
+ v {selectedVersion}
+ </Text>
+ <Container paddingLeft="6px">
+ <i className="zmdi zmdi-chevron-down" style={{ fontSize: 17, color: 'rgba(153, 153, 153, 0.8)' }} />
+ </Container>
+ </Container>
+ </Container>
+);
+
+const ActiveNode = styled(PlainActiveNode)`
+ cursor: pointer;
+ border: 2px solid ${colors.beigeWhite};
+ border-radius: 4px;
+ padding: 4px 6px 4px 8px;
+`;
+
+interface VersionDropDownProps {
+ selectedVersion: string;
+ versions: string[];
+ onVersionSelected: (semver: string) => void;
+}
+
+interface VersionDropDownState {}
+
+export class VersionDropDown extends React.Component<VersionDropDownProps, VersionDropDownState> {
+ public render(): React.ReactNode {
+ const activeNode = <ActiveNode selectedVersion={this.props.selectedVersion} />;
+ return (
+ <DropDown
+ activateEvent={DropdownMouseEvent.Click}
+ activeNode={activeNode}
+ popoverContent={this._renderDropdownMenu()}
+ anchorOrigin={{ horizontal: 'middle', vertical: 'bottom' }}
+ targetOrigin={{ horizontal: 'middle', vertical: 'top' }}
+ popoverStyle={{ borderRadius: 4 }}
+ />
+ );
+ }
+ private _renderDropdownMenu(): React.ReactNode {
+ const items = _.map(this.props.versions, version => {
+ const isSelected = version === this.props.selectedVersion;
+ return (
+ <Container key={`dropdown-items-${version}`}>
+ <Button
+ borderRadius="0px"
+ padding="0.8em 0em"
+ width="100%"
+ isDisabled={isSelected}
+ onClick={this._onClick.bind(this, version)}
+ >
+ v {version}
+ </Button>
+ </Container>
+ );
+ });
+ const dropdownMenu = <Container width="88px">{items}</Container>;
+ return dropdownMenu;
+ }
+ private _onClick(selectedVersion: string): void {
+ this.props.onVersionSelected(selectedVersion);
+ }
+}
diff --git a/packages/website/ts/components/dropdowns/developers_drop_down.tsx b/packages/website/ts/components/dropdowns/developers_drop_down.tsx
new file mode 100644
index 000000000..1db1e89b8
--- /dev/null
+++ b/packages/website/ts/components/dropdowns/developers_drop_down.tsx
@@ -0,0 +1,164 @@
+import { ALink, colors, Link } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { DropDown } from 'ts/components/ui/drop_down';
+import { Text } from 'ts/components/ui/text';
+import { Deco, Key, WebsitePaths } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { Translate } from 'ts/utils/translate';
+
+const gettingStartedKeyToLinkInfo1: ALink[] = [
+ {
+ title: Key.BuildARelayer,
+ to: `${WebsitePaths.Wiki}#Build-A-Relayer`,
+ },
+ {
+ title: Key.OrderBasics,
+ to: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`,
+ },
+];
+const gettingStartedKeyToLinkInfo2: ALink[] = [
+ {
+ title: Key.DevelopOnEthereum,
+ to: `${WebsitePaths.Wiki}#Ethereum-Development`,
+ },
+ {
+ title: Key.UseSharedLiquidity,
+ to: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`,
+ },
+];
+const popularDocsToLinkInfos: ALink[] = [
+ {
+ title: Key.ZeroExJs,
+ to: WebsitePaths.ZeroExJs,
+ },
+ {
+ title: Key.Connect,
+ to: WebsitePaths.Connect,
+ },
+ {
+ title: Key.SmartContract,
+ to: WebsitePaths.SmartContracts,
+ },
+];
+const usefulLinksToLinkInfo: ALink[] = [
+ {
+ title: Key.Wiki,
+ to: WebsitePaths.Wiki,
+ },
+ {
+ title: Key.Github,
+ to: constants.URL_GITHUB_ORG,
+ shouldOpenInNewTab: true,
+ },
+ {
+ title: Key.Whitepaper,
+ to: WebsitePaths.Whitepaper,
+ shouldOpenInNewTab: true,
+ },
+];
+
+interface DevelopersDropDownProps {
+ location: Location;
+ translate: Translate;
+ menuItemStyles: React.CSSProperties;
+ menuIconStyle: React.CSSProperties;
+}
+
+interface DevelopersDropDownState {}
+
+export class DevelopersDropDown extends React.Component<DevelopersDropDownProps, DevelopersDropDownState> {
+ public render(): React.ReactNode {
+ const activeNode = (
+ <Container className="flex relative" paddingRight="10">
+ <Text fontColor={this.props.menuIconStyle.color}>
+ {this.props.translate.get(Key.Developers, Deco.Cap)}
+ </Text>
+ </Container>
+ );
+ return (
+ <DropDown
+ activeNode={activeNode}
+ popoverContent={this._renderDropdownMenu()}
+ anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}
+ targetOrigin={{ horizontal: 'left', vertical: 'top' }}
+ style={this.props.menuItemStyles}
+ popoverStyle={{ borderRadius: 4, width: 397, height: 373, marginTop: 0 }}
+ />
+ );
+ }
+ private _renderDropdownMenu(): React.ReactNode {
+ const dropdownMenu = (
+ <Container>
+ <Container padding="1.75rem">
+ {this._renderTitle('Getting started')}
+ <Container className="flex">
+ <Container className="pr4 mr2">
+ {this._renderLinkSection(gettingStartedKeyToLinkInfo1)}
+ </Container>
+ <Container>{this._renderLinkSection(gettingStartedKeyToLinkInfo2)}</Container>
+ </Container>
+ </Container>
+ <Container width="100%" height="1px" backgroundColor={colors.grey300} />
+ <Container className="flex" padding="1.75rem">
+ <Container className="pr4 mr2">
+ <Container>{this._renderTitle('Popular docs')}</Container>
+ <Container>{this._renderLinkSection(popularDocsToLinkInfos)}</Container>
+ </Container>
+ <Container>
+ <Container>{this._renderTitle('Useful links')}</Container>
+ <Container>{this._renderLinkSection(usefulLinksToLinkInfo)}</Container>
+ </Container>
+ </Container>
+ <Link to={WebsitePaths.Docs} fontColor={colors.lightBlueA700}>
+ <Container
+ padding="0.9rem"
+ backgroundColor={colors.lightBgGrey}
+ borderBottomLeftRadius={4}
+ borderBottomRightRadius={4}
+ >
+ <Text fontColor={colors.lightBlueA700} fontWeight="bold" fontSize="14px" textAlign="center">
+ {this.props.translate.get(Key.ViewAllDocumentation, Deco.Upper)}
+ </Text>
+ </Container>
+ </Link>
+ </Container>
+ );
+ return dropdownMenu;
+ }
+ private _renderTitle(title: string): React.ReactNode {
+ return (
+ <Container paddingBottom="12px">
+ <Text letterSpacing={1} fontColor={colors.linkSectionGrey} fontSize="14px" fontWeight={600}>
+ {title.toUpperCase()}
+ </Text>
+ </Container>
+ );
+ }
+ private _renderLinkSection(links: ALink[]): React.ReactNode {
+ const numLinks = links.length;
+ let i = 0;
+ const renderLinks = _.map(links, (link: ALink) => {
+ const isWikiLink = _.startsWith(link.to, WebsitePaths.Wiki) && _.includes(link.to, '#');
+ const isOnWiki = this.props.location.pathname === WebsitePaths.Wiki;
+ let to = link.to;
+ if (isWikiLink && isOnWiki) {
+ to = `${link.to.split('#')[1]}`;
+ }
+ i++;
+ const isLast = i === numLinks;
+ const linkText = this.props.translate.get(link.title as Key, Deco.Cap);
+ return (
+ <Container className={`pr1 pt1 ${!isLast && 'pb1'}`} key={`dev-dropdown-link-${link.title}`}>
+ <Link to={to} shouldOpenInNewTab={!!link.shouldOpenInNewTab}>
+ <Text fontFamily="Roboto, Roboto Mono" fontColor={colors.lightBlueA700}>
+ {linkText}
+ </Text>
+ </Link>
+ </Container>
+ );
+ });
+ return <Container>{renderLinks}</Container>;
+ }
+}
diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx
index 3c3155349..c1bbadfde 100644
--- a/packages/website/ts/components/fill_order.tsx
+++ b/packages/website/ts/components/fill_order.tsx
@@ -1,5 +1,5 @@
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
-import { colors } from '@0xproject/react-shared';
+import { colors, Link } from '@0xproject/react-shared';
import { BigNumber, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as accounting from 'accounting';
@@ -8,7 +8,6 @@ import { Card, CardHeader, CardText } from 'material-ui/Card';
import Divider from 'material-ui/Divider';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
-import { Link } from 'react-router-dom';
import { Blockchain } from 'ts/blockchain';
import { TrackTokenConfirmationDialog } from 'ts/components/dialogs/track_token_confirmation_dialog';
import { FillOrderJSON } from 'ts/components/fill_order_json';
@@ -324,7 +323,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return (
<div>
Order successfully filled. See the trade details in your{' '}
- <Link to={`${WebsitePaths.Portal}/trades`} style={{ color: colors.white }}>
+ <Link to={`${WebsitePaths.Portal}/trades`} fontColor={colors.white}>
trade history
</Link>
</div>
diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx
index 6dcb5a0e9..db4f57100 100644
--- a/packages/website/ts/components/footer.tsx
+++ b/packages/website/ts/components/footer.tsx
@@ -1,31 +1,17 @@
-import { colors } from '@0xproject/react-shared';
+import { ALink, colors, Link } from '@0xproject/react-shared';
+import { ObjectMap } from '@0xproject/types';
import * as _ from 'lodash';
import DropDownMenu from 'material-ui/DropDownMenu';
import MenuItem from 'material-ui/MenuItem';
import * as React from 'react';
-import { Link } from 'react-router-dom';
+
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, Language, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
-interface MenuItemsBySection {
- [sectionName: string]: FooterMenuItem[];
-}
-
-interface FooterMenuItem {
- title: string;
- path?: string;
- isExternal?: boolean;
-}
-
const ICON_DIMENSION = 16;
-const linkStyle = {
- color: colors.white,
- cursor: 'pointer',
-};
-
const languageToMenuTitle = {
[Language.English]: 'English',
[Language.Russian]: 'Русский',
@@ -51,76 +37,74 @@ export class Footer extends React.Component<FooterProps, FooterState> {
};
}
public render(): React.ReactNode {
- const menuItemsBySection: MenuItemsBySection = {
+ const sectionNameToLinks: ObjectMap<ALink[]> = {
[Key.Documentation]: [
{
+ title: 'Developer Home',
+ to: WebsitePaths.Docs,
+ },
+ {
title: '0x.js',
- path: WebsitePaths.ZeroExJs,
+ to: WebsitePaths.ZeroExJs,
},
{
title: this.props.translate.get(Key.SmartContracts, Deco.Cap),
- path: WebsitePaths.SmartContracts,
+ to: WebsitePaths.SmartContracts,
},
{
title: this.props.translate.get(Key.Connect, Deco.Cap),
- path: WebsitePaths.Connect,
+ to: WebsitePaths.Connect,
},
{
title: this.props.translate.get(Key.Whitepaper, Deco.Cap),
- path: WebsitePaths.Whitepaper,
- isExternal: true,
+ to: WebsitePaths.Whitepaper,
+ shouldOpenInNewTab: true,
},
{
title: this.props.translate.get(Key.Wiki, Deco.Cap),
- path: WebsitePaths.Wiki,
- },
- {
- title: this.props.translate.get(Key.Faq, Deco.Cap),
- path: WebsitePaths.FAQ,
+ to: WebsitePaths.Wiki,
},
],
[Key.Community]: [
{
title: this.props.translate.get(Key.RocketChat, Deco.Cap),
- isExternal: true,
- path: constants.URL_ZEROEX_CHAT,
+ to: constants.URL_ZEROEX_CHAT,
+ shouldOpenInNewTab: true,
},
{
title: this.props.translate.get(Key.Blog, Deco.Cap),
- isExternal: true,
- path: constants.URL_BLOG,
+ to: constants.URL_BLOG,
+ shouldOpenInNewTab: true,
},
{
title: 'Twitter',
- isExternal: true,
- path: constants.URL_TWITTER,
+ to: constants.URL_TWITTER,
+ shouldOpenInNewTab: true,
},
{
title: 'Reddit',
- isExternal: true,
- path: constants.URL_REDDIT,
+ to: constants.URL_REDDIT,
+ shouldOpenInNewTab: true,
},
{
title: this.props.translate.get(Key.Forum, Deco.Cap),
- isExternal: true,
- path: constants.URL_DISCOURSE_FORUM,
+ to: constants.URL_DISCOURSE_FORUM,
+ shouldOpenInNewTab: true,
},
],
[Key.Organization]: [
{
title: this.props.translate.get(Key.About, Deco.Cap),
- isExternal: false,
- path: WebsitePaths.About,
+ to: WebsitePaths.About,
},
{
title: this.props.translate.get(Key.Careers, Deco.Cap),
- isExternal: false,
- path: WebsitePaths.Careers,
+ to: WebsitePaths.Careers,
},
{
title: this.props.translate.get(Key.Contact, Deco.Cap),
- isExternal: true,
- path: 'mailto:team@0xproject.com',
+ to: 'mailto:team@0xproject.com',
+ shouldOpenInNewTab: true,
},
],
};
@@ -160,19 +144,19 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center">
{this._renderHeader(Key.Documentation)}
- {_.map(menuItemsBySection[Key.Documentation], this._renderMenuItem.bind(this))}
+ {_.map(sectionNameToLinks[Key.Documentation], this._renderMenuItem.bind(this))}
</div>
</div>
<div className="col lg-col-4 md-col-4 col-12 lg-pr2 md-pr2">
<div className="lg-right md-right sm-center">
{this._renderHeader(Key.Community)}
- {_.map(menuItemsBySection[Key.Community], this._renderMenuItem.bind(this))}
+ {_.map(sectionNameToLinks[Key.Community], this._renderMenuItem.bind(this))}
</div>
</div>
<div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center">
{this._renderHeader(Key.Organization)}
- {_.map(menuItemsBySection[Key.Organization], this._renderMenuItem.bind(this))}
+ {_.map(sectionNameToLinks[Key.Organization], this._renderMenuItem.bind(this))}
</div>
</div>
</div>
@@ -187,7 +171,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div>
);
}
- private _renderMenuItem(item: FooterMenuItem): React.ReactNode {
+ private _renderMenuItem(link: ALink): React.ReactNode {
const titleToIcon: { [title: string]: string } = {
[this.props.translate.get(Key.RocketChat, Deco.Cap)]: 'rocketchat.png',
[this.props.translate.get(Key.Blog, Deco.Cap)]: 'medium.png',
@@ -195,30 +179,26 @@ export class Footer extends React.Component<FooterProps, FooterState> {
Reddit: 'reddit.png',
[this.props.translate.get(Key.Forum, Deco.Cap)]: 'discourse.png',
};
- const iconIfExists = titleToIcon[item.title];
+ const iconIfExists = titleToIcon[link.title];
return (
- <div key={item.title} className="sm-center" style={{ fontSize: 13, paddingTop: 25 }}>
- {item.isExternal ? (
- <a className="text-decoration-none" style={linkStyle} target="_blank" href={item.path}>
+ <div key={link.title} className="sm-center" style={{ fontSize: 13, paddingTop: 25 }}>
+ <Link
+ to={link.to}
+ shouldOpenInNewTab={link.shouldOpenInNewTab}
+ fontColor={colors.white}
+ className="text-decoration-none"
+ >
+ <div>
{!_.isUndefined(iconIfExists) ? (
<div className="inline-block">
<div className="pr1 table-cell">{this._renderIcon(iconIfExists)}</div>
- <div className="table-cell">{item.title}</div>
+ <div className="table-cell">{link.title}</div>
</div>
) : (
- item.title
+ link.title
)}
- </a>
- ) : (
- <Link to={item.path} style={linkStyle} className="text-decoration-none">
- <div>
- {!_.isUndefined(iconIfExists) && (
- <div className="pr1">{this._renderIcon(iconIfExists)}</div>
- )}
- {item.title}
- </div>
- </Link>
- )}
+ </div>
+ </Link>
</div>
);
}
diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx
index db093fb68..134d1cc76 100644
--- a/packages/website/ts/components/inputs/token_amount_input.tsx
+++ b/packages/website/ts/components/inputs/token_amount_input.tsx
@@ -1,9 +1,8 @@
-import { colors } from '@0xproject/react-shared';
+import { colors, Link } from '@0xproject/react-shared';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import * as React from 'react';
-import { Link } from 'react-router-dom';
import { Blockchain } from 'ts/blockchain';
import { BalanceBoundedInput } from 'ts/components/inputs/balance_bounded_input';
import { Token, ValidatedBigNumberCallback, WebsitePaths } from 'ts/types';
@@ -112,7 +111,8 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok
Insufficient allowance.{' '}
<Link
to={`${WebsitePaths.Portal}/account`}
- style={{ cursor: 'pointer', color: colors.darkestGrey }}
+ textDecoration="underline"
+ fontColor={colors.darkestGrey}
>
Set allowance
</Link>
diff --git a/packages/website/ts/components/portal/back_button.tsx b/packages/website/ts/components/portal/back_button.tsx
index ca35abc2b..64a332e07 100644
--- a/packages/website/ts/components/portal/back_button.tsx
+++ b/packages/website/ts/components/portal/back_button.tsx
@@ -1,7 +1,5 @@
-import { Styles } from '@0xproject/react-shared';
+import { Link, Styles } from '@0xproject/react-shared';
import * as React from 'react';
-import { Link } from 'react-router-dom';
-
import { Island } from 'ts/components/ui/island';
import { colors } from 'ts/style/colors';
@@ -27,7 +25,7 @@ const styles: Styles = {
export const BackButton = (props: BackButtonProps) => {
return (
<div style={{ height: 65, paddingTop: 25 }}>
- <Link to={props.to} style={{ textDecoration: 'none' }}>
+ <Link to={props.to}>
<Island className="flex right" style={styles.backButton}>
<div style={{ marginLeft: 12 }}>
<i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} />
diff --git a/packages/website/ts/components/portal/drawer_menu.tsx b/packages/website/ts/components/portal/drawer_menu.tsx
index a6707e86c..3a8c69a70 100644
--- a/packages/website/ts/components/portal/drawer_menu.tsx
+++ b/packages/website/ts/components/portal/drawer_menu.tsx
@@ -39,7 +39,7 @@ export interface DrawerMenuProps {
}
export const DrawerMenu = (props: DrawerMenuProps) => {
const relayerItemEntry = {
- to: `${WebsitePaths.Portal}`,
+ to: WebsitePaths.Portal,
labelText: 'Relayer ecosystem',
iconName: 'zmdi-portable-wifi',
};
diff --git a/packages/website/ts/components/portal/menu.tsx b/packages/website/ts/components/portal/menu.tsx
index 39dab77f5..a3352529c 100644
--- a/packages/website/ts/components/portal/menu.tsx
+++ b/packages/website/ts/components/portal/menu.tsx
@@ -1,7 +1,7 @@
import { Styles } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
-import { MenuItem } from 'ts/components/ui/menu_item';
+import { CustomMenuItem } from 'ts/components/ui/custom_menu_item';
import { colors } from 'ts/style/colors';
import { WebsitePaths } from 'ts/types';
@@ -67,14 +67,14 @@ export const Menu: React.StatelessComponent<MenuProps> = (props: MenuProps) => {
{_.map(props.menuItemEntries, entry => {
const isSelected = entry.to === props.selectedPath;
return (
- <MenuItem key={entry.to} to={entry.to}>
+ <CustomMenuItem key={entry.to} to={entry.to}>
<MenuItemLabel
title={entry.labelText}
iconName={entry.iconName}
selected={isSelected}
theme={props.theme}
/>
- </MenuItem>
+ </CustomMenuItem>
);
})}
</div>
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index 1470239d6..c58dc26bd 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -1,9 +1,9 @@
-import { colors } from '@0xproject/react-shared';
+import { colors, Link } from '@0xproject/react-shared';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
-import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom';
+import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { Blockchain } from 'ts/blockchain';
import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog';
@@ -317,7 +317,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
};
return (
<Section
- header={<BackButton to={`${WebsitePaths.Portal}`} labelText="back to Relayers" />}
+ header={<BackButton to={WebsitePaths.Portal} labelText="back to Relayers" />}
body={<Menu selectedPath={routeComponentProps.location.pathname} theme={menuTheme} />}
/>
);
@@ -389,9 +389,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
</Container>
);
return !shouldStartOnboarding ? (
- <Link to={{ pathname: `${WebsitePaths.Portal}/account` }} style={{ textDecoration: 'none' }}>
- {startOnboarding}
- </Link>
+ <Link to={`${WebsitePaths.Portal}/account`}>{startOnboarding}</Link>
) : (
startOnboarding
);
diff --git a/packages/website/ts/components/sidebar_header.tsx b/packages/website/ts/components/sidebar_header.tsx
deleted file mode 100644
index a14ab54f5..000000000
--- a/packages/website/ts/components/sidebar_header.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { colors } from '@0xproject/react-shared';
-import * as React from 'react';
-
-interface SidebarHeaderProps {
- title: string;
- iconUrl: string;
-}
-
-interface SidebarHeaderState {}
-
-export class SidebarHeader extends React.Component<SidebarHeaderProps, SidebarHeaderState> {
- public render(): React.ReactNode {
- return (
- <div className="pt2 md-px1 sm-px2" style={{ color: colors.black, paddingBottom: 18 }}>
- <div className="flex" style={{ fontSize: 25 }}>
- <div style={{ fontWeight: 'bold', fontFamily: 'Roboto Mono' }}>0x</div>
- <div className="pl2" style={{ lineHeight: 1.4, fontWeight: 300 }}>
- docs
- </div>
- </div>
- <div className="pl1" style={{ color: colors.grey350, paddingBottom: 9, paddingLeft: 10, height: 17 }}>
- |
- </div>
- <div className="flex">
- <div>
- <img src={this.props.iconUrl} width="22" />
- </div>
- <div className="pl1" style={{ fontWeight: 600, fontSize: 20, lineHeight: 1.2 }}>
- {this.props.title}
- </div>
- </div>
- </div>
- );
- }
-}
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index fe2c1fcf9..7e7247c25 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -1,23 +1,16 @@
-import { DocsInfo, DocsMenu } from '@0xproject/react-docs';
-import {
- colors,
- constants as sharedConstants,
- MenuSubsectionsBySection,
- NestedSidebarMenu,
- Styles,
-} from '@0xproject/react-shared';
+import { DocsInfo } from '@0xproject/react-docs';
+import { ALink, colors, Link, Styles } from '@0xproject/react-shared';
+import { ObjectMap } from '@0xproject/types';
import * as _ from 'lodash';
import Drawer from 'material-ui/Drawer';
-import Menu from 'material-ui/Menu';
import MenuItem from 'material-ui/MenuItem';
import * as React from 'react';
-import { Link } from 'react-router-dom';
import { Blockchain } from 'ts/blockchain';
+import { DevelopersDropDown } from 'ts/components/dropdowns/developers_drop_down';
import { DrawerMenu } from 'ts/components/portal/drawer_menu';
import { ProviderDisplay } from 'ts/components/top_bar/provider_display';
import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item';
import { Container } from 'ts/components/ui/container';
-import { DropDown } from 'ts/components/ui/drop_down';
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, ProviderType, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
@@ -41,8 +34,7 @@ export interface TopBarProps {
translate: Translate;
docsVersion?: string;
availableDocVersions?: string[];
- menu?: DocsMenu;
- menuSubsectionsBySection?: MenuSubsectionsBySection;
+ sectionNameToLinks?: ObjectMap<ALink[]>;
displayType?: TopBarDisplayType;
docsInfo?: DocsInfo;
style?: React.CSSProperties;
@@ -80,21 +72,6 @@ const styles: Styles = {
},
};
-const DOC_WEBSITE_PATHS_TO_KEY = {
- [WebsitePaths.SolCov]: Key.SolCov,
- [WebsitePaths.SmartContracts]: Key.SmartContracts,
- [WebsitePaths.Web3Wrapper]: Key.Web3Wrapper,
- [WebsitePaths.SolCompiler]: Key.SolCompiler,
- [WebsitePaths.JSONSchemas]: Key.JsonSchemas,
- [WebsitePaths.Subproviders]: Key.Subproviders,
- [WebsitePaths.ContractWrappers]: Key.ContractWrappers,
- [WebsitePaths.Connect]: Key.Connect,
- [WebsitePaths.ZeroExJs]: Key.ZeroExJs,
- [WebsitePaths.OrderUtils]: Key.OrderUtils,
- [WebsitePaths.OrderWatcher]: Key.OrderWatcher,
- [WebsitePaths.AssetBuyer]: Key.AssetBuyer,
-};
-
const DEFAULT_HEIGHT = 68;
const EXPANDED_HEIGHT = 75;
@@ -130,117 +107,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
? 'flex mx-auto items-center max-width-4'
: 'flex mx-auto items-center';
const height = isExpandedDisplayType ? EXPANDED_HEIGHT : DEFAULT_HEIGHT;
- const developerSectionMenuItems = [
- <Link key="subMenuItem-zeroEx" to={WebsitePaths.ZeroExJs} className="text-decoration-none">
- <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="0x.js" />
- </Link>,
- <Link key="subMenuItem-smartContracts" to={WebsitePaths.SmartContracts} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.SmartContracts, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-0xconnect" to={WebsitePaths.Connect} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Connect, Deco.CapWords)}
- />
- </Link>,
- <a
- key="subMenuItem-standard-relayer-api"
- target="_blank"
- className="text-decoration-none"
- href={constants.URL_STANDARD_RELAYER_API_GITHUB}
- >
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.StandardRelayerApi, Deco.CapWords)}
- />
- </a>,
- <Link key="subMenuItem-jsonSchema" to={WebsitePaths.JSONSchemas} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.JsonSchemas, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-subproviders" to={WebsitePaths.Subproviders} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Subproviders, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-web3Wrapper" to={WebsitePaths.Web3Wrapper} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Web3Wrapper, Deco.CapWords)}
- />
- </Link>,
- <Link
- key="subMenuItem-contractWrappers"
- to={WebsitePaths.ContractWrappers}
- className="text-decoration-none"
- >
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.ContractWrappers, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-orderUtils" to={WebsitePaths.OrderUtils} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.OrderUtils, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-orderWatcher" to={WebsitePaths.OrderWatcher} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.OrderWatcher, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-sol-compiler" to={WebsitePaths.SolCompiler} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.SolCompiler, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-sol-cov" to={WebsitePaths.SolCov} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.SolCov, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-ethereum-types" to={WebsitePaths.EthereumTypes} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.EthereumTypes, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-asset-buyer" to={WebsitePaths.AssetBuyer} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.AssetBuyer, Deco.CapWords)}
- />
- </Link>,
- <a
- key="subMenuItem-whitePaper"
- target="_blank"
- className="text-decoration-none"
- href={`${WebsitePaths.Whitepaper}`}
- >
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Whitepaper, Deco.CapWords)}
- />
- </a>,
- <a
- key="subMenuItem-github"
- target="_blank"
- className="text-decoration-none"
- href={constants.URL_GITHUB_ORG}
- >
- <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="GitHub" />
- </a>,
- ];
const bottomBorderStyle = this._shouldDisplayBottomBar() ? styles.bottomBar : {};
const fullWidthClasses = isExpandedDisplayType ? 'pr4' : '';
const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png';
@@ -252,15 +118,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
color: isNightVersion ? 'white' : 'black',
cursor: 'pointer',
};
- const activeNode = (
- <div className="flex relative" style={{ color: menuIconStyle.color }}>
- <div style={{ paddingRight: 10 }}>{this.props.translate.get(Key.Developers, Deco.Cap)}</div>
- <div className="absolute" style={{ paddingLeft: 3, right: 3, top: -2 }}>
- <i className="zmdi zmdi-caret-right" style={{ fontSize: 22 }} />
- </div>
- </div>
- );
- const popoverContent = <Menu style={{ color: colors.darkGrey }}>{developerSectionMenuItems}</Menu>;
return (
<div
style={{ ...styles.topBar, ...bottomBorderStyle, ...this.props.style, ...{ height } }}
@@ -273,56 +130,45 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
paddingLeft={this.props.paddingLeft}
paddingRight={this.props.paddingRight}
>
- <Link to={`${WebsitePaths.Home}`} className="text-decoration-none">
+ <Link to={WebsitePaths.Home}>
<img src={logoUrl} height="30" />
</Link>
<div className="flex-auto" />
{!this._isViewingPortal() && (
<div className={menuClasses}>
<div className="flex items-center justify-between">
- <DropDown
- activeNode={activeNode}
- popoverContent={popoverContent}
- anchorOrigin={{ horizontal: 'middle', vertical: 'bottom' }}
- targetOrigin={{ horizontal: 'middle', vertical: 'top' }}
- style={styles.menuItem}
- />
- <TopBarMenuItem
- title={this.props.translate.get(Key.Wiki, Deco.Cap)}
- path={`${WebsitePaths.Wiki}`}
- style={styles.menuItem}
- isNightVersion={isNightVersion}
- isExternal={false}
+ <DevelopersDropDown
+ location={this.props.location}
+ menuItemStyles={{ ...styles.menuItem, paddingBottom: 12, paddingTop: 12 }}
+ translate={this.props.translate}
+ menuIconStyle={menuIconStyle}
/>
<TopBarMenuItem
title={this.props.translate.get(Key.Blog, Deco.Cap)}
path={constants.URL_BLOG}
style={styles.menuItem}
isNightVersion={isNightVersion}
- isExternal={true}
+ shouldOpenInNewTab={true}
/>
<TopBarMenuItem
title={this.props.translate.get(Key.About, Deco.Cap)}
- path={`${WebsitePaths.About}`}
+ path={WebsitePaths.About}
style={styles.menuItem}
isNightVersion={isNightVersion}
- isExternal={false}
/>
<TopBarMenuItem
title={this.props.translate.get(Key.Careers, Deco.Cap)}
- path={`${WebsitePaths.Careers}`}
+ path={WebsitePaths.Careers}
style={styles.menuItem}
isNightVersion={isNightVersion}
- isExternal={false}
/>
<TopBarMenuItem
title={this.props.translate.get(Key.TradeCallToAction, Deco.Cap)}
- path={`${WebsitePaths.Portal}`}
+ path={WebsitePaths.Portal}
isPrimary={true}
style={styles.menuItem}
className={`${isExpandedDisplayType && 'md-hide'}`}
isNightVersion={isNightVersion}
- isExternal={false}
/>
</div>
</div>
@@ -379,54 +225,35 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
onRequestChange={this._onMenuButtonClick.bind(this)}
>
<div className="clearfix">
- {this._renderDocsMenu()}
- {this._renderWiki()}
<div className="pl1 py1 mt3" style={{ backgroundColor: colors.lightGrey }}>
{this.props.translate.get(Key.Website, Deco.Cap)}
</div>
- <Link to={WebsitePaths.Home} className="text-decoration-none">
+ <Link to={WebsitePaths.Home}>
<MenuItem className="py2">{this.props.translate.get(Key.Home, Deco.Cap)}</MenuItem>
</Link>
- <Link to={`${WebsitePaths.Wiki}`} className="text-decoration-none">
- <MenuItem className="py2">{this.props.translate.get(Key.Wiki, Deco.Cap)}</MenuItem>
+ <Link to={WebsitePaths.Docs}>
+ <MenuItem className="py2">{this.props.translate.get(Key.Docs, Deco.Cap)}</MenuItem>
</Link>
- {_.map(DOC_WEBSITE_PATHS_TO_KEY, (key, websitePath) => {
- if (!this._doesUrlInclude(websitePath)) {
- return (
- <Link
- key={`drawer-menu-item-${websitePath}`}
- to={websitePath}
- className="text-decoration-none"
- >
- <MenuItem className="py2">
- {this.props.translate.get(key, Deco.Cap)}{' '}
- {this.props.translate.get(Key.Docs, Deco.Cap)}
- </MenuItem>
- </Link>
- );
- }
- return null;
- })}
{!this._isViewingPortal() && (
- <Link to={`${WebsitePaths.Portal}`} className="text-decoration-none">
+ <Link to={WebsitePaths.Portal}>
<MenuItem className="py2">
{this.props.translate.get(Key.PortalDApp, Deco.CapWords)}
</MenuItem>
</Link>
)}
- <a className="text-decoration-none" target="_blank" href={`${WebsitePaths.Whitepaper}`}>
+ <Link to={WebsitePaths.Whitepaper} shouldOpenInNewTab={true}>
<MenuItem className="py2">{this.props.translate.get(Key.Whitepaper, Deco.Cap)}</MenuItem>
- </a>
- <Link to={`${WebsitePaths.About}`} className="text-decoration-none">
+ </Link>
+ <Link to={WebsitePaths.About}>
<MenuItem className="py2">{this.props.translate.get(Key.About, Deco.Cap)}</MenuItem>
</Link>
- <Link to={`${WebsitePaths.Careers}`} className="text-decoration-none">
+ <Link to={WebsitePaths.Careers}>
<MenuItem className="py2">{this.props.translate.get(Key.Careers, Deco.Cap)}</MenuItem>
</Link>
- <a className="text-decoration-none" target="_blank" href={constants.URL_BLOG}>
+ <Link to={constants.URL_BLOG} shouldOpenInNewTab={true}>
<MenuItem className="py2">{this.props.translate.get(Key.Blog, Deco.Cap)}</MenuItem>
- </a>
- <Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none">
+ </Link>
+ <Link to={WebsitePaths.FAQ}>
<MenuItem className="py2" onClick={this._onMenuButtonClick.bind(this)}>
{this.props.translate.get(Key.Faq, Deco.Cap)}
</MenuItem>
@@ -435,49 +262,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</Drawer>
);
}
- private _renderDocsMenu(): React.ReactNode {
- const isViewingDocsPage = _.some(DOC_WEBSITE_PATHS_TO_KEY, (_key, websitePath) => {
- return this._doesUrlInclude(websitePath);
- });
- // HACK: We need to make sure the SCROLL_CONTAINER is loaded before rendering the Sidebar
- // because the sidebar renders `react-scroll` links which depend on the scroll container already
- // being rendered.
- const documentationContainer = document.getElementById(sharedConstants.SCROLL_CONTAINER_ID);
- if (!isViewingDocsPage || _.isUndefined(this.props.menu) || _.isNull(documentationContainer)) {
- return undefined;
- }
- return (
- <div className="lg-hide md-hide">
- <NestedSidebarMenu
- topLevelMenu={this.props.menu}
- menuSubsectionsBySection={this.props.menuSubsectionsBySection}
- sidebarHeader={this.props.sidebarHeader}
- shouldDisplaySectionHeaders={false}
- onMenuItemClick={this._onMenuButtonClick.bind(this)}
- selectedVersion={this.props.docsVersion}
- versions={this.props.availableDocVersions}
- onVersionSelected={this.props.onVersionSelected}
- />
- </div>
- );
- }
- private _renderWiki(): React.ReactNode {
- if (!this._isViewingWiki()) {
- return undefined;
- }
-
- return (
- <div className="lg-hide md-hide">
- <NestedSidebarMenu
- topLevelMenu={this.props.menuSubsectionsBySection}
- menuSubsectionsBySection={this.props.menuSubsectionsBySection}
- sidebarHeader={this.props.sidebarHeader}
- shouldDisplaySectionHeaders={false}
- onMenuItemClick={this._onMenuButtonClick.bind(this)}
- />
- </div>
- );
- }
private _onMenuButtonClick(): void {
this.setState({
isDrawerOpen: !this.state.isDrawerOpen,
@@ -486,28 +270,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
private _isViewingPortal(): boolean {
return _.includes(this.props.location.pathname, WebsitePaths.Portal);
}
- private _isViewingDocs(): boolean {
- return _.includes(this.props.location.pathname, WebsitePaths.Docs);
- }
private _isViewingFAQ(): boolean {
return _.includes(this.props.location.pathname, WebsitePaths.FAQ);
}
- private _doesUrlInclude(aPath: string): boolean {
- return _.includes(this.props.location.pathname, aPath);
- }
- private _isViewingWiki(): boolean {
- return _.includes(this.props.location.pathname, WebsitePaths.Wiki);
- }
private _shouldDisplayBottomBar(): boolean {
- const isViewingDocsPage = _.some(DOC_WEBSITE_PATHS_TO_KEY, (_key, websitePath) => {
- return this._doesUrlInclude(websitePath);
- });
- return (
- isViewingDocsPage ||
- this._isViewingWiki() ||
- this._isViewingFAQ() ||
- this._isViewingDocs() ||
- this._isViewingPortal()
- );
+ return this._isViewingFAQ() || this._isViewingPortal();
}
} // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/components/top_bar/top_bar_menu_item.tsx b/packages/website/ts/components/top_bar/top_bar_menu_item.tsx
index 25fab2868..eff5ba66d 100644
--- a/packages/website/ts/components/top_bar/top_bar_menu_item.tsx
+++ b/packages/website/ts/components/top_bar/top_bar_menu_item.tsx
@@ -1,7 +1,6 @@
-import { colors } from '@0xproject/react-shared';
+import { colors, Link } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
-import { Link } from 'react-router-dom';
import { CallToAction } from 'ts/components/ui/button';
@@ -13,7 +12,7 @@ interface TopBarMenuItemProps {
title: string;
path?: string;
isPrimary?: boolean;
- isExternal: boolean;
+ shouldOpenInNewTab?: boolean;
style?: React.CSSProperties;
className?: string;
isNightVersion?: boolean;
@@ -26,6 +25,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
isPrimary: false,
style: DEFAULT_STYLE,
className: '',
+ shouldOpenInNewTab: false,
isNightVersion: false,
};
public render(): React.ReactNode {
@@ -38,20 +38,9 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
);
return (
<div className={`center ${this.props.className}`} style={{ ...this.props.style, color: menuItemColor }}>
- {this.props.isExternal ? (
- <a
- className="text-decoration-none"
- style={{ color: linkColor }}
- target="_blank"
- href={this.props.path}
- >
- {itemContent}
- </a>
- ) : (
- <Link to={this.props.path} className="text-decoration-none" style={{ color: linkColor }}>
- {itemContent}
- </Link>
- )}
+ <Link to={this.props.path} shouldOpenInNewTab={this.props.shouldOpenInNewTab} fontColor={linkColor}>
+ {itemContent}
+ </Link>
</div>
);
}
diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx
index 75ba7bcff..2a6a1f477 100644
--- a/packages/website/ts/components/ui/button.tsx
+++ b/packages/website/ts/components/ui/button.tsx
@@ -10,11 +10,13 @@ export interface ButtonProps {
fontFamily?: string;
backgroundColor?: string;
borderColor?: string;
+ borderRadius?: string;
width?: string;
padding?: string;
type?: string;
isDisabled?: boolean;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ textAlign?: string;
}
const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
@@ -29,11 +31,12 @@ export const Button = styled(PlainButton)`
color: ${props => props.fontColor};
transition: background-color, opacity 0.5s ease;
padding: ${props => props.padding};
- border-radius: 6px;
+ border-radius: ${props => props.borderRadius};
font-weight: 500;
outline: none;
font-family: ${props => props.fontFamily};
width: ${props => props.width};
+ text-align: ${props => props.textAlign};
background-color: ${props => props.backgroundColor};
border: ${props => (props.borderColor ? `1px solid ${props.borderColor}` : 'none')};
&:hover {
@@ -52,11 +55,13 @@ export const Button = styled(PlainButton)`
Button.defaultProps = {
fontSize: '12px',
+ borderRadius: '6px',
backgroundColor: colors.white,
width: 'auto',
fontFamily: 'Roboto',
isDisabled: false,
padding: '0.8em 2.2em',
+ textAlign: 'center',
};
Button.displayName = 'Button';
diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx
index f2ae68b70..ece077563 100644
--- a/packages/website/ts/components/ui/container.tsx
+++ b/packages/website/ts/components/ui/container.tsx
@@ -15,7 +15,11 @@ export interface ContainerProps {
paddingRight?: StringOrNum;
paddingLeft?: StringOrNum;
backgroundColor?: string;
+ background?: string;
borderRadius?: StringOrNum;
+ borderBottomLeftRadius?: StringOrNum;
+ borderBottomRightRadius?: StringOrNum;
+ borderBottom?: StringOrNum;
maxWidth?: StringOrNum;
maxHeight?: StringOrNum;
width?: StringOrNum;
diff --git a/packages/website/ts/components/ui/menu_item.tsx b/packages/website/ts/components/ui/custom_menu_item.tsx
index 0cb4b387c..c25da6be6 100644
--- a/packages/website/ts/components/ui/menu_item.tsx
+++ b/packages/website/ts/components/ui/custom_menu_item.tsx
@@ -1,24 +1,23 @@
+import { Link } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
-import { Link } from 'react-router-dom';
-interface MenuItemProps {
+interface CustomMenuItemProps {
to: string;
- style?: React.CSSProperties;
onClick?: () => void;
className?: string;
}
-interface MenuItemState {
+interface CustomMenuItemState {
isHovering: boolean;
}
-export class MenuItem extends React.Component<MenuItemProps, MenuItemState> {
- public static defaultProps: Partial<MenuItemProps> = {
+export class CustomMenuItem extends React.Component<CustomMenuItemProps, CustomMenuItemState> {
+ public static defaultProps: Partial<CustomMenuItemProps> = {
onClick: _.noop.bind(_),
className: '',
};
- public constructor(props: MenuItemProps) {
+ public constructor(props: CustomMenuItemProps) {
super(props);
this.state = {
isHovering: false,
@@ -30,7 +29,7 @@ export class MenuItem extends React.Component<MenuItemProps, MenuItemState> {
opacity: this.state.isHovering ? 0.5 : 1,
};
return (
- <Link to={this.props.to} style={{ textDecoration: 'none', ...this.props.style }}>
+ <Link to={this.props.to}>
<div
onClick={this.props.onClick.bind(this)}
className={`mx-auto ${this.props.className}`}
diff --git a/packages/website/ts/components/ui/drop_down.tsx b/packages/website/ts/components/ui/drop_down.tsx
index 4d5caef08..4138b3fe5 100644
--- a/packages/website/ts/components/ui/drop_down.tsx
+++ b/packages/website/ts/components/ui/drop_down.tsx
@@ -1,3 +1,4 @@
+import * as _ from 'lodash';
import Popover from 'material-ui/Popover';
import * as React from 'react';
import { MaterialUIPosition } from 'ts/types';
@@ -21,6 +22,7 @@ export interface DropDownProps {
zDepth?: number;
activateEvent?: DropdownMouseEvent;
closeEvent?: DropdownMouseEvent;
+ popoverStyle?: React.CSSProperties;
}
interface DropDownState {
@@ -34,6 +36,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
zDepth: 1,
activateEvent: DropdownMouseEvent.Hover,
closeEvent: DropdownMouseEvent.Hover,
+ popoverStyle: {},
};
private _isHovering: boolean;
private _popoverCloseCheckIntervalId: number;
@@ -73,10 +76,15 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
anchorEl={this.state.anchorEl}
anchorOrigin={this.props.anchorOrigin}
targetOrigin={this.props.targetOrigin}
- onRequestClose={this._closePopover.bind(this)}
+ onRequestClose={
+ this.props.closeEvent === DropdownMouseEvent.Click
+ ? this._closePopover.bind(this)
+ : _.noop.bind(_)
+ }
useLayerForClickAway={this.props.closeEvent === DropdownMouseEvent.Click}
animated={false}
zDepth={this.props.zDepth}
+ style={this.props.popoverStyle}
>
<div
onMouseEnter={this._onHover.bind(this)}
@@ -92,7 +100,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
private _onActiveNodeClick(event: React.FormEvent<HTMLInputElement>): void {
if (this.props.activateEvent === DropdownMouseEvent.Click) {
this.setState({
- isDropDownOpen: true,
+ isDropDownOpen: !this.state.isDropDownOpen,
anchorEl: event.currentTarget,
});
}
diff --git a/packages/website/ts/components/ui/simple_menu.tsx b/packages/website/ts/components/ui/simple_menu.tsx
index 8a9349c6d..bdaf0701e 100644
--- a/packages/website/ts/components/ui/simple_menu.tsx
+++ b/packages/website/ts/components/ui/simple_menu.tsx
@@ -1,7 +1,7 @@
+import { Link } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import * as CopyToClipboard from 'react-copy-to-clipboard';
-import { Link } from 'react-router-dom';
import { Container } from 'ts/components/ui/container';
import { Text } from 'ts/components/ui/text';
@@ -72,7 +72,7 @@ export const GoToAccountManagementSimpleMenuItem: React.StatelessComponent<
GoToAccountManagementSimpleMenuItemProps
> = ({ onClick }) => {
return (
- <Link to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}>
+ <Link to={`${WebsitePaths.Portal}/account`}>
<SimpleMenuItem displayText="Manage Account..." onClick={onClick} />
</Link>
);
diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx
index cd8f290e3..4415962b1 100644
--- a/packages/website/ts/components/ui/text.tsx
+++ b/packages/website/ts/components/ui/text.tsx
@@ -19,7 +19,9 @@ export interface TextProps {
textDecorationLine?: string;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
hoverColor?: string;
+ letterSpacing?: string | number;
noWrap?: boolean;
+ textAlign?: string;
display?: string;
}
@@ -34,6 +36,8 @@ export const Text = styled(PlainText)`
font-style: ${props => props.fontStyle};
font-weight: ${props => props.fontWeight};
font-size: ${props => props.fontSize};
+ text-align: ${props => props.textAlign};
+ letter-spacing: ${props => props.letterSpacing};
text-decoration-line: ${props => props.textDecorationLine};
${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
${props => (props.center ? 'text-align: center' : '')};
diff --git a/packages/website/ts/containers/asset_buyer_documentation.ts b/packages/website/ts/containers/asset_buyer_documentation.ts
index f794625de..13a597ea3 100644
--- a/packages/website/ts/containers/asset_buyer_documentation.ts
+++ b/packages/website/ts/containers/asset_buyer_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -47,6 +47,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -58,6 +59,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts
index a728abe2c..7c86357c5 100644
--- a/packages/website/ts/containers/connect_documentation.ts
+++ b/packages/website/ts/containers/connect_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -26,8 +26,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: '0x Connect',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -48,6 +47,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -59,6 +59,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/contract_wrappers_documentation.ts b/packages/website/ts/containers/contract_wrappers_documentation.ts
index 1e1735846..f7e5f17eb 100644
--- a/packages/website/ts/containers/contract_wrappers_documentation.ts
+++ b/packages/website/ts/containers/contract_wrappers_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -25,8 +25,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Contract Wrappers',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -43,6 +42,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -54,6 +54,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
docsInfo,
translate: state.translate,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/docs_home.ts b/packages/website/ts/containers/docs_home.ts
new file mode 100644
index 000000000..e0ca439a6
--- /dev/null
+++ b/packages/website/ts/containers/docs_home.ts
@@ -0,0 +1,31 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { DocsHome as DocsHomeComponent, DocsHomeProps } from 'ts/pages/documentation/docs_home';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+
+interface ConnectedState {
+ translate: Translate;
+ screenWidth: ScreenWidths;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: DocsHomeProps): ConnectedState => ({
+ translate: state.translate,
+ screenWidth: state.screenWidth,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const DocsHome: React.ComponentClass<DocsHomeProps> = connect(mapStateToProps, mapDispatchToProps)(
+ DocsHomeComponent,
+);
diff --git a/packages/website/ts/containers/ethereum_types_documentation.ts b/packages/website/ts/containers/ethereum_types_documentation.ts
index 2b6d6e64d..3cab885b4 100644
--- a/packages/website/ts/containers/ethereum_types_documentation.ts
+++ b/packages/website/ts/containers/ethereum_types_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -26,9 +26,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Ethereum Types',
packageUrl: 'https://github.com/0xProject/0x-monorepo/packages/ethereum-types',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
- types: [markdownSections.types],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -45,6 +43,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -56,6 +55,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/json_schemas_documentation.ts b/packages/website/ts/containers/json_schemas_documentation.ts
index f32a50ea9..4b3200203 100644
--- a/packages/website/ts/containers/json_schemas_documentation.ts
+++ b/packages/website/ts/containers/json_schemas_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -20,7 +20,6 @@ const markdownSections = {
introduction: 'introduction',
installation: 'installation',
usage: 'usage',
- schemaValidator: 'schemaValidator',
schemas: 'schemas',
};
@@ -31,10 +30,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'JSON Schemas',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
- usage: [markdownSections.usage],
- schemaValidator: [markdownSections.schemaValidator],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation, markdownSections.usage],
schemas: [markdownSections.schemas],
},
sectionNameToMarkdownByVersion: {
@@ -60,6 +56,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -71,6 +68,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/order_utils_documentation.ts b/packages/website/ts/containers/order_utils_documentation.ts
index b54c30a1e..77204b480 100644
--- a/packages/website/ts/containers/order_utils_documentation.ts
+++ b/packages/website/ts/containers/order_utils_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -25,8 +25,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Order utils',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -43,6 +42,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -54,6 +54,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/order_watcher_documentation.ts b/packages/website/ts/containers/order_watcher_documentation.ts
index 59a018847..1b0c1ec91 100644
--- a/packages/website/ts/containers/order_watcher_documentation.ts
+++ b/packages/website/ts/containers/order_watcher_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -25,8 +25,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'OrderWatcher',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -43,6 +42,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -54,6 +54,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/smart_contracts_documentation.ts b/packages/website/ts/containers/smart_contracts_documentation.ts
index 05b2a50c3..0989a7d0e 100644
--- a/packages/website/ts/containers/smart_contracts_documentation.ts
+++ b/packages/website/ts/containers/smart_contracts_documentation.ts
@@ -6,7 +6,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, SmartContractDocSections as Sections } from 'ts/types';
+import { DocPackages, ScreenWidths, SmartContractDocSections as Sections } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -97,6 +97,7 @@ interface ConnectedState {
docsVersion: string;
availableDocVersions: string[];
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -108,6 +109,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/sol_compiler_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts
index 20f26ed1d..b84974d69 100644
--- a/packages/website/ts/containers/sol_compiler_documentation.ts
+++ b/packages/website/ts/containers/sol_compiler_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -27,9 +27,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Solidity Compiler',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
- usage: [markdownSections.usage],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation, markdownSections.usage],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -47,6 +45,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -58,6 +57,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts
index 27efd641e..f9c428f8e 100644
--- a/packages/website/ts/containers/sol_cov_documentation.ts
+++ b/packages/website/ts/containers/sol_cov_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -27,9 +27,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Sol-cov',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
- usage: [markdownSections.usage],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation, markdownSections.usage],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -47,6 +45,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -58,6 +57,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts
index 28b2e9508..1588c7d46 100644
--- a/packages/website/ts/containers/subproviders_documentation.ts
+++ b/packages/website/ts/containers/subproviders_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -27,9 +27,7 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Subproviders',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [docSections.introduction],
- install: [docSections.installation],
- ['ledger-node-hid-issue']: [docSections.ledgerNodeHid],
+ 'getting-started': [docSections.introduction, docSections.installation, docSections.ledgerNodeHid],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -47,6 +45,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -58,6 +57,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts
index dc9d23304..0154c05b9 100644
--- a/packages/website/ts/containers/web3_wrapper_documentation.ts
+++ b/packages/website/ts/containers/web3_wrapper_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -13,7 +13,7 @@ const IntroMarkdownV1 = require('md/docs/web3_wrapper/introduction');
const InstallationMarkdownV1 = require('md/docs/web3_wrapper/installation');
/* tslint:enable:no-var-requires */
-const docSections = {
+const markdownSections = {
introduction: 'introduction',
installation: 'installation',
};
@@ -25,16 +25,15 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: 'Web3Wrapper',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [docSections.introduction],
- install: [docSections.installation],
+ 'getting-started': [markdownSections.introduction, markdownSections.installation],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
- [docSections.introduction]: IntroMarkdownV1,
- [docSections.installation]: InstallationMarkdownV1,
+ [markdownSections.introduction]: IntroMarkdownV1,
+ [markdownSections.installation]: InstallationMarkdownV1,
},
},
- markdownSections: docSections,
+ markdownSections,
};
const docsInfo = new DocsInfo(docsInfoConfig);
@@ -43,6 +42,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -54,6 +54,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
translate: state.translate,
docsInfo,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/wiki.ts b/packages/website/ts/containers/wiki.ts
index 357f8bbf4..069b0ae54 100644
--- a/packages/website/ts/containers/wiki.ts
+++ b/packages/website/ts/containers/wiki.ts
@@ -4,10 +4,12 @@ import { Dispatch } from 'redux';
import { Wiki as WikiComponent, WikiProps } from 'ts/pages/wiki/wiki';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
+import { ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
interface ConnectedState {
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -16,6 +18,7 @@ interface ConnectedDispatch {
const mapStateToProps = (state: State, _ownProps: WikiProps): ConnectedState => ({
translate: state.translate,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts
index 2a3afd86c..459d8390a 100644
--- a/packages/website/ts/containers/zero_ex_js_documentation.ts
+++ b/packages/website/ts/containers/zero_ex_js_documentation.ts
@@ -5,7 +5,7 @@ import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -39,9 +39,13 @@ const docsInfoConfig: DocsInfoConfig = {
displayName: '0x.js',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
- introduction: [markdownSections.introduction],
- install: [markdownSections.installation],
- topics: [markdownSections.async, markdownSections.errors, markdownSections.versioning],
+ 'getting-started': [
+ markdownSections.introduction,
+ markdownSections.installation,
+ markdownSections.async,
+ markdownSections.errors,
+ markdownSections.versioning,
+ ],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
@@ -68,6 +72,7 @@ interface ConnectedState {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
@@ -79,6 +84,7 @@ const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState
availableDocVersions: state.availableDocVersions,
docsInfo,
translate: state.translate,
+ screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index bb218eac1..21157e427 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -5,6 +5,7 @@ import { Provider } from 'react-redux';
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
import { MetaTags } from 'ts/components/meta_tags';
import { About } from 'ts/containers/about';
+import { DocsHome } from 'ts/containers/docs_home';
import { FAQ } from 'ts/containers/faq';
import { Jobs } from 'ts/containers/jobs';
import { Landing } from 'ts/containers/landing';
@@ -140,6 +141,7 @@ render(
path={`${WebsitePaths.AssetBuyer}/:version?`}
component={LazyAssetBuyerDocumentation}
/>
+ <Route path={WebsitePaths.Docs} component={DocsHome as any} />
{/* Legacy endpoints */}
<Route
path={`${WebsiteLegacyPaths.ZeroExJs}/:version?`}
diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx
index 3ede56a71..4d346327b 100644
--- a/packages/website/ts/pages/about/about.tsx
+++ b/packages/website/ts/pages/about/about.tsx
@@ -1,8 +1,7 @@
-import { colors, Styles } from '@0xproject/react-shared';
+import { colors, Link, Styles } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
-import { Link } from 'react-router-dom';
import { Footer } from 'ts/components/footer';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Profile } from 'ts/pages/about/profile';
@@ -389,7 +388,7 @@ export class About extends React.Component<AboutProps, AboutState> {
}}
>
We are seeking outstanding candidates to{' '}
- <Link to={WebsitePaths.Careers} style={{ color: 'black' }}>
+ <Link to={WebsitePaths.Careers} textDecoration="underline" fontColor="black">
join our team
</Link>
. We value passion, diversity and unique perspectives.
diff --git a/packages/website/ts/pages/documentation/developers_page.tsx b/packages/website/ts/pages/documentation/developers_page.tsx
new file mode 100644
index 000000000..e35218a70
--- /dev/null
+++ b/packages/website/ts/pages/documentation/developers_page.tsx
@@ -0,0 +1,182 @@
+import { colors, constants as sharedConstants } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import DocumentTitle = require('react-document-title');
+import { DocsLogo } from 'ts/components/documentation/docs_logo';
+import { DocsTopBar } from 'ts/components/documentation/docs_top_bar';
+import { Container } from 'ts/components/ui/container';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+import { utils } from 'ts/utils/utils';
+
+const THROTTLE_TIMEOUT = 100;
+const TOP_BAR_HEIGHT = 80;
+const SCROLLER_WIDTH = 4;
+
+export interface DevelopersPageProps {
+ location: Location;
+ translate: Translate;
+ screenWidth: ScreenWidths;
+ dispatcher: Dispatcher;
+ mainContent: React.ReactNode;
+ sidebar: React.ReactNode;
+}
+
+export interface DevelopersPageState {
+ isHoveringSidebar: boolean;
+ isHoveringMainContent: boolean;
+ isSidebarScrolling: boolean;
+}
+
+export class DevelopersPage extends React.Component<DevelopersPageProps, DevelopersPageState> {
+ private readonly _throttledScreenWidthUpdate: () => void;
+ private readonly _throttledSidebarScrolling: () => void;
+ private _sidebarScrollClearingInterval: number;
+ constructor(props: DevelopersPageProps) {
+ super(props);
+ this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+ this._throttledSidebarScrolling = _.throttle(this._onSidebarScroll.bind(this), THROTTLE_TIMEOUT);
+ this.state = {
+ isHoveringSidebar: false,
+ isHoveringMainContent: false,
+ isSidebarScrolling: false,
+ };
+ }
+ public componentDidMount(): void {
+ window.addEventListener('resize', this._throttledScreenWidthUpdate);
+ window.scrollTo(0, 0);
+ this._sidebarScrollClearingInterval = window.setInterval(() => {
+ this.setState({
+ isSidebarScrolling: false,
+ });
+ }, 1000);
+ }
+ public componentWillUnmount(): void {
+ window.removeEventListener('resize', this._throttledScreenWidthUpdate);
+ window.clearInterval(this._sidebarScrollClearingInterval);
+ }
+ public render(): React.ReactNode {
+ const scrollableContainerStyles: React.CSSProperties = {
+ position: 'absolute',
+ top: 80,
+ left: 0,
+ bottom: 0,
+ right: 0,
+ overflowX: 'hidden',
+ overflowY: 'scroll',
+ minHeight: `calc(100vh - ${TOP_BAR_HEIGHT}px)`,
+ WebkitOverflowScrolling: 'touch',
+ };
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ const mainContentPadding = isSmallScreen ? 20 : 50;
+ const sidebarPadding = 22;
+ return (
+ <Container
+ className="flex items-center overflow-hidden"
+ width="100%"
+ background={`linear-gradient(to right, ${colors.grey100} 0%, ${colors.grey100} 50%, ${
+ colors.white
+ } 50%, ${colors.white} 100%)`}
+ >
+ <DocumentTitle title="0x Docs DevelopersPage" />
+ <Container className="flex mx-auto" height="100vh">
+ <Container
+ className="sm-hide xs-hide relative"
+ width={234}
+ paddingLeft={22}
+ paddingRight={22}
+ paddingTop={0}
+ backgroundColor={colors.grey100}
+ >
+ <Container
+ borderBottom={this.state.isSidebarScrolling ? `1px solid ${colors.grey300}` : 'none'}
+ >
+ <Container paddingTop="30px" paddingLeft="10px" paddingBottom="8px">
+ <DocsLogo height={36} />
+ </Container>
+ </Container>
+ <div
+ style={{
+ ...scrollableContainerStyles,
+ paddingTop: 27,
+ overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden',
+ }}
+ onMouseEnter={this._onSidebarHover.bind(this, true)}
+ onMouseLeave={this._onSidebarHover.bind(this, false)}
+ onWheel={this._throttledSidebarScrolling}
+ >
+ <div
+ style={{
+ paddingBottom: 100,
+ paddingLeft: sidebarPadding,
+ paddingRight: this.state.isHoveringSidebar
+ ? sidebarPadding - SCROLLER_WIDTH
+ : sidebarPadding,
+ }}
+ >
+ {this.props.screenWidth !== ScreenWidths.Sm && this.props.sidebar}
+ </div>
+ </div>
+ </Container>
+ <Container
+ className="relative"
+ width={isSmallScreen ? '100vw' : 786}
+ paddingBottom="100px"
+ backgroundColor={colors.white}
+ >
+ <Container paddingLeft={mainContentPadding} paddingRight={mainContentPadding}>
+ <DocsTopBar
+ location={this.props.location}
+ screenWidth={this.props.screenWidth}
+ translate={this.props.translate}
+ sidebar={this.props.sidebar}
+ />
+ </Container>
+ <div
+ id={sharedConstants.SCROLL_CONTAINER_ID}
+ className="absolute"
+ style={{
+ ...scrollableContainerStyles,
+ paddingTop: 0,
+ paddingLeft: mainContentPadding,
+ paddingRight: this.state.isHoveringMainContent
+ ? mainContentPadding - SCROLLER_WIDTH
+ : mainContentPadding,
+ overflow: this.state.isHoveringMainContent ? 'auto' : 'hidden',
+ }}
+ onMouseEnter={this._onMainContentHover.bind(this, true)}
+ onMouseOver={this._onMainContentHover.bind(this, true)}
+ onMouseLeave={this._onMainContentHover.bind(this, false)}
+ >
+ {this.props.mainContent}
+ </div>
+ </Container>
+ </Container>
+ </Container>
+ );
+ }
+ private _onSidebarHover(isHovering: boolean, _event: React.FormEvent<HTMLInputElement>): void {
+ if (isHovering !== this.state.isHoveringSidebar) {
+ this.setState({
+ isHoveringSidebar: isHovering,
+ });
+ }
+ }
+ private _onMainContentHover(isHovering: boolean, _event: React.FormEvent<HTMLInputElement>): void {
+ if (isHovering !== this.state.isHoveringMainContent) {
+ this.setState({
+ isHoveringMainContent: isHovering,
+ });
+ }
+ }
+ private _onSidebarScroll(_event: React.FormEvent<HTMLInputElement>): void {
+ this.setState({
+ isSidebarScrolling: true,
+ });
+ }
+ private _updateScreenWidth(): void {
+ const newScreenWidth = utils.getScreenWidth();
+ this.props.dispatcher.updateScreenWidth(newScreenWidth);
+ }
+} // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx
index 135581fc9..40c728c24 100644
--- a/packages/website/ts/pages/documentation/doc_page.tsx
+++ b/packages/website/ts/pages/documentation/doc_page.tsx
@@ -1,35 +1,30 @@
import {
DocAgnosticFormat,
+ DocReference,
DocsInfo,
- Documentation,
GeneratedDocJson,
SupportedDocJson,
TypeDocUtils,
} from '@0xproject/react-docs';
+import { NestedSidebarMenu } from '@0xproject/react-shared';
import findVersions = require('find-versions');
import * as _ from 'lodash';
+import CircularProgress from 'material-ui/CircularProgress';
import * as React from 'react';
-import DocumentTitle = require('react-document-title');
import semverSort = require('semver-sort');
-import { SidebarHeader } from 'ts/components/sidebar_header';
-import { TopBar } from 'ts/components/top_bar/top_bar';
+import { SidebarHeader } from 'ts/components/documentation/sidebar_header';
+import { Container } from 'ts/components/ui/container';
+import { DevelopersPage } from 'ts/pages/documentation/developers_page';
import { Dispatcher } from 'ts/redux/dispatcher';
-import { DocPackages } from 'ts/types';
+import { DocPackages, ScreenWidths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { docUtils } from 'ts/utils/doc_utils';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
const isDevelopmentOrStaging = utils.isDevelopment() || utils.isStaging();
-const DEFAULT_ICON = 'docs.png';
const ZERO_EX_JS_VERSION_MISSING_TOPLEVEL_PATH = '0.32.4';
-const idToIcon: { [id: string]: string } = {
- [DocPackages.ZeroExJs]: 'zeroExJs.png',
- [DocPackages.Connect]: 'connect.png',
- [DocPackages.SmartContracts]: 'contracts.png',
-};
-
const docIdToSubpackageName: { [id: string]: string } = {
[DocPackages.ZeroExJs]: '0x.js',
[DocPackages.Connect]: 'connect',
@@ -53,6 +48,7 @@ export interface DocPageProps {
availableDocVersions: string[];
docsInfo: DocsInfo;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface DocPageState {
@@ -80,38 +76,58 @@ export class DocPage extends React.Component<DocPageProps, DocPageState> {
this._isUnmounted = true;
}
public render(): React.ReactNode {
- const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat)
- ? {}
- : this.props.docsInfo.getMenuSubsectionsBySection(this.state.docAgnosticFormat);
const sourceUrl = this._getSourceUrl();
- const iconFileName = idToIcon[this.props.docsInfo.id] || DEFAULT_ICON;
- const iconUrl = `/images/doc_icons/${iconFileName}`;
+ const sectionNameToLinks = _.isUndefined(this.state.docAgnosticFormat)
+ ? {}
+ : this.props.docsInfo.getSectionNameToLinks(this.state.docAgnosticFormat);
+ const mainContent = _.isUndefined(this.state.docAgnosticFormat) ? (
+ <div className="flex justify-center">{this._renderLoading()}</div>
+ ) : (
+ <DocReference
+ selectedVersion={this.props.docsVersion}
+ availableVersions={this.props.availableDocVersions}
+ docsInfo={this.props.docsInfo}
+ docAgnosticFormat={this.state.docAgnosticFormat}
+ sourceUrl={sourceUrl}
+ />
+ );
+ const sidebar = _.isUndefined(this.state.docAgnosticFormat) ? (
+ <div />
+ ) : (
+ <NestedSidebarMenu sidebarHeader={this._renderSidebarHeader()} sectionNameToLinks={sectionNameToLinks} />
+ );
+ return (
+ <DevelopersPage
+ sidebar={sidebar}
+ mainContent={mainContent}
+ location={this.props.location}
+ screenWidth={this.props.screenWidth}
+ translate={this.props.translate}
+ dispatcher={this.props.dispatcher}
+ />
+ );
+ }
+ private _renderSidebarHeader(): React.ReactNode {
+ return (
+ <SidebarHeader
+ screenWidth={this.props.screenWidth}
+ title={this.props.docsInfo.displayName}
+ docsVersion={this.props.docsVersion}
+ availableDocVersions={this.props.availableDocVersions}
+ onVersionSelected={this._onVersionSelected.bind(this)}
+ />
+ );
+ }
+ private _renderLoading(): React.ReactNode {
return (
- <div>
- <DocumentTitle title={`${this.props.docsInfo.displayName} Documentation`} />
- <TopBar
- blockchainIsLoaded={false}
- location={this.props.location}
- docsVersion={this.props.docsVersion}
- availableDocVersions={this.props.availableDocVersions}
- menu={this.props.docsInfo.menu}
- menuSubsectionsBySection={menuSubsectionsBySection}
- docsInfo={this.props.docsInfo}
- translate={this.props.translate}
- onVersionSelected={this._onVersionSelected.bind(this)}
- sidebarHeader={<SidebarHeader title={this.props.docsInfo.displayName} iconUrl={iconUrl} />}
- />
- <Documentation
- selectedVersion={this.props.docsVersion}
- availableVersions={this.props.availableDocVersions}
- docsInfo={this.props.docsInfo}
- docAgnosticFormat={this.state.docAgnosticFormat}
- sidebarHeader={<SidebarHeader title={this.props.docsInfo.displayName} iconUrl={iconUrl} />}
- sourceUrl={sourceUrl}
- topBarHeight={60}
- onVersionSelected={this._onVersionSelected.bind(this)}
- />
- </div>
+ <Container className="pt4">
+ <Container className="center pb2">
+ <CircularProgress size={40} thickness={5} />
+ </Container>
+ <Container className="center pt2" paddingBottom="11px">
+ Loading documentation...
+ </Container>
+ </Container>
);
}
private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> {
@@ -146,10 +162,10 @@ export class DocPage extends React.Component<DocPageProps, DocPageState> {
// documenting solidity.
docAgnosticFormat = versionDocObj as DocAgnosticFormat;
// HACK: need to modify docsInfo like convertToDocAgnosticFormat() would do
- this.props.docsInfo.menu.Contracts = [];
+ this.props.docsInfo.markdownMenu.Contracts = [];
_.each(docAgnosticFormat, (_docObj, sectionName) => {
this.props.docsInfo.sections[sectionName] = sectionName;
- this.props.docsInfo.menu.Contracts.push(sectionName);
+ this.props.docsInfo.markdownMenu.Contracts.push(sectionName);
});
}
diff --git a/packages/website/ts/pages/documentation/docs_home.tsx b/packages/website/ts/pages/documentation/docs_home.tsx
new file mode 100644
index 000000000..f0af78fc1
--- /dev/null
+++ b/packages/website/ts/pages/documentation/docs_home.tsx
@@ -0,0 +1,384 @@
+import { ALink, colors, Link, NestedSidebarMenu } from '@0xproject/react-shared';
+import { ObjectMap } from '@0xproject/types';
+import * as _ from 'lodash';
+import * as React from 'react';
+import { OverviewContent } from 'ts/components/documentation/overview_content';
+import { Button } from 'ts/components/ui/button';
+import { DevelopersPage } from 'ts/pages/documentation/developers_page';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { Categories, Deco, Key, Package, ScreenWidths, TutorialInfo, WebsitePaths } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { Translate } from 'ts/utils/translate';
+
+const TUTORIALS: TutorialInfo[] = [
+ {
+ iconUrl: '/images/developers/tutorials/develop_on_ethereum.svg',
+ description: Key.DevelopOnEthereumDescription,
+ link: {
+ title: Key.DevelopOnEthereum,
+ to: `${WebsitePaths.Wiki}#Ethereum-Development`,
+ },
+ },
+ {
+ iconUrl: '/images/developers/tutorials/build_a_relayer.svg',
+ description: Key.BuildARelayerDescription,
+ link: {
+ title: Key.BuildARelayer,
+ to: `${WebsitePaths.Wiki}#Build-A-Relayer`,
+ },
+ },
+ {
+ iconUrl: '/images/developers/tutorials/0x_order_basics.svg',
+ description: Key.OrderBasicsDescription,
+ link: {
+ title: Key.OrderBasics,
+ to: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`,
+ },
+ },
+ {
+ iconUrl: '/images/developers/tutorials/use_shared_liquidity.svg',
+ description: Key.UseSharedLiquidityDescription,
+ link: {
+ title: Key.UseSharedLiquidity,
+ to: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`,
+ },
+ },
+];
+
+const CATEGORY_TO_PACKAGES: ObjectMap<Package[]> = {
+ [Categories.ZeroExProtocol]: [
+ {
+ description:
+ 'A library for interacting with the 0x protocol. It is a high level package which combines a number of smaller specific-purpose packages such as [order-utils](https://0xproject.com/docs/order-utils) and [contract-wrappers](https://0xproject.com/docs/contract-wrappers).',
+ link: {
+ title: '0x.js',
+ to: WebsitePaths.ZeroExJs,
+ },
+ },
+ {
+ description:
+ 'A Typescript starter project that will walk you through the basics of how to interact with 0x Protocol and trade of an SRA relayer',
+ link: {
+ title: '0x starter project',
+ to: 'https://github.com/0xProject/0x-starter-project',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'An http & websocket client for interacting with relayers that have implemented the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api)',
+ link: {
+ title: '@0xproject/connect',
+ to: WebsitePaths.Connect,
+ },
+ },
+ {
+ description:
+ 'Typescript/Javascript wrappers of the 0x protocol Ethereum smart contracts. Use this library to call methods on the 0x smart contracts, subscribe to contract events and to fetch information stored in contracts.',
+ link: {
+ title: '@0xproject/contract-wrappers',
+ to: WebsitePaths.ContractWrappers,
+ },
+ },
+ {
+ description:
+ 'A collection of 0x-related JSON-schemas (incl. SRA request/response schemas, 0x order message format schema, etc...)',
+ link: {
+ title: '@0xproject/json-schemas',
+ to: WebsitePaths.JSONSchemas,
+ },
+ },
+ {
+ description:
+ 'A set of utils for working with 0x orders. It includes utilities for creating, signing, validating 0x orders, encoding/decoding assetData and much more.',
+ link: {
+ title: '@0xproject/order-utils',
+ to: WebsitePaths.OrderUtils,
+ },
+ },
+ {
+ description:
+ "A daemon that watches a set of 0x orders and emits events when an order's fillability has changed. Can be used by a relayer to prune their orderbook or by a trader to keep their view of the market up-to-date.",
+ link: {
+ title: '@0xproject/order-watcher',
+ to: WebsitePaths.OrderWatcher,
+ },
+ },
+ {
+ description:
+ 'Contains the Standard Relayer API OpenAPI Spec. The package distributes both a javascript object version and a json version.',
+ link: {
+ title: '@0xproject/sra-spec',
+ to: 'https://github.com/0xProject/0x-monorepo/tree/development/packages/sra-spec',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'Convenience package for buying assets represented on the Ethereum blockchain using 0x. In its simplest form, the package helps in the usage of the [0x forwarder contract](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md), which allows users to execute [Wrapped Ether](https://weth.io/) based 0x orders without having to set allowances, wrap Ether or own ZRX, meaning they can buy tokens with Ether alone. Given some liquidity (0x signed orders), it helps estimate the Ether cost of buying a certain asset (giving a range) and then buying that asset.',
+ link: {
+ title: '@0xproject/asset-buyer',
+ to: WebsitePaths.AssetBuyer,
+ },
+ },
+ ],
+ [Categories.Ethereum]: [
+ {
+ description:
+ "This package allows you to generate TypeScript contract wrappers from ABI files. It's heavily inspired by Geth abigen but takes a different approach. You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.",
+ link: {
+ title: 'abi-gen',
+ to: 'https://github.com/0xProject/0x-monorepo/tree/development/packages/abi-gen',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'A collection of Typescript types that are useful when working on an Ethereum-based project (e.g RawLog, Transaction, TxData, SolidityTypes, etc...).',
+ link: {
+ title: 'ethereum-types',
+ to: WebsitePaths.EthereumTypes,
+ },
+ },
+ {
+ description:
+ 'A wrapper around [solc-js](https://github.com/ethereum/solc-js) that adds smart re-compilation, ability to compile an entire project, Solidity version specific compilation, standard input description support and much more.',
+ link: {
+ title: '@0xproject/sol-compiler',
+ to: WebsitePaths.SolCompiler,
+ },
+ },
+ {
+ description:
+ 'A Solidity code coverage tool. Sol-cov uses transaction traces to figure out which lines of your code has been covered by your tests.',
+ link: {
+ title: '@0xproject/sol-cov',
+ to: WebsitePaths.SolCov,
+ },
+ },
+ {
+ description:
+ 'A collection of subproviders to use with [web3-provider-engine](https://www.npmjs.com/package/web3-provider-engine) (e.g subproviders for interfacing with Ledger hardware wallet, Mnemonic wallet, private key wallet, etc...)',
+ link: {
+ title: '@0xproject/subproviders',
+ to: WebsitePaths.Subproviders,
+ },
+ },
+ {
+ description:
+ 'A raw Ethereum JSON RPC client to simplify interfacing with Ethereum nodes. Also includes some convenience functions for awaiting transactions to be mined, converting between token units, etc...',
+ link: {
+ title: '@0xproject/web3-wrapper',
+ to: WebsitePaths.Web3Wrapper,
+ },
+ },
+ ],
+ [Categories.CommunityMaintained]: [
+ {
+ description:
+ 'Node.js worker originally built for 0x Tracker which extracts 0x fill events from the Ethereum blockchain and persists them to MongoDB. Support for both V1 and V2 of the 0x protocol is included with events tagged against the protocol version they belong to.',
+ link: {
+ title: '0x Event Extractor',
+ to: 'https://github.com/0xTracker/0x-event-extractor',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'Node.js worker built for 0x Tracker which performs various ETL tasks related to the 0x protocol trading data and other information used on 0x Tracker.',
+ link: {
+ title: '0x Tracker Worker',
+ to: 'https://github.com/0xTracker/0x-tracker-worker',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ "ERCdex's Javascript SDK for trading on their relayer, as well as other Aquaduct partner relayers",
+ link: {
+ title: 'Aquaduct',
+ to: 'https://www.npmjs.com/package/aqueduct',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'SDKs for automation using Aqueduct & ERC dEX. Aqueduct Server is a lightweight, portable and secure server that runs locally on any workstation. The server exposes a small number of foundational endpoints that enable working with the decentralized Aqueduct liquidity pool from any context or programming language.',
+ link: {
+ title: 'Aquaduct Server SDK',
+ to: 'https://github.com/ERCdEX/aqueduct-server-sdk',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: 'A node.js SDK for trading on the DDEX relayer',
+ link: {
+ to: 'https://www.npmjs.com/package/ddex-api',
+ title: 'DDEX Node.js SDK',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: "The ERC dEX Trade Widget let's any website provide token liquidity to it's users",
+ link: {
+ to: 'https://github.com/ERCdEX/widget',
+ title: 'ERCdex Widget',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: "ERCdex's Java SDK for trading on their relayer, as well as other Aquaduct partner relayers",
+ link: {
+ to: 'https://github.com/ERCdEX/java',
+ title: 'ERCdex Java SDK',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: "ERCdex's Python SDK for trading on their relayer, as well as other Aquaduct partner relayers",
+ link: {
+ to: 'https://github.com/ERCdEX/python',
+ title: 'ERCdex Python SDK',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'A set of command-line tools for creating command-line scripts for interacting with the Ethereum blockchain in general, and 0x in particular',
+ link: {
+ title: 'Massive',
+ to: 'https://github.com/NoteGio/massive',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: 'An open-source API-only Relayer written in Go',
+ link: {
+ to: 'https://github.com/NoteGio/openrelay',
+ title: 'OpenRelay',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'A JavaScript Library for Interacting with OpenRelay.xyz and other 0x Standard Relayer API Implementations',
+ link: {
+ title: 'OpenRelay.js',
+ to: 'https://github.com/NoteGio/openrelay.js',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'The Radar Relay SDK is a software development kit that simplifies the interactions with Radar Relay’s APIs',
+ link: {
+ title: 'Radar SDK',
+ to: 'https://github.com/RadarRelay/sdk',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description:
+ 'The Ocean provides a simple REST API, WebSockets API, and JavaScript library to help you integrate decentralized trading into your existing trading strategy.',
+ link: {
+ title: 'The Ocean Javascript SDK',
+ to: 'https://github.com/TheOceanTrade/theoceanx-javascript',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: "Tokenlon SDK provides APIs for developers to trade of imToken's relayer",
+ link: {
+ to: 'https://www.npmjs.com/package/tokenlon-sdk',
+ title: 'Tokenlon Javascript SDK',
+ shouldOpenInNewTab: true,
+ },
+ },
+ {
+ description: 'A small library that implements the 0x order assetData encoding/decoding in Java',
+ link: {
+ to: 'https://github.com/wildnothing/asset-data-decoder',
+ title: 'AssetData decoder library in Java',
+ shouldOpenInNewTab: true,
+ },
+ },
+ ],
+};
+
+export interface DocsHomeProps {
+ location: Location;
+ translate: Translate;
+ screenWidth: ScreenWidths;
+ tutorials: TutorialInfo[];
+ categoryToPackages: ObjectMap<Package[]>;
+ dispatcher: Dispatcher;
+}
+
+export interface DocsHomeState {}
+
+export class DocsHome extends React.Component<DocsHomeProps, DocsHomeState> {
+ public render(): React.ReactNode {
+ const sectionNameToLinks: ObjectMap<ALink[]> = {
+ 'Starter guides': _.map(TUTORIALS, tutorialInfo => {
+ return {
+ ...tutorialInfo.link,
+ title: this.props.translate.get(tutorialInfo.link.title as Key, Deco.Cap),
+ };
+ }),
+ [Categories.ZeroExProtocol]: _.map(CATEGORY_TO_PACKAGES[Categories.ZeroExProtocol], pkg => pkg.link),
+ [Categories.Ethereum]: _.map(CATEGORY_TO_PACKAGES[Categories.Ethereum], pkg => pkg.link),
+ [Categories.CommunityMaintained]: _.map(
+ CATEGORY_TO_PACKAGES[Categories.CommunityMaintained],
+ pkg => pkg.link,
+ ),
+ };
+ const mainContent = (
+ <OverviewContent
+ translate={this.props.translate}
+ tutorials={TUTORIALS}
+ categoryToPackages={CATEGORY_TO_PACKAGES}
+ />
+ );
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ const sidebar = (
+ <NestedSidebarMenu
+ sidebarHeader={isSmallScreen ? this._renderSidebarHeader() : undefined}
+ sectionNameToLinks={sectionNameToLinks}
+ shouldReformatMenuItemNames={false}
+ />
+ );
+ return (
+ <DevelopersPage
+ mainContent={mainContent}
+ sidebar={sidebar}
+ location={this.props.location}
+ screenWidth={this.props.screenWidth}
+ translate={this.props.translate}
+ dispatcher={this.props.dispatcher}
+ />
+ );
+ }
+ private _renderSidebarHeader(): React.ReactNode {
+ const menuItems = _.map(constants.DEVELOPER_TOPBAR_LINKS, menuItemInfo => {
+ return (
+ <Link
+ key={`menu-item-${menuItemInfo.title}`}
+ to={menuItemInfo.to}
+ shouldOpenInNewTab={menuItemInfo.shouldOpenInNewTab}
+ >
+ <Button
+ borderRadius="4px"
+ padding="0.4em 6px"
+ width="100%"
+ fontColor={colors.grey800}
+ fontSize="14px"
+ textAlign="left"
+ >
+ {this.props.translate.get(menuItemInfo.title as Key, Deco.Cap)}
+ </Button>
+ </Link>
+ );
+ });
+ return menuItems;
+ }
+}
diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx
index 388e83d51..f7a6fe0ce 100644
--- a/packages/website/ts/pages/landing/landing.tsx
+++ b/packages/website/ts/pages/landing/landing.tsx
@@ -1,8 +1,7 @@
-import { colors } from '@0xproject/react-shared';
+import { colors, Link } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import DocumentTitle = require('react-document-title');
-import { Link } from 'react-router-dom';
import { Footer } from 'ts/components/footer';
import { SubscribeForm } from 'ts/components/forms/subscribe_form';
import { TopBar } from 'ts/components/top_bar/top_bar';
@@ -213,14 +212,14 @@ export class Landing extends React.Component<LandingProps, LandingState> {
className={`pt3 flex clearfix sm-mx-auto ${isSmallScreen ? 'justify-center' : ''}`}
>
<Container paddingRight="20px">
- <Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
+ <Link to={WebsitePaths.Docs}>
<CallToAction type="light">
{this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
</CallToAction>
</Link>
</Container>
<div>
- <Link to={WebsitePaths.Portal} className="text-decoration-none">
+ <Link to={WebsitePaths.Portal}>
<CallToAction>
{this.props.translate.get(Key.TradeCallToAction, Deco.Cap)}
</CallToAction>
@@ -318,11 +317,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
}}
>
{this.props.translate.get(Key.FullListPrompt)}{' '}
- <Link
- to={WebsitePaths.Portal}
- className="text-decoration-none underline"
- style={{ color: colors.landingLinkGrey }}
- >
+ <Link to={WebsitePaths.Portal} textDecoration="underline" fontColor={colors.landingLinkGrey}>
{this.props.translate.get(Key.FullListLink)}
</Link>
</div>
@@ -603,7 +598,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
{this.props.translate.get(Key.FinalCallToAction, Deco.Cap)}
</div>
<div className="sm-center sm-pt2 lg-table-cell md-table-cell">
- <Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
+ <Link to={WebsitePaths.Docs}>
<CallToAction fontSize="15px">
{this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
</CallToAction>
diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx
index 55f532b11..76d52c9bd 100644
--- a/packages/website/ts/pages/wiki/wiki.tsx
+++ b/packages/website/ts/pages/wiki/wiki.tsx
@@ -1,27 +1,28 @@
import {
+ ALink,
colors,
constants as sharedConstants,
HeaderSizes,
+ Link,
MarkdownSection,
NestedSidebarMenu,
- Styles,
utils as sharedUtils,
} from '@0xproject/react-shared';
+import { ObjectMap } from '@0xproject/types';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
-import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
-import DocumentTitle = require('react-document-title');
-import { SidebarHeader } from 'ts/components/sidebar_header';
-import { TopBar } from 'ts/components/top_bar/top_bar';
+import { SidebarHeader } from 'ts/components/documentation/sidebar_header';
+import { Button } from 'ts/components/ui/button';
+import { Container } from 'ts/components/ui/container';
+import { DevelopersPage } from 'ts/pages/documentation/developers_page';
import { Dispatcher } from 'ts/redux/dispatcher';
-import { Article, ArticlesBySection } from 'ts/types';
+import { Article, ArticlesBySection, Deco, Key, ScreenWidths } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
-const TOP_BAR_HEIGHT = 60;
const WIKI_NOT_READY_BACKOUT_TIMEOUT_MS = 5000;
export interface WikiProps {
@@ -29,6 +30,7 @@ export interface WikiProps {
location: Location;
dispatcher: Dispatcher;
translate: Translate;
+ screenWidth: ScreenWidths;
}
interface WikiState {
@@ -36,24 +38,6 @@ interface WikiState {
isHoveringSidebar: boolean;
}
-const styles: Styles = {
- mainContainers: {
- position: 'absolute',
- top: 1,
- left: 0,
- bottom: 0,
- right: 0,
- overflow: 'hidden',
- height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`,
- WebkitOverflowScrolling: 'touch',
- },
- menuContainer: {
- borderColor: colors.grey300,
- maxWidth: 330,
- backgroundColor: colors.gray40,
- },
-};
-
export class Wiki extends React.Component<WikiProps, WikiState> {
private _wikiBackoffTimeoutId: number;
private _isUnmounted: boolean;
@@ -78,89 +62,73 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
window.removeEventListener('hashchange', this._onHashChanged.bind(this), false);
}
public render(): React.ReactNode {
- const menuSubsectionsBySection = _.isUndefined(this.state.articlesBySection)
+ const sectionNameToLinks = _.isUndefined(this.state.articlesBySection)
? {}
- : this._getMenuSubsectionsBySection(this.state.articlesBySection);
- const mainContainersStyle: React.CSSProperties = {
- ...styles.mainContainers,
- overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden',
- };
- const sidebarHeader = <SidebarHeader title="Wiki" iconUrl="/images/doc_icons/wiki.png" />;
- return (
- <div>
- <DocumentTitle title="0x Protocol Wiki" />
- <TopBar
- blockchainIsLoaded={false}
- location={this.props.location}
- menuSubsectionsBySection={menuSubsectionsBySection}
- translate={this.props.translate}
- sidebarHeader={sidebarHeader}
- />
- {_.isUndefined(this.state.articlesBySection) ? (
- <div className="col col-12" style={mainContainersStyle}>
- <div
- className="relative sm-px2 sm-pt2 sm-m1"
- style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
- >
- <div className="center pb2">
- <CircularProgress size={40} thickness={5} />
- </div>
- <div className="center pt2" style={{ paddingBottom: 11 }}>
- Loading wiki...
- </div>
- </div>
- </div>
- ) : (
- <div style={{ width: '100%', height: '100%', backgroundColor: colors.gray40 }}>
- <div
- className="mx-auto max-width-4 flex"
- style={{ color: colors.grey800, height: `calc(100vh - ${TOP_BAR_HEIGHT}px)` }}
- >
- <div
- className="relative lg-pl0 md-pl1 sm-hide xs-hide"
- style={{ height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, width: '36%' }}
- >
- <div
- className="absolute"
- style={{
- ...styles.menuContainer,
- ...mainContainersStyle,
- height: 'calc(100vh - 76px)',
- }}
- onMouseEnter={this._onSidebarHover.bind(this)}
- onMouseLeave={this._onSidebarHoverOff.bind(this)}
- >
- <NestedSidebarMenu
- topLevelMenu={menuSubsectionsBySection}
- menuSubsectionsBySection={menuSubsectionsBySection}
- sidebarHeader={sidebarHeader}
- />
- </div>
- </div>
- <div
- className="relative"
- style={{
- width: '100%',
- height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`,
- backgroundColor: 'white',
- }}
- >
- <div
- id={sharedConstants.SCROLL_CONTAINER_ID}
- style={{ ...mainContainersStyle, overflow: 'auto' }}
- className="absolute"
- >
- <div id={sharedConstants.SCROLL_TOP_ID} />
- <div id="wiki" style={{ paddingRight: 2 }}>
- {this._renderWikiArticles()}
- </div>
- </div>
- </div>
- </div>
- </div>
- )}
+ : this._getSectionNameToLinks(this.state.articlesBySection);
+
+ const mainContent = _.isUndefined(this.state.articlesBySection) ? (
+ <div className="flex justify-center">{this._renderLoading()}</div>
+ ) : (
+ <div id="wiki" style={{ paddingRight: 2 }}>
+ {this._renderWikiArticles()}
</div>
);
+ const sidebar = _.isUndefined(this.state.articlesBySection) ? (
+ <div />
+ ) : (
+ <NestedSidebarMenu sidebarHeader={this._renderSidebarHeader()} sectionNameToLinks={sectionNameToLinks} />
+ );
+ return (
+ <DevelopersPage
+ sidebar={sidebar}
+ mainContent={mainContent}
+ location={this.props.location}
+ screenWidth={this.props.screenWidth}
+ translate={this.props.translate}
+ dispatcher={this.props.dispatcher}
+ />
+ );
+ }
+ private _renderSidebarHeader(): React.ReactNode {
+ const menuItems = _.map(constants.DEVELOPER_TOPBAR_LINKS, menuItemInfo => {
+ return (
+ <Link
+ key={`menu-item-${menuItemInfo.title}`}
+ to={menuItemInfo.to}
+ shouldOpenInNewTab={menuItemInfo.shouldOpenInNewTab}
+ >
+ <Button
+ borderRadius="4px"
+ padding="0.4em 6px"
+ width="100%"
+ fontColor={colors.grey800}
+ fontSize="14px"
+ textAlign="left"
+ >
+ {this.props.translate.get(menuItemInfo.title as Key, Deco.Cap)}
+ </Button>
+ </Link>
+ );
+ });
+ const wikiTitle = this.props.translate.get(Key.Wiki, Deco.Cap);
+ return (
+ <Container>
+ <SidebarHeader screenWidth={this.props.screenWidth} title={wikiTitle} />
+ {menuItems}
+ </Container>
+ );
+ }
+ private _renderLoading(): React.ReactNode {
+ return (
+ <Container className="pt4">
+ <Container className="center pb2">
+ <CircularProgress size={40} thickness={5} />
+ </Container>
+ <Container className="center pt2" paddingBottom="11px">
+ Loading wiki...
+ </Container>
+ </Container>
+ );
}
private _renderWikiArticles(): React.ReactNode {
const sectionNames = _.keys(this.state.articlesBySection);
@@ -179,22 +147,10 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
headerSize={HeaderSizes.H2}
githubLink={githubLink}
/>
- <div className="clearfix mb3 mt2 p3 mx-auto lg-flex md-flex sm-pb4" style={{ maxWidth: 390 }}>
- <div className="sm-col sm-col-12 sm-center" style={{ opacity: 0.4, lineHeight: 2.5 }}>
- See a way to improve this article?
- </div>
- <div className="sm-col sm-col-12 lg-col-7 md-col-7 sm-center sm-pt2">
- <RaisedButton href={githubLink} target="_blank" label="Edit on Github" />
- </div>
- </div>
</div>
);
});
- return (
- <div key={`section-${sectionName}`} className="py2 md-px1 sm-px0">
- {renderedArticles}
- </div>
- );
+ return <div key={`section-${sectionName}`}>{renderedArticles}</div>;
}
private async _fetchArticlesBySectionAsync(): Promise<void> {
try {
@@ -223,25 +179,20 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
}
}
}
- private _getMenuSubsectionsBySection(articlesBySection: ArticlesBySection): { [section: string]: string[] } {
+ private _getSectionNameToLinks(articlesBySection: ArticlesBySection): ObjectMap<ALink[]> {
const sectionNames = _.keys(articlesBySection);
- const menuSubsectionsBySection: { [section: string]: string[] } = {};
+ const sectionNameToLinks: ObjectMap<ALink[]> = {};
for (const sectionName of sectionNames) {
const articles = articlesBySection[sectionName];
- const articleNames = _.map(articles, article => article.title);
- menuSubsectionsBySection[sectionName] = articleNames;
+ const articleLinks = _.map(articles, article => {
+ return {
+ to: sharedUtils.getIdFromName(article.title),
+ title: article.title,
+ };
+ });
+ sectionNameToLinks[sectionName] = articleLinks;
}
- return menuSubsectionsBySection;
- }
- private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
- this.setState({
- isHoveringSidebar: true,
- });
- }
- private _onSidebarHoverOff(): void {
- this.setState({
- isHoveringSidebar: false,
- });
+ return sectionNameToLinks;
}
private _onHashChanged(_event: any): void {
const hash = window.location.hash.slice(1);
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index 7e140c951..84be4d3b0 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -1,3 +1,4 @@
+import { ALink } from '@0xproject/react-shared';
import { ObjectMap, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Provider } from 'ethereum-types';
@@ -461,6 +462,23 @@ export enum Key {
RocketChat = 'ROCKETCHAT',
TradeCallToAction = 'TRADE_CALL_TO_ACTION',
OurMissionAndValues = 'OUR_MISSION_AND_VALUES',
+ BuildARelayer = 'BUILD_A_RELAYER',
+ BuildARelayerDescription = 'BUILD_A_RELAYER_DESCRIPTION',
+ DevelopOnEthereum = 'DEVELOP_ON_ETHEREUM',
+ DevelopOnEthereumDescription = 'DEVELOP_ON_ETHEREUM_DESCRIPTION',
+ OrderBasics = 'ORDER_BASICS',
+ OrderBasicsDescription = 'ORDER_BASICS_DESCRIPTION',
+ UseSharedLiquidity = 'USE_SHARED_LIQUIDITY',
+ UseSharedLiquidityDescription = 'USE_SHARED_LIQUIDITY_DESCRIPTION',
+ ViewAllDocumentation = 'VIEW_ALL_DOCUMENTATION',
+ Sandbox = 'SANDBOX',
+ Github = 'GITHUB',
+ LiveChat = 'LIVE_CHAT',
+ LibrariesAndTools = 'LIBRARIES_AND_TOOLS',
+ LibrariesAndToolsDescription = 'LIBRARIES_AND_TOOLS_DESCRIPTION',
+ More = 'MORE',
+ StartBuildOn0x = 'START_BUILDING_ON_0X',
+ StartBuildOn0xDescription = 'START_BUILDING_ON_0X_DESCRIPTION',
}
export enum SmartContractDocSections {
@@ -603,4 +621,21 @@ export interface InjectedWeb3 {
getNetwork(cd: (err: Error, networkId: string) => void): void;
};
}
+
+export interface TutorialInfo {
+ iconUrl: string;
+ description: string;
+ link: ALink;
+}
+
+export enum Categories {
+ ZeroExProtocol = '0x Protocol',
+ Ethereum = 'Ethereum',
+ CommunityMaintained = 'Community Maintained',
+}
+
+export interface Package {
+ description: string;
+ link: ALink;
+}
// tslint:disable:max-file-line-count
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index 18a4d8100..e76d40bd3 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -1,4 +1,9 @@
+import { ALink } from '@0xproject/react-shared';
import { BigNumber } from '@0xproject/utils';
+import { Key, WebsitePaths } from 'ts/types';
+
+const URL_FORUM = 'https://forum.0xproject.com';
+const URL_ZEROEX_CHAT = 'https://chat.0xproject.com';
export const constants = {
DECIMAL_PLACES_ETH: 18,
@@ -74,6 +79,7 @@ export const constants = {
URL_TESTNET_FAUCET: 'https://faucet.0xproject.com',
URL_GITHUB_ORG: 'https://github.com/0xProject',
URL_GITHUB_WIKI: 'https://github.com/0xProject/wiki',
+ URL_FORUM,
URL_METAMASK_CHROME_STORE: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
URL_METAMASK_FIREFOX_STORE: 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/',
URL_COINBASE_WALLET_IOS_APP_STORE: 'https://itunes.apple.com/us/app/coinbase-wallet/id1278383455?mt=8',
@@ -84,10 +90,11 @@ export const constants = {
URL_PARITY_CHROME_STORE:
'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig',
URL_REDDIT: 'https://reddit.com/r/0xproject',
+ URL_SANDBOX: 'https://codesandbox.io/s/1qmjyp7p5j',
URL_STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md',
URL_TWITTER: 'https://twitter.com/0xproject',
URL_WETH_IO: 'https://weth.io/',
- URL_ZEROEX_CHAT: 'https://chat.0xproject.com',
+ URL_ZEROEX_CHAT,
URL_WEB3_DOCS: 'https://github.com/ethereum/wiki/wiki/JavaScript-API',
URL_WEB3_DECODED_LOG_ENTRY_EVENT:
'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123',
@@ -95,4 +102,24 @@ export const constants = {
URL_WEB3_PROVIDER_DOCS: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150',
URL_BIGNUMBERJS_GITHUB: 'http://mikemcl.github.io/bignumber.js',
URL_MISSION_AND_VALUES_BLOG_POST: 'https://blog.0xproject.com/the-0x-mission-and-values-181a58706f9f',
+ DEVELOPER_TOPBAR_LINKS: [
+ {
+ title: Key.Home,
+ to: WebsitePaths.Home,
+ },
+ {
+ title: Key.Wiki,
+ to: WebsitePaths.Wiki,
+ },
+ {
+ title: Key.Forum,
+ to: URL_FORUM,
+ shouldOpenInNewTab: true,
+ },
+ {
+ title: Key.LiveChat,
+ to: URL_ZEROEX_CHAT,
+ shouldOpenInNewTab: true,
+ },
+ ] as ALink[],
};
diff --git a/packages/website/ts/utils/translate.ts b/packages/website/ts/utils/translate.ts
index 1ee1a59c5..5595e6e0f 100644
--- a/packages/website/ts/utils/translate.ts
+++ b/packages/website/ts/utils/translate.ts
@@ -80,7 +80,12 @@ export class Translate {
case Deco.CapWords:
const words = text.split(' ');
- const capitalizedWords = _.map(words, w => this._capitalize(w));
+ const capitalizedWords = _.map(words, (w: string, i: number) => {
+ if (w.length === 1) {
+ return w;
+ }
+ return this._capitalize(w);
+ });
text = capitalizedWords.join(' ');
break;