friends list

This commit is contained in:
Martina 2020-07-31 20:44:16 -07:00
parent ed28c7a9c5
commit 26348f0868
25 changed files with 769 additions and 202 deletions

View File

@ -79,22 +79,24 @@ export default class SidebarAddFileToBucket extends React.Component {
</System.P>
) : null}
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
type="label"
htmlFor="file"
style={{ marginTop: 24 }}
loading={this.props.fileLoading}
>
Add file
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
{!this.props.fileLoading ? (
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
style={{ marginTop: 16 }}
onClick={this.props.onCancel}
>
Cancel
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
) : null}
</React.Fragment>
);

View File

@ -87,12 +87,13 @@ export default class SidebarCreatePaymentChannel extends React.Component {
<div css={STYLES_SUBTEXT}>Total Filecoin</div>
</div>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
>
Send
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
</React.Fragment>
);
}

View File

@ -64,20 +64,22 @@ export default class SidebarCreateSlate extends React.Component {
{this.props.viewer.username}/{Strings.createSlug(this.state.name)}
</System.P>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
loading={this.state.loading}
>
Create {this.state.name}
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
style={{ marginTop: 16 }}
onClick={this._handleCancel}
>
Cancel
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
</div>
);
}

View File

@ -89,20 +89,22 @@ export default class SidebarCreateWalletAddress extends React.Component {
Make this wallet the default
</System.CheckBox>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
loading={this.state.loading}
>
Create {this.state.name}
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
style={{ marginTop: 16 }}
onClick={this._handleCancel}
>
Cancel
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
</div>
);
}

View File

@ -27,19 +27,21 @@ export default class SidebarDeleteWalletAddress extends React.Component {
Are you sure you want to delete the selected wallet?
</System.P>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
>
Delete
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
style={{ marginTop: 16 }}
onClick={this._handleCancel}
>
Cancel
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
</div>
);
}

View File

@ -138,21 +138,23 @@ export default class SidebarFileStorageDeal extends React.Component {
options={this.props.viewer.addresses}
/>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
loading={this.props.sidebarLoading}
>
Make storage deal
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
{!this.props.sidebarLoading ? (
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
style={{ marginTop: 16 }}
onClick={this._handleCancel}
>
Cancel deal
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
) : null}
</React.Fragment>
);

View File

@ -116,20 +116,22 @@ export default class SidebarWalletSendFunds extends React.Component {
<div css={STYLES_SUBTEXT}>Total Filecoin</div>
</div>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
loading={this.state.loading}
>
Send
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
style={{ marginTop: 16 }}
onClick={this._handleCancel}
>
Cancel
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
</React.Fragment>
);
}

View File

