diff --git a/packages/website/public/css/formular.css b/packages/website/public/css/formular.css index 85549f8c87..bbe7b0871f 100644 --- a/packages/website/public/css/formular.css +++ b/packages/website/public/css/formular.css @@ -43,3 +43,10 @@ src: url('../fonts/Formular-Regular.woff2') format('woff2'), url('../fonts/Formular-Regular.woff') format('woff'); font-display: swap; } + +@font-face { + font-family: 'Formular Mono'; + src: url('../fonts/Formular-Mono.woff') format('truetype'); + font-weight: 400; + font-style: normal; + } \ No newline at end of file diff --git a/packages/website/public/fonts/Formular-Mono.woff b/packages/website/public/fonts/Formular-Mono.woff new file mode 100644 index 0000000000..9ad89f7939 Binary files /dev/null and b/packages/website/public/fonts/Formular-Mono.woff differ diff --git a/packages/website/ts/components/docs/callout.tsx b/packages/website/ts/components/docs/callout.tsx index dd5790e6ab..1595e26105 100644 --- a/packages/website/ts/components/docs/callout.tsx +++ b/packages/website/ts/components/docs/callout.tsx @@ -64,7 +64,7 @@ Callout.defaultProps = { type: 'standard', }; -const Wrapper = styled.a` +const Wrapper = styled.div` background-color: ${props => ThemeSettings[props.type].bgColor}; color: ${colors.textDarkPrimary}; padding: 1rem 1rem 1rem 1rem; diff --git a/packages/website/ts/components/docs/feature_link.tsx b/packages/website/ts/components/docs/feature_link.tsx new file mode 100644 index 0000000000..eff1b90083 --- /dev/null +++ b/packages/website/ts/components/docs/feature_link.tsx @@ -0,0 +1,54 @@ +import { Link } from '@0x/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; +import styled, { withTheme } from 'styled-components'; + +import { Button } from 'ts/components/button'; +import { SearchInput } from 'ts/components/docs/search_input'; +import { Icon } from 'ts/components/icon'; +import { Column, FlexWrap, WrapGrid } from 'ts/components/newLayout'; +import { ThemeValuesInterface } from 'ts/components/siteWrap'; +import { Heading, Paragraph } from 'ts/components/text'; +import { colors } from 'ts/style/colors'; +import { WebsitePaths } from 'ts/types'; +import { constants } from 'ts/utils/constants'; + +export interface LinkProps { + heading: string; + icon: string; + description?: string; + url: string; + shouldOpenInNewTab?: boolean; +} + +interface WrapperProps { +} + +export const FeatureLink: React.FunctionComponent = (props: LinkProps) => ( + <> + + + + {props.heading} + {props.description} + + + + + + +); + +const Wrapper = styled.a` + background-color: ${colors.backgroundLight}; + border: 1px solid #DBDFDD; + padding: 30px 30px; + display: flex; + align-items: center; + margin-bottom: 0.555555556rem; +`; + +const Content = styled.div` + margin-right: auto; + padding-right: 30px; +`; diff --git a/packages/website/ts/components/docs/header.tsx b/packages/website/ts/components/docs/header.tsx index f0a71f1b67..f8819153e1 100644 --- a/packages/website/ts/components/docs/header.tsx +++ b/packages/website/ts/components/docs/header.tsx @@ -46,13 +46,13 @@ const navItems: NavItemProps[] = [ text: 'API Explorer', }, { - id: 'tutorials', - url: WebsitePaths.AboutMission, - text: 'Tutorials', + id: 'guides', + url: '/docs/guides', + text: 'Guides', }, { id: 'tools', - url: WebsitePaths.AboutMission, + url: '/docs/tools', text: 'Tools', }, ]; diff --git a/packages/website/ts/components/docs/helpful_cta.tsx b/packages/website/ts/components/docs/helpful_cta.tsx new file mode 100644 index 0000000000..aefb8694be --- /dev/null +++ b/packages/website/ts/components/docs/helpful_cta.tsx @@ -0,0 +1,66 @@ +import { Link } from '@0x/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; +import styled, { withTheme } from 'styled-components'; + +import { Button } from 'ts/components/button'; +import { SearchInput } from 'ts/components/docs/search_input'; +import { Icon } from 'ts/components/icon'; +import { Column, FlexWrap, WrapGrid } from 'ts/components/newLayout'; +import { ThemeValuesInterface } from 'ts/components/siteWrap'; +import { Heading, Paragraph } from 'ts/components/text'; +import { colors } from 'ts/style/colors'; +import { WebsitePaths } from 'ts/types'; +import { constants } from 'ts/utils/constants'; + +export interface HelpfulCtaProps { + heading?: string; + description?: string; + url?: string; +} + +export const HelpfulCta: React.FunctionComponent = (props: HelpfulCtaProps) => ( + <> + + Was this page helpful + + Yes + No + + + +); + +HelpfulCta.defaultProps = { + heading: 'Need some help?', + description: 'Get in touch here and we’ll be happy to help.', +}; + +const Wrapper = styled.div` + display: flex; + align-items: center; + margin-bottom: 1.875rem; +`; + +const Text = styled(Paragraph)` + color: ${colors.textDarkPrimary}; + font-size: 1.111111111rem; + font-weight: 400; + margin-bottom: 0; + opacity: 1; +`; + +const Buttons = styled.div` + display: flex; + align-items: center; + margin-left: 40px; +`; + +const CtaButton = styled(Button)` + padding: 8px 30px 6px; + font-size: 1rem; + + & + & { + margin-left: 10px; + } +`; diff --git a/packages/website/ts/components/docs/hero.tsx b/packages/website/ts/components/docs/hero.tsx index a1fc88f90d..9fe488fce8 100644 --- a/packages/website/ts/components/docs/hero.tsx +++ b/packages/website/ts/components/docs/hero.tsx @@ -44,7 +44,7 @@ const Wrapper = styled.div` padding-bottom: 80px; margin-bottom: 60px; min-height: 15rem; - min-height: 21.875rem; + min-height: ${props => props.isHome ? '21.875rem' : '13.222rem'}; display: flex; flex-direction: column; justify-content: center; diff --git a/packages/website/ts/components/docs/newsletter_signup.tsx b/packages/website/ts/components/docs/newsletter_signup.tsx index 82f5a1a835..6bc2e6b3b5 100644 --- a/packages/website/ts/components/docs/newsletter_signup.tsx +++ b/packages/website/ts/components/docs/newsletter_signup.tsx @@ -31,6 +31,11 @@ export const NewsletterSignup: React.FunctionComponent = + + + + + @@ -60,6 +65,7 @@ const Label = styled.label` const InputWrapper = styled.div` padding: 0 40px; + position: relative; `; const Input = styled.input` @@ -71,4 +77,16 @@ const Input = styled.input` font-size: 1.25rem; font-weight: 300; width: 100%; + outline: none; +`; + +const Submit = styled.button` + background-color: transparent; + border: 0; + cursor: pointer; + appearance: none; + position: absolute; + height: 100%; + width: 50px; + right: 40px; `; diff --git a/packages/website/ts/components/docs/note.tsx b/packages/website/ts/components/docs/note.tsx new file mode 100644 index 0000000000..c0d4a88de7 --- /dev/null +++ b/packages/website/ts/components/docs/note.tsx @@ -0,0 +1,52 @@ +import * as _ from 'lodash'; +import * as React from 'react'; +import styled from 'styled-components'; + +import { Heading, Paragraph } from 'ts/components/text'; +import { colors } from 'ts/style/colors'; + +export interface NoteProps { + heading: string; + description?: string; +} + +interface WrapperProps { +} + +export const Note: React.FunctionComponent = (props: NoteProps) => ( + <> + + + {props.heading} + {props.description} + + + +); + +const Wrapper = styled.div` + background-color: ${colors.backgroundLight}; + border: 1px solid #DBDFDD; + padding: 20px 14px; + display: flex; + align-items: center; + float: right; + max-width: 300px; + margin-left: 30px; + margin-bottom: 30px; +`; + +const Content = styled.div` +`; + +const NoteHeading = styled(Heading).attrs({ color: colors.brandDark, asElement: 'h4' })` + font-size: 0.944444444rem !important; + margin-bottom: 6px; +`; + +const Description = styled(Paragraph)` + font-size: 0.888888889rem; + margin-bottom: 0; + line-height: 1.25; + opacity: 1; +`; diff --git a/packages/website/ts/components/docs/resource/level.tsx b/packages/website/ts/components/docs/resource/level.tsx new file mode 100644 index 0000000000..2410425210 --- /dev/null +++ b/packages/website/ts/components/docs/resource/level.tsx @@ -0,0 +1,52 @@ +import { Link } from '@0x/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; +import styled from 'styled-components'; +import { colors } from 'ts/style/colors'; +import { RatingBar } from 'ts/components/docs/resource/rating_bar'; + +export interface LevelProps { + difficulty: Difficulty; +} + +export enum Difficulty { + Beginner = 'beginner', + Intermediate = 'intermediate', + Advanced = 'advanced', +} + +const difficulties = { + [Difficulty.Beginner]: { + label: 'Beginner', + rating: 1 + }, + [Difficulty.Intermediate]: { + label: 'Intermediate', + rating: 2 + }, + [Difficulty.Advanced]: { + label: 'Advanced', + rating: 3 + }, +} + +export const Level: React.FunctionComponent = ({ difficulty }: LevelProps) => { + const info = difficulties[difficulty]; + return ( + + {info.label} + + + ) +}; + +const Wrapper = styled.div` + display: flex; + align-items: center; +`; + +const DifficultyLabel = styled.span` + font-size: 0.777777778rem; + color: ${colors.brandDark}; + margin-right: 0.611111111rem; +`; diff --git a/packages/website/ts/components/docs/resource/rating_bar.tsx b/packages/website/ts/components/docs/resource/rating_bar.tsx new file mode 100644 index 0000000000..146f35dec0 --- /dev/null +++ b/packages/website/ts/components/docs/resource/rating_bar.tsx @@ -0,0 +1,55 @@ +import * as _ from 'lodash'; +import * as React from 'react'; +import styled from 'styled-components'; + +import { Paragraph } from 'ts/components/text'; +import { colors } from 'ts/style/colors'; + +interface LabelInterface { + [key: number]: string; +} + +interface RatingBarProps { + rating: number; +} + +interface RatingBulletProps { + isFilled: boolean; +} + +export const RatingBar: React.StatelessComponent = ({ rating }) => { + const id = + Math.random() + .toString(36) + .substring(2, 15) + + Math.random() + .toString(36) + .substring(2, 15); + const ratingPlaceholders = Array.from(new Array(3), (value, index) => index + 1); + const fillCheck = (currentIndex: number) => currentIndex <= rating; + + // TODO convert this to use a Container component + return ( + + {ratingPlaceholders.map((currentIndex: number) => ( + + ))} + + ); +}; + +const Wrapper = styled.div` + display: flex; + align-items: center; +`; + +const RatingBullet = styled.div` + background-color: ${props => (props.isFilled ? colors.brandDark : 'rgba(0, 56, 49, 0.2)')}; + border-radius: 50%; + width: 10px; + height: 10px; + + & + & { + margin-left: 4px; + } +`; diff --git a/packages/website/ts/components/docs/resource/resource.tsx b/packages/website/ts/components/docs/resource/resource.tsx index ea92fd08cf..3200eed377 100644 --- a/packages/website/ts/components/docs/resource/resource.tsx +++ b/packages/website/ts/components/docs/resource/resource.tsx @@ -6,6 +6,7 @@ import { Heading, Paragraph } from 'ts/components/text'; import { colors } from 'ts/style/colors'; import { Tag } from 'ts/components/docs/resource/tag'; +import { Level, Difficulty } from 'ts/components/docs/resource/level'; export interface ResourceProps { heading?: string; @@ -14,11 +15,9 @@ export interface ResourceProps { tags: TagProps[]; } -interface WrapperProps { -} - interface TagProps { label: React.ReactNode; + isInverted?: boolean; } export const Resource: React.FunctionComponent = ({ heading, description, url, tags }: ResourceProps) => ( @@ -27,11 +26,9 @@ export const Resource: React.FunctionComponent = ({ heading, desc {description} - {tags.map((tag, index) => {tag.label})} + {tags.map(({label, isInverted}, index) => {label})} -
- Rating -
+ ); @@ -41,10 +38,10 @@ Resource.defaultProps = { description: 'Get in touch here and we’ll be happy to help.', }; -const Wrapper = styled.a` +const Wrapper = styled.a` border: 1px solid #D7E3DB; padding: 25px 30px; - margin-bottom: 1.875rem; + margin-bottom: 1.111111111rem; display: block; `; @@ -57,4 +54,4 @@ const Meta = styled.div` const Tags = styled.div` display: flex; align-items: center; -`; +`; \ No newline at end of file diff --git a/packages/website/ts/components/docs/resource/tag.tsx b/packages/website/ts/components/docs/resource/tag.tsx index 7781d5bf95..5e92a76129 100644 --- a/packages/website/ts/components/docs/resource/tag.tsx +++ b/packages/website/ts/components/docs/resource/tag.tsx @@ -27,8 +27,10 @@ const Wrapper = styled.div` background-color: ${props => props.isInverted ? colors.brandDark : 'rgba(0, 56, 49, 0.1)'}; border-radius: 4px; color: ${props => props.isInverted ? colors.white : colors.brandDark}; - font-size: 0.75rem; - padding: 6px 10px 4px; + font-size: 0.666666667rem; + font-family: 'Formular Mono'; + font-weight: 400; + padding: 6px 10px 5px; display: inline-flex; align-items: center; text-transform: uppercase; diff --git a/packages/website/ts/components/docs/sidebar/filter.tsx b/packages/website/ts/components/docs/sidebar/filter.tsx new file mode 100644 index 0000000000..274aa57390 --- /dev/null +++ b/packages/website/ts/components/docs/sidebar/filter.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; +import styled from 'styled-components'; +import { colors } from 'ts/style/colors'; + +export interface FilterProps { + name: string; + value: string; + label: string; +} + +export const Filter: React.FunctionComponent = ({ value, name, label }: FilterProps) => ( + + + + + +); + +const Wrapper = styled.label` + cursor: pointer; + display: flex; + align-items: center; + margin-bottom: 0.833333333rem; +`; + +const Checkbox = styled.input.attrs({ type: 'checkbox' })` + position: absolute; + opacity: 0; + opacity: 0; +`; + +const CheckboxBox = styled.div` +border: 1px solid #CBCBCB; +width: 22px; +height: 22px; +margin-right: 0.666rem; + +${Checkbox}:checked ~ & { + background: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.983 12.522c-.21 0-.4-.07-.557-.226l-3.46-3.461a.777.777 0 0 1 0-1.113.777.777 0 0 1 1.112 0L6 10.626l6.94-6.922a.777.777 0 0 1 1.112 0c.313.313.313.8 0 1.113l-7.495 7.479a.83.83 0 0 1-.574.226z' fill='currentColor'/%3E%3C/svg%3E") no-repeat center; +} +`; + +const Label = styled.span` + font-size: 0.833rem; + color: ${colors.textDarkPrimary}; + font-weight: 300; +`; diff --git a/packages/website/ts/components/docs/sidebar/filters.tsx b/packages/website/ts/components/docs/sidebar/filters.tsx new file mode 100644 index 0000000000..b2f756d8e5 --- /dev/null +++ b/packages/website/ts/components/docs/sidebar/filters.tsx @@ -0,0 +1,111 @@ +import * as React from 'react'; +import * as CopyToClipboard from 'react-copy-to-clipboard'; +import SyntaxHighlighter from 'react-syntax-highlighter'; + +import { Button } from 'ts/components/button'; +import { Heading } from 'ts/components/text'; +import { Container } from 'ts/components/ui/container'; +import { Filter } from 'ts/components/docs/sidebar/filter'; +import { colors } from 'ts/style/colors'; +import { styled } from 'ts/style/theme'; +import { zIndex } from 'ts/style/z_index'; + +export interface FiltersProps { +} + +export interface FiltersState { +} + +interface Group { + heading: string; + name: string; + filters: FilterProps[]; +} + +interface FilterProps { +value: string; +label: string; +} + +const groups: Group[] = [ + { + heading: 'Topic', + name: 'topic', + filters: [ + { + value: 'mesh', + label: 'Mesh' + }, + { + value: 'testing', + label: 'Testing' + }, + { + value: 'mesh', + label: 'Mesh' + }, + { + value: 'testing', + label: 'Testing' + }, + ] + }, + { + heading: 'Level', + name: 'level', + filters: [ + { + value: 'beginner', + label: 'Beginner' + }, + { + value: 'intermediate', + label: 'Intermediate' + }, + { + value: 'advanced', + label: 'Advanced' + }, + ] + }, +] + +export class Filters extends React.Component { + public static defaultProps = { + }; + public state: FiltersState = { + }; + public render(): React.ReactNode { + return ( + + {groups.map(({ heading, name, filters }: Group, index) => ( + + {heading} + {filters.map(({ value, label }: FilterProps, index) => ( + + ))} + + ))} + + ); + } + /*private readonly _handleCopyClick = () => { + this.setState({ didCopyFilters: true }); + };*/ +} + +const Wrapper = styled.div` + position: relative; + max-width: 702px; +`; + +const GroupWrapper = styled.div` + margin-bottom: 2.22em; +`; + +const GroupHeading = styled(Heading)` +color: ${colors.textDarkPrimary}; + font-size: 1rem !important; + font-weight: 400 !important; + margin-bottom: 1em !important; +`; diff --git a/packages/website/ts/components/docs/table.tsx b/packages/website/ts/components/docs/table.tsx index abe3891ebb..430a9e48ef 100644 --- a/packages/website/ts/components/docs/table.tsx +++ b/packages/website/ts/components/docs/table.tsx @@ -24,8 +24,8 @@ const Wrapper = styled.table` width: 100%; th { - font-size: 1rem; - font-weight: 500; + font-size: 0.888888889rem; + font-weight: 400; padding: 14px 20px 13px; border-bottom: 1px solid #CFCFCF; text-align: left; @@ -34,8 +34,9 @@ const Wrapper = styled.table` td { padding: 14px 20px 13px; border-bottom: 1px solid #CFCFCF; - font-size: 0.875rem; + font-size: 0.777777778rem; opacity: 0.76; + line-height: 1.428571429; } td + td, @@ -50,4 +51,14 @@ const Wrapper = styled.table` tr:nth-child(even) td { background-color: ${colors.backgroundLight}; } + + code { + background-color: rgba(0, 56, 49, 0.1); + border-radius: 3px; + border: 0; + font-size: 1em; + padding: 2px 5px; + color: ${colors.brandDark}; + font-family: inherit; + } `; diff --git a/packages/website/ts/pages/docs/page_template.tsx b/packages/website/ts/pages/docs/page_template.tsx index a584da4352..f7006ee410 100644 --- a/packages/website/ts/pages/docs/page_template.tsx +++ b/packages/website/ts/pages/docs/page_template.tsx @@ -5,10 +5,15 @@ import styled, { keyframes } from 'styled-components'; // import { Tabs } from 'react-tabs'; import { Callout } from 'ts/components/docs/callout'; import { Code } from 'ts/components/docs/code'; +import { Filters } from 'ts/components/docs/sidebar/filters'; import { CommunityLink, CommunityLinkProps } from 'ts/components/docs/community_link'; +import { FeatureLink } from 'ts/components/docs/feature_link'; import { HelpCallout } from 'ts/components/docs/help_callout'; +import { HelpfulCta } from 'ts/components/docs/helpful_cta'; import { Hero } from 'ts/components/docs/hero'; import { NewsletterSignup } from 'ts/components/docs/newsletter_signup'; +import { Note } from 'ts/components/docs/note'; +import { Resource } from 'ts/components/docs/resource/resource'; import { SearchInput } from 'ts/components/docs/search_input'; import { LinkProps, ShortcutLink } from 'ts/components/docs/shortcut_link'; import { SiteWrap } from 'ts/components/docs/siteWrap'; @@ -24,7 +29,6 @@ import { Heading, Paragraph } from 'ts/components/text'; import { colors } from 'ts/style/colors'; import { WebsitePaths } from 'ts/types'; import { documentConstants } from 'ts/utils/document_meta_constants'; -import { Resource } from 'ts/components/docs/resource/resource'; interface Props { location: Location; @@ -63,11 +67,11 @@ export class DocsPageTemplate extends React.Component {
Large Heading - Large Heading + Larger introduction text Notifications @@ -97,20 +101,28 @@ export class DocsPageTemplate extends React.Component { - Step1 - Step2 + makerAddress + Address that created the order. The maker is one of the two parties that will be involved in the trade if the order gets filled. - Step1 - Step2 + takerAddress + Address that is allowed to fill the order. If set to 0, anyone is allowed to fill the order. This field allows makers to decide who can fill an order, rendering it useless to eavesdroppers or outside parties. - Step1 - Step2 + feeRecipientAddress + The address that will receive the fees stipulated by the order. This is typically used to incentivize off-chain order relay. - Step1 - Step2 + senderAddress + Is an advanced feature that can be defaulted to the 0 address. It allows the maker to enforce that the order must flow through some additional logic residing in an additional Ethereum smart contract before it can be filled (e.g a KYC whitelist contract) -- more on "extension contracts" later. + + + makerAssetAmount + Amount of the maker'sAsset being offered by the maker. Must be greater than 0. + + + makerFee + The fee to be paid by the order maker to the feeRecipientAddress in the event of an order fill. Partial fills result in partial fees. @@ -170,6 +182,12 @@ const txnReceipt = await exchange.executeTransaction.awaitTransactionSuccessAsyn Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec consequat velit in nisl varius malesuada. Morbi at porttitor enim. Donec vel tristique dolor, quis convallis sapien. Nam et massa tempus, dignissim leo vitae, ultricies libero. Vivamus eu enim tellus. Phasellus eu mattis elit. Proin ut eleifend urna, sed tincidunt nunc. Sed eu dapibus metus, in congue ipsum. Duis volutpat sem et sem faucibus blandit. Nullam ultricies ante eu elit auctor, id mattis nunc euismod. Curabitur arcu enim, cursus ac pellentesque quis, accumsan sit amet turpis. Praesent dignissim mi a maximus euismod +
+ + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec consequat velit in nisl varius malesuada. Morbi at porttitor enim. Donec vel tristique dolor, quis convallis sapien. Nam et massa tempus, dignissim leo vitae, ultricies libero. Vivamus eu enim tellus. Phasellus eu mattis elit. Proin ut eleifend urna, sed tincidunt nunc. Sed eu dapibus metus, in congue ipsum. Duis volutpat sem et sem faucibus blandit. Nullam ultricies ante eu elit auctor, id mattis nunc euismod. Curabitur arcu enim, cursus ac pellentesque quis, accumsan sit amet turpis. Praesent dignissim mi a maximus euismod + +
  • List items
  • List items
  • @@ -182,7 +200,18 @@ const txnReceipt = await exchange.executeTransaction.awaitTransactionSuccessAsyn - + +
    + Resources + + +
    +
    + Feature Links + + + +