diff --git a/.gitignore b/.gitignore index 4d29575..3a9c6a5 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +.vercel \ No newline at end of file diff --git a/package.json b/package.json index abaeb71..c4f0f3c 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,19 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", + "@types/classnames": "^2.2.10", "@types/jest": "^24.0.0", "@types/node": "^12.0.0", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", + "@types/yup": "^0.29.3", + "classnames": "^2.2.6", + "formik": "^2.1.4", "react": "^16.13.1", "react-dom": "^16.13.1", "react-scripts": "3.4.1", - "typescript": "~3.7.2" + "typescript": "~3.7.2", + "yup": "^0.29.1" }, "scripts": { "start": "react-scripts start", @@ -24,7 +29,7 @@ }, "lint-staged": { "src/**/*.{js,jsx,ts,tsx}": [ - "eslint", + "eslint --fix", "prettier --write --tab-width 4", "git add" ], diff --git a/src/App.scss b/src/App.scss index 20b3337..dbfb868 100644 --- a/src/App.scss +++ b/src/App.scss @@ -23,7 +23,7 @@ limitations under the License. .topSpacer { @include spacer; - height: 30vh; + height: 10vh; } .bottomSpacer { diff --git a/src/App.tsx b/src/App.tsx index a4c2df7..43dd368 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,11 +18,13 @@ import React from "react"; import "./App.scss"; import SingleColumn from "./layouts/SingleColumn"; +import CreateLinkTile from "./components/CreateLinkTile"; const App: React.FC = () => { return (
+
); diff --git a/src/_color-scheme.scss b/src/_color-scheme.scss index eee6eb0..ff077ca 100644 --- a/src/_color-scheme.scss +++ b/src/_color-scheme.scss @@ -4,3 +4,5 @@ $foreground: #000000; $font: #333333; $grey: #666666; $accent: #0098d4; +$error: #d6001c; +$link: #0098d4; diff --git a/src/_error.scss b/src/_error.scss new file mode 100644 index 0000000..83aa5d6 --- /dev/null +++ b/src/_error.scss @@ -0,0 +1,4 @@ +@mixin error { + color: $error; + border-color: $error; +} diff --git a/src/components/Button.scss b/src/components/Button.scss index 35497aa..c34c521 100644 --- a/src/components/Button.scss +++ b/src/components/Button.scss @@ -17,19 +17,19 @@ limitations under the License. @import "../color-scheme"; .button { - width: 100%; + width: 100%; - padding: 1rem; - border-radius: 1000px; - border: 0; + padding: 1rem; + border-radius: 2rem; + border: 0; - background-color: $foreground; - color: $background; + background-color: $foreground; + color: $background; - font-size: 14px; - font-weight: 500px; + font-size: 14px; + font-weight: 500; } .buttonHighlight { - background-color: $accent; + background-color: $accent; } diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 57f0735..e65cab0 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -27,37 +27,43 @@ interface IProps extends React.ButtonHTMLAttributes { /** * Like a normal button except it will flash content when clicked. */ -const Button: React.FC = ({ - onClick, - children, - flashChildren, - className, - ...restProps -}: IProps) => { - const [wasClicked, setWasClicked] = React.useState(false); +const Button: React.FC< + IProps & React.RefAttributes +> = React.forwardRef( + ( + { onClick, children, flashChildren, className, ...restProps }: IProps, + ref: React.Ref + ) => { + const [wasClicked, setWasClicked] = React.useState(false); - const wrappedOnClick: React.MouseEventHandler = (e) => { - if (onClick) { - onClick(e); - } + const wrappedOnClick: React.MouseEventHandler = (e) => { + if (onClick) { + onClick(e); + } - setWasClicked(true); - window.setTimeout(() => { - setWasClicked(false); - }, 1000); - }; + setWasClicked(true); + window.setTimeout(() => { + setWasClicked(false); + }, 1000); + }; - const content = wasClicked ? flashChildren : children; + const content = wasClicked && flashChildren ? flashChildren : children; - const classNames = classnames("button", className, { - buttonHighlight: wasClicked, - }); + const classNames = classnames("button", className, { + buttonHighlight: wasClicked, + }); - return ( - - ); -}; + return ( + + ); + } +); export default Button; diff --git a/src/components/CreateLinkTile.scss b/src/components/CreateLinkTile.scss new file mode 100644 index 0000000..7ad283d --- /dev/null +++ b/src/components/CreateLinkTile.scss @@ -0,0 +1,30 @@ +/* +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. +*/ + +.createLinkTile { + background: none; + + > * { + margin: 12px 0; + width: 100%; + } + + > form { + display: grid; + row-gap: 24px; + align-self: center; + } +} diff --git a/src/components/CreateLinkTile.tsx b/src/components/CreateLinkTile.tsx new file mode 100644 index 0000000..aed0f60 --- /dev/null +++ b/src/components/CreateLinkTile.tsx @@ -0,0 +1,116 @@ +/* +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, useRef } from "react"; +import Tile from "./Tile"; +import Button from "./Button"; +import TextButton from "./TextButton"; +import Input from "./Input"; +import { Formik, Form } from "formik"; +import * as Yup from "yup"; + +import "./CreateLinkTile.scss"; + +interface ILinkNotCreatedTileProps { + setLink: React.Dispatch>; +} + +const LinkNotCreatedTile = (props: ILinkNotCreatedTileProps) => { + return ( + +

+ Create shareable links to Matrix rooms, users or messages + without being tied to any app +

+ link + ) + .required("Required"), + })} + onSubmit={(values) => { + props.setLink( + document.location.protocol + + "//" + + document.location.host + + "/" + + values.identifier + ); + }} + > +
+ + +
+
+
+ ); +}; + +interface ILinkCreatedTileProps { + link: string; + setLink: React.Dispatch>; +} + +const LinkCreatedTile: React.FC = (props) => { + const buttonRef = useRef(null); + + // Focus button on render + useEffect(() => { + if (buttonRef && buttonRef.current) { + buttonRef.current.focus(); + } + }); + + return ( + + props.setLink("")}> + Create another lnk + +

{props.link}

+ +
+ ); +}; + +const CreateLinkTile: React.FC = () => { + const [link, setLink] = React.useState(""); + console.log(link); + if (!link) { + return ; + } else { + return ; + } +}; + +export default CreateLinkTile; diff --git a/src/components/Input.scss b/src/components/Input.scss new file mode 100644 index 0000000..e6ca735 --- /dev/null +++ b/src/components/Input.scss @@ -0,0 +1,40 @@ +/* +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"; +@import "../error"; + +.input { + width: 100%; + padding: 12px; + + background: $background; + + border: 1px solid $font; + border-radius: 24px; + + font-size: 14px; + line-height: 24px; + + &.error { + @include error; + } +} + +.inputError { + @include error; + text-align: center; +} diff --git a/src/components/Input.tsx b/src/components/Input.tsx new file mode 100644 index 0000000..f1217f1 --- /dev/null +++ b/src/components/Input.tsx @@ -0,0 +1,48 @@ +/* +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 { useField } from "formik"; + +import "./Input.scss"; + +interface IProps extends React.InputHTMLAttributes { + name: string; + type: string; +} + +const Input: React.FC = ({ className, ...props }) => { + const [field, meta] = useField(props); + + const error = + meta.touched && meta.error ? ( +
{meta.error}
+ ) : null; + + const classNames = classnames("input", className, { + error: meta.error, + }); + + return ( + <> + + {error} + + ); +}; + +export default Input; diff --git a/src/components/TextButton.scss b/src/components/TextButton.scss new file mode 100644 index 0000000..a5168e0 --- /dev/null +++ b/src/components/TextButton.scss @@ -0,0 +1,27 @@ +/* +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"; + +.textButton { + background: none; + border: none; + color: $link; + font-style: normal; + font-weight: normal; + font-size: 14px; + line-height: 24px; +} diff --git a/src/components/TextButton.tsx b/src/components/TextButton.tsx new file mode 100644 index 0000000..0d3de8d --- /dev/null +++ b/src/components/TextButton.tsx @@ -0,0 +1,33 @@ +/* +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 "./TextButton.scss"; + +const TextButton: React.FC> = ({ + className, + ...restProps +}) => { + return ( +