@ -222,6 +222,11 @@ export default class SystemPage extends React.Component {
href="/experiences/filecoin-settings"
title="FilecoinSettings"
/>
<SidebarLink
url={url}
href="/experiences/friends-list"
title="FriendsList"
/>
<SidebarLink
url={url}
href="/experiences/peers-list"

View File

@ -59,7 +59,58 @@ const STYLES_BUTTON_PRIMARY = css`
}
`;
const STYLES_BUTTON_PRIMARY_FULL = css`
${STYLES_BUTTON_FULL}
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
cursor: pointer;
background-color: ${Constants.system.brand};
color: ${Constants.system.white};
:hover {
background-color: #003fe3;
}
:focus {
box-shadow: inset 0 0 5px 2px rgba(0, 0, 0, 0.3);
background-color: ${Constants.system.brand};
outline: 0;
border: 0;
}
`;
export const ButtonPrimary = (props) => {
if (props.full) {
if (props.loading) {
return (
<button css={STYLES_BUTTON_PRIMARY_FULL} style={props.style}>
<LoaderSpinner style={{ height: 16, width: 16 }} />
</button>
);
}
if (props.type === "label") {
return (
<label
css={STYLES_BUTTON_PRIMARY_FULL}
style={props.style}
onClick={props.onClick}
children={props.children}
type={props.label}
htmlFor={props.htmlFor}
/>
);
}
return (
<button
css={STYLES_BUTTON_PRIMARY_FULL}
style={props.style}
onClick={props.onClick}
children={props.children}
/>
);
}
if (props.loading) {
return (
<button css={STYLES_BUTTON_PRIMARY} style={props.style}>
@ -91,25 +142,6 @@ export const ButtonPrimary = (props) => {
);
};
const STYLES_BUTTON_PRIMARY_FULL = css`
${STYLES_BUTTON_FULL}
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
cursor: pointer;
background-color: ${Constants.system.brand};
color: ${Constants.system.white};
:hover {
background-color: #003fe3;
}
:focus {
box-shadow: inset 0 0 5px 2px rgba(0, 0, 0, 0.3);
background-color: ${Constants.system.brand};
outline: 0;
border: 0;
}
`;
export const ButtonPrimaryFull = (props) => {
if (props.loading) {
return (
@ -161,14 +193,6 @@ const STYLES_BUTTON_SECONDARY = css`
}
`;
export const ButtonSecondary = (props) => {
if (props.type === "label") {
return <label css={STYLES_BUTTON_SECONDARY} {...props} />;
}
return <button css={STYLES_BUTTON_SECONDARY} {...props} />;
};
const STYLES_BUTTON_SECONDARY_FULL = css`
${STYLES_BUTTON_FULL}
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
@ -188,6 +212,39 @@ const STYLES_BUTTON_SECONDARY_FULL = css`
}
`;
export const ButtonSecondary = (props) => {
if (props.full) {
if (props.loading) {
return (
<button css={STYLES_BUTTON_SECONDARY_FULL} style={props.style}>
<LoaderSpinner style={{ height: 16, width: 16 }} />
</button>
);
}
if (props.type === "label") {
return (
<label
css={STYLES_BUTTON_SECONDARY_FULL}
style={props.style}
onClick={props.onClick}
children={props.children}
type={props.label}
htmlFor={props.htmlFor}
/>
);
}
return <button css={STYLES_BUTTON_SECONDARY_FULL} {...props} />;
}
if (props.type === "label") {
return <label css={STYLES_BUTTON_SECONDARY} {...props} />;
}
return <button css={STYLES_BUTTON_SECONDARY} {...props} />;
};
export const ButtonSecondaryFull = (props) => {
if (props.loading) {
return (
@ -225,10 +282,6 @@ const STYLES_BUTTON_DISABLED = css`
}
`;
export const ButtonDisabled = (props) => {
return <button css={STYLES_BUTTON_DISABLED} {...props} />;
};
const STYLES_BUTTON_DISABLED_FULL = css`
${STYLES_BUTTON_FULL}
cursor: not-allowed;
@ -241,6 +294,15 @@ const STYLES_BUTTON_DISABLED_FULL = css`
}
`;
export const ButtonDisabled = (props) => {
return (
<button
css={props.full ? STYLES_BUTTON_DISABLED_FULL : STYLES_BUTTON_DISABLED}
{...props}
/>
);
};
export const ButtonDisabledFull = (props) => {
return <button css={STYLES_BUTTON_DISABLED_FULL} {...props} />;
};

View File

@ -121,38 +121,40 @@ export class Table extends React.Component {
const width = TABLE_COLUMN_WIDTH_DEFAULTS[data.columns.length];
return (
<React.Fragment>
<div css={STYLES_TABLE_TOP_ROW}>
{data.columns.map((c, cIndex) => {
const text = c.hideLabel
? ""
: Strings.isEmpty(c.name)
? c.key
: c.name;
let localWidth = c.width ? c.width : width;
let flexShrink = c.width && c.width !== "100%" ? "0" : null;
if (cIndex === 0 && !c.width) {
localWidth = "100%";
}
{this.props.noLabel ? null : (
<div css={STYLES_TABLE_TOP_ROW}>
{data.columns.map((c, cIndex) => {
const text = c.hideLabel
? ""
: Strings.isEmpty(c.name)
? c.key
: c.name;
let localWidth = c.width ? c.width : width;
let flexShrink = c.width && c.width !== "100%" ? "0" : null;
if (cIndex === 0 && !c.width) {
localWidth = "100%";
}
return (
<SubSystem.TableColumn
top
key={`table-top-${c.key}-${cIndex}`}
style={{
width: localWidth,
backgroundColor: ac[c.key].color,
flexShrink,
}}
tooltip={c.tooltip}
>
{text}
</SubSystem.TableColumn>
);
})}
{this.props.onClick ? (
<div css={STYLES_TABLE_EXPAND_SECTION} />
) : null}
</div>
return (
<SubSystem.TableColumn
top
key={`table-top-${c.key}-${cIndex}`}
style={{
width: localWidth,
backgroundColor: ac[c.key].color,
flexShrink,
}}
tooltip={c.tooltip}
>
{text}
</SubSystem.TableColumn>
);
})}
{this.props.onClick ? (
<div css={STYLES_TABLE_EXPAND_SECTION} />
) : null}
</div>
)}
{data.rows.map((r, i) => {
const selected = r.id === this.props.selectedRowId;
@ -176,36 +178,54 @@ export class Table extends React.Component {
key={`${each}-${i}-${cIndex}`}
style={{
width: localWidth,
backgroundColor: field.color,
backgroundColor: this.props.noColor
? null
: field.color,
flexShrink,
}}
contentStyle={field.contentStyle}
copyable={field.copyable}
>
<SubSystem.TableContent
data={r}
text={text}
type={field.type}
action={field.action}
onNavigateTo={this.props.onNavigateTo}
onAction={this.props.onAction}
/>
<div style={field.style}>
<SubSystem.TableContent
data={r}
text={text}
type={field.type}
action={field.action}
onNavigateTo={this.props.onNavigateTo}
onAction={this.props.onAction}
/>
</div>
</SubSystem.TableColumn>
);
})}
{this.props.onClick ? (
<div
css={STYLES_TABLE_EXPAND_SECTION}
onClick={() => this._handleClick(r.id)}
style={{ cursor: r.children ? "pointer" : "default" }}
style={{
width: "40px",
display: "flex",
alignItems: "center",
alignSelf: "center",
justifyContent: "flex-start",
}}
>
{r.children ? (
<SVG.Plus
height="16px"
style={{
transform: selected ? `rotate(45deg)` : null,
}}
/>
) : null}
<div
css={STYLES_TABLE_EXPAND_SECTION}
onClick={() => this._handleClick(r.id)}
style={{
cursor: r.children ? "pointer" : "default",
display: "inline-flex",
}}
>
{r.children ? (
<SVG.Plus
height="16px"
style={{
transform: selected ? `rotate(45deg)` : null,
}}
/>
) : null}
</div>
</div>
) : null}
</div>

View File

@ -100,7 +100,6 @@ const STYLES_COLUMN = css`
align-items: flex-start;
justify-content: space-between;
align-self: stretch;
min-width: 10%;
`;
const STYLES_TOP_COLUMN = css`
@ -109,14 +108,12 @@ const STYLES_TOP_COLUMN = css`
align-items: flex-start;
justify-content: space-between;
align-self: stretch;
min-width: 10%;
transition: 200ms ease all;
`;
const STYLES_CONTENT = css`
box-sizing: border-box;
padding: 12px 12px 12px 12px;
min-width: 10%;
width: 100%;
align-self: stretch;
flex-direction: column;
@ -172,7 +169,9 @@ export const TableColumn = (props) => {
css={props.top ? STYLES_TOP_COLUMN : STYLES_COLUMN}
style={props.style}
>
<span css={STYLES_CONTENT}>{props.children}</span>
<span css={STYLES_CONTENT} style={props.contentStyle}>
{props.children}
</span>
{tooltipElement}
{copyableElement}
</span>

View File

@ -6,6 +6,7 @@ import { dispatchCustomEvent } from "~/common/custom-events";
// NOTE(jim): Modules
import { CreateToken } from "~/components/system/modules/CreateToken";
import { PeersList } from "~/components/system/modules/PeersList";
import { FriendsList } from "~/components/system/modules/FriendsList";
import { CreateFilecoinAddress } from "~/components/system/modules/CreateFilecoinAddress";
import { CreateFilecoinStorageDeal } from "~/components/system/modules/CreateFilecoinStorageDeal";
import { SendAddressFilecoin } from "~/components/system/modules/SendAddressFilecoin";
@ -94,6 +95,7 @@ export {
FilecoinRetrievalDealsList,
FilecoinStorageDealsList,
FilecoinSettings,
FriendsList,
// NOTE(jim): Components
ButtonPrimary,
ButtonPrimaryFull,

View File

@ -2,13 +2,9 @@ import * as React from "react";
import * as Constants from "~/common/constants";
import { Input } from "~/components/system/components/Input";
import {
SelectMenu,
} from "~/components/system/components/SelectMenus";
import { SelectMenu } from "~/components/system/components/SelectMenus";
import { CheckBox } from "~/components/system/components/CheckBox";
import {
ButtonPrimaryFull,
} from "~/components/system/components/Buttons";
import { ButtonPrimary } from "~/components/system/components/Buttons";
import { css } from "@emotion/react";
const SELECT_MENU_OPTIONS = [
@ -85,12 +81,13 @@ export class CreateFilecoinAddress extends React.Component {
Make this wallet the default
</CheckBox>
<ButtonPrimaryFull
<ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
>
Create address
</ButtonPrimaryFull>
</ButtonPrimary>
</div>
);
}

View File

@ -1,8 +1,8 @@
import * as React from "react";
import * as Constants from "~/common/constants";
import {
ButtonPrimaryFull,
ButtonSecondaryFull,
ButtonPrimary,
ButtonSecondary,
} from "~/components/system/components/Buttons";
import { css } from "@emotion/react";
@ -96,16 +96,17 @@ export class CreateFilecoinStorageDeal extends React.Component {
</div>
</div>
) : null}
<ButtonSecondaryFull type="label" htmlFor="file">
<ButtonSecondary full type="label" htmlFor="file">
Add file
</ButtonSecondaryFull>
</ButtonSecondary>
{this.state.file ? (
<ButtonPrimaryFull
<ButtonPrimary
full
style={{ marginTop: 24 }}
onClick={this._handleSubmit}
>
Make storage deal
</ButtonPrimaryFull>
</ButtonPrimary>
) : null}
</div>
);

View File

@ -2,7 +2,7 @@ import * as React from "react";
import * as Constants from "~/common/constants";
import { css } from "@emotion/react";
import { ButtonPrimaryFull } from "~/components/system/components/Buttons";
import { ButtonPrimary } from "~/components/system/components/Buttons";
import Odometer from "~/vendor/odometer";
@ -81,9 +81,9 @@ export const CreateToken = (props) => {
</span>
</div>
<div css={STYLES_CREATE_TOKEN_BOTTOM}>
<ButtonPrimaryFull onClick={props.onClick}>
<ButtonPrimary full onClick={props.onClick}>
Generate new Powergate token
</ButtonPrimaryFull>
</ButtonPrimary>
</div>
</div>
);

View File

@ -76,7 +76,7 @@ export class FilecoinStorageDealsList extends React.Component {
}}
selectedRowId={this.state.selectedRowId}
onClick={this._handleClick}
name={"hello"}
name={this.props.name}
/>
</Group>
);

View File

@ -0,0 +1,245 @@
import * as React from "react";
import * as Constants from "~/common/constants";
import * as Strings from "~/common/strings";
import * as SVG from "~/components/system/svg";
import { css } from "@emotion/react";
import { Table } from "~/components/system/components/Table";
import { StatUpload, StatDownload } from "~/components/system/components/Stat";
let genericImg =
"https://hub.textile.io/ipfs/bafybeiblly23jomdjjiq7ilth667npcfm5llqb5xfstodbbfa5pxtoek7u";
const STYLES_BUTTON = `
font-family: ${Constants.font.text};
font-size: ${Constants.typescale.lvl1};
cursor: pointer;
background: none;
border: none;
outline: none;
padding: 8px;
:hover {
background-color: ${Constants.system.gray};
border-radius: 4px;
}
`;
const STYLES_ACCEPT_BUTTON = css`
${STYLES_BUTTON}
color: ${Constants.system.brand};
`;
const STYLES_REJECT_BUTTON = css`
${STYLES_BUTTON}
color: ${Constants.system.black};
`;
const centerLeftStyle = {
display: "flex",
height: "100%",
alignItems: "center",
};
const centerRightStyle = {
display: "flex",
height: "100%",
alignItems: "center",
justifyContent: "flex-end",
};
export class FriendsList extends React.Component {
state = {
selectedRowId: null,
};
_handleClick = (e) => {
this.setState({ selectedRowId: e.target.value });
};
render() {
return (
<React.Fragment>
<div
style={{ fontSize: Constants.typescale.lvl2, marginBottom: "8px" }}
>
Requests
</div>
<Table
noColor
noLabel
data={{
columns: [
{
key: "image",
width: "64px",
style: centerLeftStyle,
},
{
key: "user",
width: "100%",
style: centerLeftStyle,
},
{
key: "accept",
width: "92px",
style: centerRightStyle,
contentStyle: { padding: "0px" },
},
{
key: "reject",
width: "92px",
style: centerRightStyle,
contentStyle: { padding: "0px" },
},
],
rows: this.props.data.requests.map((each) => {
return {
id: each.user,
user: (
<a
href={"/" + each.user}
target="_blank"
style={{
color: Constants.system.black,
fontSize: Constants.typescale.lvl1,
}}
>
{each.user}
</a>
),
image: (
<div
style={{
width: "40px",
height: "40px",
overflow: "hidden",
borderRadius: "4px",
}}
>
<img
src={each.img || genericImg}
alt=""
style={{ width: "40px" }}
/>
</div>
),
accept: (
<button type="button" css={STYLES_ACCEPT_BUTTON}>
Accept
</button>
),
reject: (
<button type="button" css={STYLES_REJECT_BUTTON}>
Reject
</button>
),
};
}),
}}
/>
<br />
<br />
<div
style={{ fontSize: Constants.typescale.lvl2, marginBottom: "8px" }}
>
Peers
</div>
<Table
noColor
noLabel
selectedRowId={this.state.selectedRowId}
onClick={this._handleClick}
data={{
columns: [
{
key: "image",
width: "64px",
style: centerLeftStyle,
},
{
key: "user",
width: "100%",
style: centerLeftStyle,
},
],
rows: this.props.data.friends.map((each) => {
return {
id: each.user,
user: (
<a
href={"/" + each.user}
target="_blank"
style={{
color: Constants.system.black,
fontSize: Constants.typescale.lvl1,
}}
>
{each.user}
</a>
),
image: (
<div
style={{
width: "40px",
height: "40px",
overflow: "hidden",
borderRadius: "4px",
}}
>
<img
src={each.img || genericImg}
alt=""
style={{ width: "40px" }}
/>
</div>
),
children: (
<div>
<div
style={{
display: "grid",
alignItems: "center",
gridTemplateColumns: "1fr 1fr",
}}
>
{each.info.location ? (
<div>
<SVG.LocationPin
height="20px"
style={{
position: "relative",
top: "5px",
marginRight: "8px",
}}
/>
{each.info.location}
</div>
) : null}
<div style={{ justifySelf: "end" }}>
<br />
<StatUpload
size={each.info.upload}
style={{ marginRight: "16px" }}
/>
<StatDownload size={each.info.download} />
</div>
</div>
<br />
<div>
<strong>Height</strong>: {each.info.height}
</div>
<br />
<div style={{ wordBreak: "break-word" }}>
<strong>Chain Head</strong>: {each.info.chainHead}
</div>
</div>
),
};
}),
}}
/>
</React.Fragment>
);
}
}

View File

@ -2,9 +2,7 @@ import * as React from "react";
import * as Constants from "~/common/constants";
import { Input } from "~/components/system/components/Input";
import {
ButtonPrimaryFull,
} from "~/components/system/components/Buttons";
import { ButtonPrimary } from "~/components/system/components/Buttons";
import { css } from "@emotion/react";
const STYLES_CONTAINER = css`
@ -67,12 +65,13 @@ export class SendAddressFilecoin extends React.Component {
onChange={this._handleChange}
/>
<ButtonPrimaryFull
<ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
>
Send {this.state.amount} FIL
</ButtonPrimaryFull>
</ButtonPrimary>
</div>
);
}

View File

@ -295,3 +295,21 @@ export const ChevronLeft = (props) => {
</svg>
);
};
export const LocationPin = (props) => {
return (
<svg
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
{...props}
>
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
<circle cx="12" cy="10" r="3"></circle>
</svg>
);
};

View File

@ -0,0 +1,195 @@
import * as React from "react";
import * as System from "~/components/system";
import SystemPage from "~/components/system/SystemPage";
import ViewSourceLink from "~/components/system/ViewSourceLink";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE = `import * as React from "react";
import { FriendsList } from "slate-react-system";
const friendsList = {
requests: [
{
id: 72572959238,
user: "@martina",
img:
"https://hub.textile.io/ipfs/bafybeiguo2uhd63reslbqkkgsqedgeikhtuwn5lzqpnqzluoaa3rnkfcvi",
},
{
id: 2572952030,
user: "@jim",
img:
"https://hub.textile.io/ipfs/bafybeicuz5wrxonu7ud6eskrnshxb66ksg3ncu3ie776xuiydlxrkfuvmu",
},
],
friends: [
{
id: 64783925020,
user: "@haris",
img: null,
info: {
chainHead:
"t3solnyrrblqlmvi6gmzewzvu62vs7uqvkl22yemzr63bcylbaaqsg44mnipepuafg7efzzx4zwcsi66jgze3q",
height: 8273,
location: "United States",
upload: 40092,
download: 83900,
},
},
{
id: 637838385993,
user: "@aaron",
img:
"https://hub.textile.io/ipfs/bafkreicb2lookm56omsfjwuwuziwftizmdsj4oneveuqiqlu6k5hc7j5nq",
info: {
chainHead:
"bafyl5q5qo5wolfxsui4ciujfucqwf6gqso4lettcjwl2tyismgol7c4tngvoono5rmytuqotye7oosfjv6g7a",
height: 4728,
location: "United Kingdom",
upload: 28725802,
download: 2088774,
},
},
{
id: 982799203032,
user: "@colin",
img:
"https://hub.textile.io/ipfs/bafybeigxb4arecl6iwsvjnwzi2lqpmmif6l2kgwptac7q3tzqmsimci2yq",
info: {
chainHead:
"t3ual5q5qo5wolfxsui4ciujfucqwf6gqso4lettcjwl2tyismgol7c4tngvoono5rmytuqotye7oosfjv6g7a",
height: 9223,
location: "Netherlands",
upload: 7692,
download: 110,
},
},
{
id: 673883729083,
user: "@jason",
img:
"https://hub.textile.io/ipfs/bafybeicp3x3poprnrsxhnqscsiuobxejxsbcsu2t4yhte6qmcofjvjqbn4",
info: {
chainHead:
"t3solnyrrblqlmvi6gmzewzvu62vs7uqvkl22yemzr63bcylbaaqsg44mnipepuafg7efzzx4zwcsi66jgze3q",
height: 1938,
location: "Albania",
upload: 82802020,
download: 37792,
},
},
],
};
class Example extends React.Component {
render() {
return <FriendsList data={friendsList} />;
}
}
`;
export default class SystemPagePeersList extends React.Component {
render() {
const friendsList = {
requests: [
{
id: 72572959238,
user: "@martina",
img:
"https://hub.textile.io/ipfs/bafybeiguo2uhd63reslbqkkgsqedgeikhtuwn5lzqpnqzluoaa3rnkfcvi",
},
{
id: 2572952030,
user: "@jim",
img:
"https://hub.textile.io/ipfs/bafybeicuz5wrxonu7ud6eskrnshxb66ksg3ncu3ie776xuiydlxrkfuvmu",
},
],
friends: [
{
id: 64783925020,
user: "@haris",
img: null,
info: {
chainHead:
"t3solnyrrblqlmvi6gmzewzvu62vs7uqvkl22yemzr63bcylbaaqsg44mnipepuafg7efzzx4zwcsi66jgze3q",
height: 8273,
location: "United States",
upload: 40092,
download: 83900,
},
},
{
id: 637838385993,
user: "@aaron",
img:
"https://hub.textile.io/ipfs/bafkreicb2lookm56omsfjwuwuziwftizmdsj4oneveuqiqlu6k5hc7j5nq",
info: {
chainHead:
"bafyl5q5qo5wolfxsui4ciujfucqwf6gqso4lettcjwl2tyismgol7c4tngvoono5rmytuqotye7oosfjv6g7a",
height: 4728,
location: "United Kingdom",
upload: 28725802,
download: 2088774,
},
},
{
id: 982799203032,
user: "@colin",
img:
"https://hub.textile.io/ipfs/bafybeigxb4arecl6iwsvjnwzi2lqpmmif6l2kgwptac7q3tzqmsimci2yq",
info: {
chainHead:
"t3ual5q5qo5wolfxsui4ciujfucqwf6gqso4lettcjwl2tyismgol7c4tngvoono5rmytuqotye7oosfjv6g7a",
height: 9223,
location: "Netherlands",
upload: 7692,
download: 110,
},
},
{
id: 673883729083,
user: "@jason",
img:
"https://hub.textile.io/ipfs/bafybeicp3x3poprnrsxhnqscsiuobxejxsbcsu2t4yhte6qmcofjvjqbn4",
info: {
chainHead:
"t3solnyrrblqlmvi6gmzewzvu62vs7uqvkl22yemzr63bcylbaaqsg44mnipepuafg7efzzx4zwcsi66jgze3q",
height: 1938,
location: "Albania",
upload: 82802020,
download: 37792,
},
},
],
};
return (
<SystemPage
title="SDS: Friends List"
description="..."
url="https://slate.host/experiences/friends-list"
>
<System.H1>
Friends List <ViewSourceLink file="experiences/friends-list.js" />
</System.H1>
<br />
<br />
<System.P>
Here is an example of an experience for getting friends.
</System.P>
<br />
<br />
<System.FriendsList data={friendsList} />
<br />
<br />
<br />
<System.H2>Code</System.H2>
<hr />
<br />
<CodeBlock>{EXAMPLE_CODE}</CodeBlock>
</SystemPage>
);
}
}

View File

@ -35,11 +35,8 @@ export default class SystemPageButtons extends React.Component {
{`import * as React from "react";
import {
ButtonPrimary,
ButtonPrimaryFull,
ButtonSecondary,
ButtonSecondaryFull,
ButtonDisabled,
ButtonDisabledFull,
} from "slate-react-system";`}
</CodeBlock>
<br />
@ -48,7 +45,7 @@ import {
<hr />
<br />
<System.P>
There are three variations of the regular width button component.
There are three variations of the button component.
<br />
Primary, Secondary and Disabled.
</System.P>
@ -83,38 +80,33 @@ class ExampleDisabled extends React.Component {
<System.H2>Full width</System.H2>
<hr />
<br />
<System.P>
There are three variations of the full width button component. <br />
Primary, Secondary and Disabled.
</System.P>
<System.P>Each of the button styles has a full width option.</System.P>
<br />
<System.ButtonPrimaryFull>Primary Button Full</System.ButtonPrimaryFull>
<System.ButtonPrimary full>Primary Button Full</System.ButtonPrimary>
<br />
<System.ButtonSecondaryFull>
<System.ButtonSecondary full>
Secondary Button Full
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonDisabledFull>
Disabled Button Full
</System.ButtonDisabledFull>
<System.ButtonDisabled full>Disabled Button Full</System.ButtonDisabled>
<br />
<br />
<CodeBlock>
{`class ExamplePrimaryFull extends React.Component {
render() {
return <ButtonPrimaryFull>Primary Button Full</ButtonPrimaryFull>;
return <ButtonPrimary full>Primary Button Full</ButtonPrimary>;
}
}
class ExampleSecondaryFull extends React.Component {
render() {
return <ButtonSecondaryFull>Secondary Button Full</ButtonSecondaryFull>;
return <ButtonSecondary full>Secondary Button Full</ButtonSecondary>;
}
}
class ExampleDisabledFull extends React.Component {
render() {
return <ButtonDisabledFull>Disabled Button Full</ButtonDisabledFull>;
return <ButtonDisabled full>Disabled Button Full</ButtonDisabled>;
}
}`}
</CodeBlock>

View File

@ -82,7 +82,8 @@ import { GlobalCarousel, dispatchCustomEvent } from "slate-react-system";`}
<System.H2>Carousel</System.H2>
<hr />
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
slides: [
@ -103,7 +104,7 @@ import { GlobalCarousel, dispatchCustomEvent } from "slate-react-system";`}
}
>
Open carousel
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.P>
While the Carousel component is always present, a carousel will only
@ -137,11 +138,12 @@ import { GlobalCarousel, dispatchCustomEvent } from "slate-react-system";`}
].map((props) => <img {...props} style={{ maxHeight: "80vh" }} />);
return (
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() => this._handleCreate({ slides: carouselContent })}
>
Open Carousel
</ButtonSecondaryFull>
</ButtonSecondary>
);
}
}`}

View File

@ -84,7 +84,8 @@ import { GlobalModal, dispatchCustomEvent } from "slate-react-system";`}
<System.H2>Modal</System.H2>
<hr />
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
modal: (
@ -108,7 +109,7 @@ import { GlobalModal, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for modal popup
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.P>
While the Modal component is always present, a modal will only appear
@ -145,11 +146,12 @@ import { GlobalModal, dispatchCustomEvent } from "slate-react-system";`}
</div>
);
return (
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() => this._handleCreate({ modal: modalContent })}
>
Click for modal popup
</ButtonSecondaryFull>
</ButtonSecondary>
);
}
}`}

View File

@ -87,7 +87,8 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
<System.H2>Notification</System.H2>
<hr />
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -96,9 +97,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -108,11 +110,11 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for dark style notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonPrimaryFull onClick={this._handleDelete}>
<System.ButtonPrimary full onClick={this._handleDelete}>
Click to clear notifications
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<br />
<System.P>
A notification will only appear once you trigger it by creating a
@ -146,7 +148,8 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
render() {
return (
<React.Fragment>
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -155,9 +158,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for notification
</ButtonSecondaryFull>
</ButtonSecondary>
<br />
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -167,11 +171,11 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for dark style notification
</ButtonSecondaryFull>
</ButtonSecondary>
<ButtonPrimaryFull onClick={this._handleDelete}>
<ButtonPrimary full onClick={this._handleDelete}>
Click to clear notifications
</ButtonPrimaryFull>
</ButtonPrimary>
</React.Fragment>
);
}
@ -183,7 +187,8 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
<System.H2>Notification with timeout</System.H2>
<hr />
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -193,11 +198,11 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for disappearing notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonPrimaryFull onClick={this._handleDelete}>
<System.ButtonPrimary full onClick={this._handleDelete}>
Click to clear notifications
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<br />
<System.P>
You can declare the Notification component with a{" "}
@ -219,7 +224,8 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
render() {
return (
<React.Fragment>
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -229,11 +235,11 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for disappearing notification
</ButtonSecondaryFull>
</ButtonSecondary>
<ButtonPrimaryFull onClick={this._handleDelete}>
<ButtonPrimary full onClick={this._handleDelete}>
Click to clear notifications
</ButtonPrimaryFull>
</ButtonPrimary>
</React.Fragment>
);
}
@ -245,7 +251,8 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
<System.H2>Notification with status</System.H2>
<hr />
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -255,9 +262,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for info style notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -267,9 +275,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for success style notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -279,9 +288,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for warning style notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonSecondaryFull
<System.ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -291,11 +301,11 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for error style notification
</System.ButtonSecondaryFull>
</System.ButtonSecondary>
<br />
<System.ButtonPrimaryFull onClick={this._handleDelete}>
<System.ButtonPrimary full onClick={this._handleDelete}>
Click to clear notifications
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
<br />
<br />
<System.P>
@ -323,7 +333,8 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
render() {
return (
<React.Fragment>
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -333,9 +344,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for info style notification
</ButtonSecondaryFull>
</ButtonSecondary>
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -345,9 +357,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for success style notification
</ButtonSecondaryFull>
</ButtonSecondary>
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -357,9 +370,10 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for warning style notification
</ButtonSecondaryFull>
</ButtonSecondary>
<ButtonSecondaryFull
<ButtonSecondary
full
onClick={() =>
this._handleCreate({
id: this.state.count,
@ -369,11 +383,11 @@ import { GlobalNotification, dispatchCustomEvent } from "slate-react-system";`}
}
>
Click for error style notification
</ButtonSecondaryFull>
</ButtonSecondary>
<ButtonPrimaryFull onClick={this._handleDelete}>
<ButtonPrimary full onClick={this._handleDelete}>
Click to clear notifications
</ButtonPrimaryFull>
</ButtonPrimary>
</React.Fragment>
);
}

View File

@ -150,13 +150,14 @@ export default class SceneSignIn extends React.Component {
Password should be at least 8 characters
</div>
<System.ButtonPrimaryFull
<System.ButtonPrimary
full
style={{ marginTop: 48 }}
onClick={!this.state.loading ? this._handleSubmit : () => {}}
loading={this.state.loading}
>
Sign in
</System.ButtonPrimaryFull>
</System.ButtonPrimary>
</div>
);