diff --git a/.gitignore b/.gitignore
index 3a9c6a5..0bd7603 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,6 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
-.vercel
\ No newline at end of file
+.vercel
+
+storybook-static
diff --git a/.storybook/preview.js b/.storybook/preview.js
index cff5d31..bebbd5b 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -5,13 +5,15 @@ import { withKnobs } from '@storybook/addon-knobs';
import { withDesign } from 'storybook-addon-designs'
import { addParameters } from '@storybook/react';
+import SingleColumn from '../src/layouts/SingleColumn';
+
// Default styles
import "../src/index.scss";
addDecorator(
- storyFn =>
{storyFn()}
+ storyFn => {storyFn()}
);
addDecorator(withA11y);
@@ -22,7 +24,7 @@ addDecorator(withDesign);
addParameters({
backgrounds: [
- {name: 'light', value: '#F4F4F4'},
- {name: 'white', value: '#FFFFFF', default: true},
+ {name: 'light', value: '#F4F4F4', default: true},
+ {name: 'white', value: '#FFFFFF'},
],
});
diff --git a/README.md b/README.md
index 42c4536..0694cfb 100644
--- a/README.md
+++ b/README.md
@@ -44,3 +44,6 @@ You can discuss matrix.to in
[`#matrix.to:matrix.org`](https://matrix.to/#/#matrix.to:matrix.org)
A development build of matrix-two can be found at https://matrix-to.vercel.app
+
+A preview of all components can be found at
+https://matrix-to-storybook.vercel.app
diff --git a/src/App.scss b/src/App.scss
index 648cdf6..1d4ff36 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+@import "./color-scheme";
+
#root {
background-color: $app-background;
}
diff --git a/src/_color-scheme.scss b/src/_color-scheme.scss
index d7fc24c..1c32596 100644
--- a/src/_color-scheme.scss
+++ b/src/_color-scheme.scss
@@ -22,3 +22,4 @@ $grey: #666666;
$accent: #0098d4;
$error: #d6001c;
$link: #0098d4;
+$borders: #f4f4f4;
diff --git a/src/components/Avatar.scss b/src/components/Avatar.scss
new file mode 100644
index 0000000..7895a82
--- /dev/null
+++ b/src/components/Avatar.scss
@@ -0,0 +1,24 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+@import "../color-scheme";
+
+.avatar {
+ border-radius: 100%;
+ border: 1px solid $borders;
+ height: 50px;
+ width: 50px;
+}
diff --git a/src/components/Avatar.stories.tsx b/src/components/Avatar.stories.tsx
new file mode 100644
index 0000000..d586c6f
--- /dev/null
+++ b/src/components/Avatar.stories.tsx
@@ -0,0 +1,39 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+
+import { UserAvatar } from "./Avatar";
+
+export default {
+ title: "Avatar",
+ parameters: {
+ design: {
+ type: "figma",
+ url:
+ "https://www.figma.com/file/WSXjCGc1k6FVI093qhlzOP/04-Recieving-share-link?node-id=143%3A5853",
+ },
+ },
+};
+
+export const Default: React.FC<{}> = () => (
+
+);
diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx
new file mode 100644
index 0000000..1a73b9f
--- /dev/null
+++ b/src/components/Avatar.tsx
@@ -0,0 +1,86 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React, { useEffect, useState } from "react";
+import classNames from "classnames";
+import { convertMXCtoMediaQuery } from "cypher";
+import { Room } from "cypher/src/schemas/PublicRoomsSchema";
+import { User } from "cypher/src/schemas/UserSchema";
+import logo from "../imgs/matrix-logo.svg";
+
+import "./Avatar.scss";
+
+interface IProps {
+ className?: string;
+ avatarUrl: string;
+ label: string;
+}
+
+const Avatar: React.FC = ({ className, avatarUrl, label }: IProps) => {
+ const [src, setSrc] = useState(avatarUrl);
+ useEffect(() => {
+ setSrc(avatarUrl);
+ }, [avatarUrl]);
+
+ return (
+ setSrc(logo)}
+ alt={label}
+ className={classNames("avatar", className)}
+ />
+ );
+};
+
+interface IPropsUserAvatar {
+ user: User;
+}
+
+export const UserAvatar: React.FC = ({
+ user,
+}: IPropsUserAvatar) => (
+
+);
+
+interface IPropsRoomAvatar {
+ room: Room;
+}
+
+export const RoomAvatar: React.FC = ({
+ room,
+}: IPropsRoomAvatar) => (
+
+);
+
+export default Avatar;
diff --git a/src/components/EventPreview.tsx b/src/components/EventPreview.tsx
new file mode 100644
index 0000000..f0eef35
--- /dev/null
+++ b/src/components/EventPreview.tsx
@@ -0,0 +1,36 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+import { Room } from "cypher/src/schemas/PublicRoomsSchema";
+import { Event } from "cypher/src/schemas/EventSchema";
+
+import RoomPreview from "./RoomPreview";
+
+interface IProps {
+ room: Room;
+ event: Event;
+}
+
+const EventPreview: React.FC = ({ room, event }: IProps) => (
+ <>
+
+ "{event.content}"
+ {event.sender}
+ >
+);
+
+export default EventPreview;
diff --git a/src/components/InviteTile.scss b/src/components/InviteTile.scss
new file mode 100644
index 0000000..d1efbd2
--- /dev/null
+++ b/src/components/InviteTile.scss
@@ -0,0 +1,25 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.inviteTile {
+ .button {
+ margin-top: 24px;
+ }
+
+ > .textButton {
+ margin-top: 28px;
+ }
+}
diff --git a/src/components/InviteTile.stories.tsx b/src/components/InviteTile.stories.tsx
new file mode 100644
index 0000000..e42b544
--- /dev/null
+++ b/src/components/InviteTile.stories.tsx
@@ -0,0 +1,122 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+
+import InviteTile from "./InviteTile";
+import UserPreview, { InviterPreview } from "./UserPreview";
+import RoomPreview, { RoomPreviewWithTopic } from "./RoomPreview";
+
+export default {
+ title: "InviteTile",
+ parameters: {
+ design: {
+ type: "figma",
+ url:
+ "https://figma.com/file/WSXjCGc1k6FVI093qhlzOP/04-Recieving-share-link?node-id=59%3A334",
+ },
+ },
+};
+
+export const withLink: React.FC<{}> = () => (
+
+ This is an invite with a link
+
+);
+
+export const withInstruction: React.FC<{}> = () => (
+
+ This is an invite with an instruction
+
+);
+
+export const withUserPreview: React.FC<{}> = () => (
+
+
+
+);
+
+export const withRoomPreviewAndRoomTopic: React.FC<{}> = () => (
+
+
+
+);
+
+export const withRoomPreviewAndInviter: React.FC<{}> = () => (
+
+
+
+
+);
diff --git a/src/components/InviteTile.tsx b/src/components/InviteTile.tsx
new file mode 100644
index 0000000..154db4c
--- /dev/null
+++ b/src/components/InviteTile.tsx
@@ -0,0 +1,64 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+
+import Tile from "./Tile";
+import LinkButton from "./LinkButton";
+import TextButton from "./TextButton";
+
+import "./InviteTile.scss";
+
+export interface InviteLink {
+ type: "link";
+ link: string;
+}
+
+export interface InviteInstruction {
+ type: "instruction";
+ text: string;
+}
+
+type InviteAction = InviteLink | InviteInstruction;
+
+interface IProps {
+ children?: React.ReactNode;
+ inviteAction: InviteAction;
+}
+
+const InviteTile: React.FC = ({ children, inviteAction }: IProps) => {
+ let invite: React.ReactNode;
+ switch (inviteAction.type) {
+ case "link":
+ invite = (
+ Accept invite
+ );
+ break;
+ case "instruction":
+ invite = {inviteAction.text}
;
+ break;
+ }
+
+ return (
+
+ {children}
+ {invite}
+ Advanced options
+
+ );
+};
+
+export default InviteTile;
diff --git a/src/components/LinkButton.tsx b/src/components/LinkButton.tsx
new file mode 100644
index 0000000..bd98d73
--- /dev/null
+++ b/src/components/LinkButton.tsx
@@ -0,0 +1,28 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+import classnames from "classnames";
+
+import "./Button.scss";
+
+interface IProps extends React.LinkHTMLAttributes {}
+
+const LinkButton: React.FC = ({ className, ...props }: IProps) => (
+
+);
+
+export default LinkButton;
diff --git a/src/components/MatrixTile.tsx b/src/components/MatrixTile.tsx
index 8855b95..d76d0eb 100644
--- a/src/components/MatrixTile.tsx
+++ b/src/components/MatrixTile.tsx
@@ -26,8 +26,8 @@ const MatrixTile: React.FC = () => {
- Matrix.to is a stateless URL redirecting service for the{" "}
-
Matrix ecosystem.
+ This invite uses
Matrix, an
+ open network for secure, decentralized communication.
);
diff --git a/src/components/RoomPreview.scss b/src/components/RoomPreview.scss
new file mode 100644
index 0000000..ef82fb9
--- /dev/null
+++ b/src/components/RoomPreview.scss
@@ -0,0 +1,31 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.roomPreview {
+ > .avatar {
+ margin-top: 20px;
+ margin-bottom: 16px;
+ }
+
+ > h1 {
+ font-size: 20px;
+ margin-bottom: 4px;
+ }
+}
+
+.roomTopic {
+ padding-top: 32px;
+}
diff --git a/src/components/RoomPreview.tsx b/src/components/RoomPreview.tsx
new file mode 100644
index 0000000..9d18ee5
--- /dev/null
+++ b/src/components/RoomPreview.tsx
@@ -0,0 +1,50 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+import { Room } from "cypher/src/schemas/PublicRoomsSchema";
+
+import { RoomAvatar } from "./Avatar";
+
+import "./RoomPreview.scss";
+
+interface IProps {
+ room: Room;
+}
+
+const RoomPreview: React.FC = ({ room }: IProps) => {
+ const roomAlias = room.aliases ? room.aliases[0] : room.room_id;
+ return (
+
+
+
{room.name}
+
{room.num_joined_members.toLocaleString()} members
+
{roomAlias}
+
+ );
+};
+
+export const RoomPreviewWithTopic: React.FC = ({ room }: IProps) => {
+ const topic = room.topic ? {room.topic}
: null;
+ return (
+ <>
+
+ {topic}
+ >
+ );
+};
+
+export default RoomPreview;
diff --git a/src/components/Tile.scss b/src/components/Tile.scss
index 57c22ee..a18f8ad 100644
--- a/src/components/Tile.scss
+++ b/src/components/Tile.scss
@@ -19,11 +19,15 @@ limitations under the License.
.tile {
background-color: $background;
- border-radius: 8px;
- padding: 1rem;
+ border-radius: 16px;
+ padding: 2rem;
display: grid;
justify-items: center;
text-align: center;
+
+ p {
+ color: $grey;
+ }
}
diff --git a/src/components/UserPreview.scss b/src/components/UserPreview.scss
new file mode 100644
index 0000000..d35dfda
--- /dev/null
+++ b/src/components/UserPreview.scss
@@ -0,0 +1,74 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+@import "../color-scheme";
+
+.userPreview {
+ width: 100%;
+
+ > .avatar {
+ margin-top: 20px;
+ margin-bottom: 16px;
+ }
+
+ h1 {
+ font-size: 20px;
+ margin-bottom: 4px;
+ }
+
+ p {
+ margin-bottom: 16px;
+ }
+
+ hr {
+ width: 100%;
+ margin: 0;
+ opacity: 0.2;
+ }
+}
+
+.miniUserPreview {
+ width: 100%;
+
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ border: 1px solid $app-background;
+ border-radius: 16px;
+ padding: 6px 16px;
+
+ > div {
+ flex-grow: 1;
+ text-align: left;
+ }
+
+ h1 {
+ font-weight: normal;
+ font-size: 14px;
+ line-height: 20px;
+ text-align: left;
+ }
+
+ p {
+ line-height: 20px;
+ }
+
+ .avatar {
+ flex-grow: 0;
+ flex-shrink: 0;
+ }
+}
diff --git a/src/components/UserPreview.tsx b/src/components/UserPreview.tsx
new file mode 100644
index 0000000..e0992fd
--- /dev/null
+++ b/src/components/UserPreview.tsx
@@ -0,0 +1,50 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+import { User } from "cypher/src/schemas/UserSchema";
+
+import { UserAvatar } from "./Avatar";
+
+import "./UserPreview.scss";
+
+interface IProps {
+ user: User;
+ userId: string;
+}
+
+const UserPreview: React.FC = ({ user, userId }: IProps) => (
+
+
+
{user.displayname} invites you to connect
+
{userId}
+
+
+);
+
+export default UserPreview;
+
+export const InviterPreview: React.FC = ({ user, userId }: IProps) => (
+
+
+
+ Invited by {user.displayname}
+
+
{userId}
+
+
+
+);
diff --git a/src/contexts/ClientContext.ts b/src/contexts/ClientContext.ts
new file mode 100644
index 0000000..0b14e47
--- /dev/null
+++ b/src/contexts/ClientContext.ts
@@ -0,0 +1,65 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from "react";
+
+import { Client, discoverServer } from "cypher";
+import { prefixFetch } from "cypher/src/utils/fetch";
+
+type State = {
+ clientURL: string;
+ client: Client;
+}[];
+
+// Actions are a discriminated union.
+export enum ActionTypes {
+ AddClient = "ADD_CLIENT",
+ RemoveClient = "REMOVE_CLIENT",
+}
+
+export interface AddClient {
+ action: ActionTypes.AddClient;
+ clientURL: string;
+}
+
+export interface RemoveClient {
+ action: ActionTypes.RemoveClient;
+ clientURL: string;
+}
+
+export type Action = AddClient | RemoveClient;
+
+export const INITIAL_STATE: State = [];
+export const reducer = async (state: State, action: Action): Promise => {
+ switch (action.action) {
+ case ActionTypes.AddClient:
+ return state.filter((x) => x.clientURL !== action.clientURL);
+
+ case ActionTypes.RemoveClient:
+ if (!state.filter((x) => x.clientURL === action.clientURL)) {
+ const resolvedURL = await discoverServer(action.clientURL);
+ state.push({
+ clientURL: resolvedURL,
+ client: prefixFetch(resolvedURL),
+ });
+ }
+ }
+ return state;
+};
+
+// The null is a hack to make the type checker happy
+// create context does not need an argument
+export default React.createContext(null);