From 5dd23896f3c23d476b10398d8acea41899d14c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lknur=20=C3=9Cltan=C4=B1r=20Sar=C4=B1?= <45620986+iibarbari@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:29:49 +0300 Subject: [PATCH] Test custom design for sign in page (#204) * add sign in page * implement logic * pr fix * add necessary line break * add sign in page * implement logic * Add basic header * add custom styling to sign in page states * Update eslint rules * Update eslint.config.js * add sign in page * Add basic header * fix lint errors * pr fixes * rebase fixes * revert to base state * sort imports * sorted imports --------- Co-authored-by: Gokhan Sari --- frontend/eslint.config.js | 25 ++-- frontend/package.json | 1 + frontend/pnpm-lock.yaml | 111 ++++++++++++++++++ .../src/components/ActivityOverlay/index.tsx | 2 +- frontend/src/components/App/index.tsx | 3 - frontend/src/components/Collapse/index.tsx | 2 +- frontend/src/components/Header/index.tsx | 39 +++--- frontend/src/components/Layout/index.tsx | 17 ++- frontend/src/components/Logo/index.tsx | 2 +- frontend/src/components/Markdown/index.tsx | 2 +- .../SignIn/FormTitle/FormTitle.module.css | 9 ++ .../src/components/SignIn/FormTitle/index.tsx | 45 +++++-- .../src/components/SignIn/SignIn.module.css | 15 +++ frontend/src/components/SignIn/index.tsx | 27 ++--- frontend/src/lib/api/index.tsx | 2 +- frontend/src/styles/components/button.css | 6 + frontend/src/styles/components/link.css | 7 ++ frontend/src/styles/components/spinner.css | 2 +- 18 files changed, 257 insertions(+), 60 deletions(-) diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 3930e019..db4a9b56 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -1,3 +1,4 @@ +import stylisticTs from "@stylistic/eslint-plugin-ts"; import pluginImport from "eslint-plugin-import"; import jsxA11y from "eslint-plugin-jsx-a11y"; import pluginReact from "eslint-plugin-react"; @@ -17,6 +18,7 @@ export default [ { rules: { "arrow-parens": "error", + "comma-dangle": ["error", "always-multiline"], "eol-last": ["error"], eqeqeq: ["error"], "max-len": ["error", { code: 140, ignoreStrings: true }], @@ -28,6 +30,8 @@ export default [ "prefer-destructuring": ["error"], "quote-props": ["error", "as-needed"], quotes: ["error", "double", { allowTemplateLiterals: true }], + semi: ["error", "always"], + "semi-style": ["error", "last"], "sort-keys": "error", }, }, @@ -35,10 +39,6 @@ export default [ // import { ...pluginImport.flatConfigs.recommended, - rules: { - "import/no-extraneous-dependencies": "error", - "import/no-unresolved": "error", - }, settings: { "import/resolver": { typescript: {}, @@ -90,12 +90,21 @@ export default [ }, // typescript + ...typescriptEslint.configs.recommended, { - ...typescriptEslint.configs.recommended[0], - languageOptions: { - parser: typescriptEslint.parser, + rules: { + "@typescript-eslint/consistent-type-definitions": ["error", "type"], + "@typescript-eslint/no-explicit-any": 0, + }, + }, + + { + plugins: { + "@stylistic/ts": stylisticTs, + }, + rules: { + "@stylistic/ts/member-delimiter-style": ["error"], }, - rules: {}, }, // typescript-sort-keys diff --git a/frontend/package.json b/frontend/package.json index 215cf9e4..9bc198a1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "@eslint/js": "^9.13.0", + "@stylistic/eslint-plugin-ts": "^2.10.1", "@types/express": "^5.0.0", "@types/node": "^22.7.7", "@types/react": "^18.3.11", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 72c2d780..c5b1cd55 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@eslint/js': specifier: ^9.13.0 version: 9.13.0 + '@stylistic/eslint-plugin-ts': + specifier: ^2.10.1 + version: 2.10.1(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3) '@types/express': specifier: ^5.0.0 version: 5.0.0 @@ -469,6 +472,12 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@stylistic/eslint-plugin-ts@2.10.1': + resolution: {integrity: sha512-XmXcixLPYfW0Z4Nf2ChnQ7CnfALNy/5gwNh22POiy64xreVYtiag4+yxN2SBEalEfoOAwDnqwDKam7e7XeoKTA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.40.0' + '@swc/core-darwin-arm64@1.7.36': resolution: {integrity: sha512-8vDczXzCgv3ceTPhEivlpGprN44YlrCK1nbfU9g2TrhV/Aiqi09W/eM5zLesdoM1Z3mJl492gc/8nlTkpDdusw==} engines: {node: '>=10'} @@ -662,6 +671,10 @@ packages: resolution: {integrity: sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.14.0': + resolution: {integrity: sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.11.0': resolution: {integrity: sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -679,6 +692,10 @@ packages: resolution: {integrity: sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.14.0': + resolution: {integrity: sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -697,6 +714,15 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.14.0': + resolution: {integrity: sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -709,6 +735,12 @@ packages: peerDependencies: eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/utils@8.14.0': + resolution: {integrity: sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -717,6 +749,10 @@ packages: resolution: {integrity: sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.14.0': + resolution: {integrity: sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -743,6 +779,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1256,6 +1297,10 @@ packages: resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@9.13.0: resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1270,6 +1315,10 @@ packages: resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -2876,6 +2925,16 @@ snapshots: '@rtsao/scc@1.1.0': {} + '@stylistic/eslint-plugin-ts@2.10.1(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/utils': 8.14.0(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3) + eslint: 9.13.0(jiti@1.21.6) + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + transitivePeerDependencies: + - supports-color + - typescript + '@swc/core-darwin-arm64@1.7.36': optional: true @@ -3071,6 +3130,11 @@ snapshots: '@typescript-eslint/types': 8.11.0 '@typescript-eslint/visitor-keys': 8.11.0 + '@typescript-eslint/scope-manager@8.14.0': + dependencies: + '@typescript-eslint/types': 8.14.0 + '@typescript-eslint/visitor-keys': 8.14.0 + '@typescript-eslint/type-utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3)': dependencies: '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3) @@ -3087,6 +3151,8 @@ snapshots: '@typescript-eslint/types@8.11.0': {} + '@typescript-eslint/types@8.14.0': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -3116,6 +3182,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.14.0(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.14.0 + '@typescript-eslint/visitor-keys': 8.14.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) @@ -3142,6 +3223,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.14.0(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + '@typescript-eslint/scope-manager': 8.14.0 + '@typescript-eslint/types': 8.14.0 + '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3) + eslint: 9.13.0(jiti@1.21.6) + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -3152,6 +3244,11 @@ snapshots: '@typescript-eslint/types': 8.11.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.14.0': + dependencies: + '@typescript-eslint/types': 8.14.0 + eslint-visitor-keys: 3.4.3 + '@ungap/structured-clone@1.2.0': {} '@vitejs/plugin-react-swc@3.7.1(vite@5.4.9(@types/node@22.7.7)(sugarss@4.0.1(postcss@8.4.47)))': @@ -3175,8 +3272,14 @@ snapshots: dependencies: acorn: 8.13.0 + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + acorn@8.13.0: {} + acorn@8.14.0: {} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -3817,6 +3920,8 @@ snapshots: eslint-visitor-keys@4.1.0: {} + eslint-visitor-keys@4.2.0: {} + eslint@9.13.0(jiti@1.21.6): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) @@ -3865,6 +3970,12 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.13.0) eslint-visitor-keys: 4.1.0 + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + esquery@1.6.0: dependencies: estraverse: 5.3.0 diff --git a/frontend/src/components/ActivityOverlay/index.tsx b/frontend/src/components/ActivityOverlay/index.tsx index fecdeb7b..108c1c96 100644 --- a/frontend/src/components/ActivityOverlay/index.tsx +++ b/frontend/src/components/ActivityOverlay/index.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { JSX, PropsWithoutRef } from "react"; import styles from "./ActivityOverlay.module.css"; -type ActivityOverlayProps = Overwrite, { +export type ActivityOverlayProps = Overwrite, { isActive: boolean; }> diff --git a/frontend/src/components/App/index.tsx b/frontend/src/components/App/index.tsx index 48bd7576..c3b18dde 100644 --- a/frontend/src/components/App/index.tsx +++ b/frontend/src/components/App/index.tsx @@ -2,7 +2,6 @@ import { Route, Switch } from "wouter"; import "../../styles/style.css"; import Bootstrap from "~/components/Bootstrap"; import Error from "~/components/Error"; -import Header from "~/components/Header"; import Home from "~/components/Home"; import Manifesto from "~/components/Manifesto"; import SignIn from "~/components/SignIn"; @@ -10,8 +9,6 @@ import SignIn from "~/components/SignIn"; export default function App() { return ( <> -
- diff --git a/frontend/src/components/Collapse/index.tsx b/frontend/src/components/Collapse/index.tsx index 2ca61ae5..b7c93b6a 100644 --- a/frontend/src/components/Collapse/index.tsx +++ b/frontend/src/components/Collapse/index.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { JSX, PropsWithoutRef, useEffect, useRef, useState } from "react"; import styles from "./Collapse.module.css"; -type CollapseProps = Overwrite, { +export type CollapseProps = Overwrite, { open: boolean; resolution?: "lg"; }>; diff --git a/frontend/src/components/Header/index.tsx b/frontend/src/components/Header/index.tsx index 482198f3..0c641c59 100644 --- a/frontend/src/components/Header/index.tsx +++ b/frontend/src/components/Header/index.tsx @@ -1,20 +1,23 @@ import { IconMenu2 } from "@tabler/icons-react"; import clsx from "clsx"; -import { ReactNode, useEffect, useMemo, useState } from "react"; -import { Link } from "wouter"; +import { JSX, PropsWithoutRef, ReactNode, useEffect, useMemo, useState } from "react"; +import { Link, useLocation } from "wouter"; import Collapse from "~/components/Collapse"; -import styles from "./Header.module.css"; import Logo from "~/components/Logo"; -import { useLocation } from "wouter"; +import styles from "./Header.module.css"; -const links: Array<{ link: string, name: string }> = [ +const links: Array<{ link: string; name: string }> = [ { link: "/", name: "Home" }, { link: "/manifesto", name: "Manifesto" }, { link: "/pricing", name: "Pricing" }, { link: "/docs", name: "Docs" }, ]; -export default function Header() { +export type HeaderProps = Overwrite, { + variant?: "basic" | "default"; +}>; + +export default function Header({ variant = "default", ...props }: HeaderProps) { const [location] = useLocation(); const [isDrawerOpen, setIsDrawerOpen] = useState(false); @@ -38,23 +41,27 @@ export default function Header() { ), []); return ( -
+
diff --git a/frontend/src/components/Layout/index.tsx b/frontend/src/components/Layout/index.tsx index bbc6815c..c8032b4b 100644 --- a/frontend/src/components/Layout/index.tsx +++ b/frontend/src/components/Layout/index.tsx @@ -1,13 +1,20 @@ import clsx from "clsx"; import { JSX, PropsWithoutRef } from "react"; +import Header, { HeaderProps } from "~/components/Header"; import styles from "./Layout.module.css"; -type LayoutProps = PropsWithoutRef +export type LayoutProps = Overwrite, { + headerProps?: HeaderProps; +}>; -export default function Layout({ children, className, ...props }: LayoutProps) { +export default function Layout({ children, className, headerProps, ...props }: LayoutProps) { return ( -
- {children} -
+ <> +
+ +
+ {children} +
+ ); } diff --git a/frontend/src/components/Logo/index.tsx b/frontend/src/components/Logo/index.tsx index b71af5d3..13fb2833 100644 --- a/frontend/src/components/Logo/index.tsx +++ b/frontend/src/components/Logo/index.tsx @@ -2,7 +2,7 @@ import { JSX, PropsWithoutRef } from "react"; import clsx from "clsx"; import styles from "./Logo.module.css"; -type LogoProps = PropsWithoutRef; +export type LogoProps = PropsWithoutRef; export default function Logo({ className, ...props }: LogoProps) { return ( diff --git a/frontend/src/components/Markdown/index.tsx b/frontend/src/components/Markdown/index.tsx index 953669b5..8b5ef3ea 100644 --- a/frontend/src/components/Markdown/index.tsx +++ b/frontend/src/components/Markdown/index.tsx @@ -2,7 +2,7 @@ import ReactMarkdown from "react-markdown"; import { Link } from "wouter"; import styles from "./Markdown.module.css"; -type MarkdownProps = { +export type MarkdownProps = { content: string; } diff --git a/frontend/src/components/SignIn/FormTitle/FormTitle.module.css b/frontend/src/components/SignIn/FormTitle/FormTitle.module.css index 6f7bc9d5..368b15fb 100644 --- a/frontend/src/components/SignIn/FormTitle/FormTitle.module.css +++ b/frontend/src/components/SignIn/FormTitle/FormTitle.module.css @@ -1,6 +1,7 @@ @import "~/styles/media.css"; .form-title { + margin-inline: auto; text-align: center; .action-group { @@ -20,6 +21,14 @@ transition: font-size 0.2s ease; } + .go-back { + color: rgba(var(--color-foreground-rgb)); + font-size: 0.875rem; + margin-block: 0.75rem 0; + margin-inline: auto; + text-align: end; + } + .summary { color: rgba(var(--color-blue-700-rgb)); font-weight: 700; diff --git a/frontend/src/components/SignIn/FormTitle/index.tsx b/frontend/src/components/SignIn/FormTitle/index.tsx index 43211fac..bf87e8f9 100644 --- a/frontend/src/components/SignIn/FormTitle/index.tsx +++ b/frontend/src/components/SignIn/FormTitle/index.tsx @@ -1,17 +1,34 @@ import clsx from "clsx"; -import { PropsWithoutRef, ReactNode, JSX } from "react"; +import { PropsWithoutRef, ReactNode, JSX, CSSProperties } from "react"; import styles from "./FormTitle.module.css"; +import { IconChevronLeft } from "@tabler/icons-react"; -type AuthenticationHeaderProps = Overwrite, "children">, { - actions?: ReactNode, - description: ReactNode, - summary: ReactNode, - title: ReactNode +export type AuthenticationHeaderProps = Overwrite, "children">, { + actions?: ReactNode; + description: ReactNode; + maxWidth?: CSSProperties["maxWidth"]; + showGoBack?: boolean; + summary: ReactNode; + title: ReactNode; }> -export default function FormTitle({ actions, className, description, summary, title, ...props }: AuthenticationHeaderProps) { +export default function FormTitle( + { + actions, + className, + description, + maxWidth = "fit-content", + showGoBack = true, + summary, + title, + ...props + }: AuthenticationHeaderProps) { return ( -
+

{summary}

@@ -27,6 +44,18 @@ export default function FormTitle({ actions, className, description, summary, ti {actions}

) : null} + + {showGoBack ? ( + + ) : null}
); } diff --git a/frontend/src/components/SignIn/SignIn.module.css b/frontend/src/components/SignIn/SignIn.module.css index a433c7d6..d9976a56 100644 --- a/frontend/src/components/SignIn/SignIn.module.css +++ b/frontend/src/components/SignIn/SignIn.module.css @@ -1,3 +1,5 @@ +@import "~/styles/media.css"; + .card { margin-inline: auto; margin-top: 2rem; @@ -20,3 +22,16 @@ font-size: 0.875rem; text-align: center; } + +@media (--min-md) and (orientation: landscape) { + .layout { + display: grid; + flex-grow: 1; + grid-template-rows: repeat(3, 1fr); + + > :global(.container) { + align-self: center; + grid-row: 2 span / 3; + } + } +} diff --git a/frontend/src/components/SignIn/index.tsx b/frontend/src/components/SignIn/index.tsx index af7ba595..36595c09 100644 --- a/frontend/src/components/SignIn/index.tsx +++ b/frontend/src/components/SignIn/index.tsx @@ -5,13 +5,13 @@ import { useErrorBoundary } from "react-error-boundary"; import { useForm } from "react-hook-form"; import { Link } from "wouter"; import ActivityOverlay from "~/components/ActivityOverlay"; -import { base64Encode } from "~/helpers/base64"; -import FormTitle from "./FormTitle"; import Layout from "~/components/Layout"; -import styles from "./SignIn.module.css"; import Title from "~/components/Title"; +import { base64Encode } from "~/helpers/base64"; import { api } from "~/lib/api"; import { setErrors } from "~/lib/form"; +import FormTitle from "./FormTitle"; +import styles from "./SignIn.module.css"; type Form = { userEmail: string; @@ -55,8 +55,8 @@ export default function SignIn() { <> Sign In - {state.isAlreadySignedIn ? ( - + + {state.isAlreadySignedIn ? (
-
- ) : state.isSignInComplete ? ( - + ) : state.isSignInComplete ? (
)} description="You are successfully signed in." + showGoBack={false} summary="Sign in" title="Signed in!" />
-
- ) : ( - + ) : (
@@ -149,14 +148,14 @@ export default function SignIn() {

{"Don't have an account?"} {" "} - Sign up + Sign up

-
- )} + )} +
); } diff --git a/frontend/src/lib/api/index.tsx b/frontend/src/lib/api/index.tsx index eb38b0f8..2e117337 100644 --- a/frontend/src/lib/api/index.tsx +++ b/frontend/src/lib/api/index.tsx @@ -39,7 +39,7 @@ export function getFetcher(requireUserAccessToken: boolean) { try { response = await apiCall(endpoint, init); - } catch (e) { + } catch { throw new Error("An error occurred while calling the API."); } diff --git a/frontend/src/styles/components/button.css b/frontend/src/styles/components/button.css index bb8cac58..aaa6cc0a 100644 --- a/frontend/src/styles/components/button.css +++ b/frontend/src/styles/components/button.css @@ -1,9 +1,14 @@ .button { + align-items: center; background: none; border: 1px solid transparent; border-radius: var(--border-radius); cursor: pointer; + display: flex; + flex-direction: row; font-weight: 500; + gap: 0.5rem; + justify-content: center; padding: 0.375em 0.75em; text-decoration: none; transition: all var(--transition-duration) ease-in-out; @@ -57,6 +62,7 @@ &.button-sm { border-radius: var(--border-radius-sm); font-size: 0.875rem; + gap: 0.25rem; padding: 0.25rem 0.5rem; } diff --git a/frontend/src/styles/components/link.css b/frontend/src/styles/components/link.css index 4d6cf00b..b5c0eb1f 100644 --- a/frontend/src/styles/components/link.css +++ b/frontend/src/styles/components/link.css @@ -1,6 +1,13 @@ .link { + align-items: center; + align-self: start; + background: transparent; color: rgb(var(--color-blue-600-rgb)); + cursor: pointer; + display: inline-flex; + flex-direction: row; font-weight: 500; + gap: 0.25rem; text-decoration: none; transition: color var(--transition-duration) ease-in-out; diff --git a/frontend/src/styles/components/spinner.css b/frontend/src/styles/components/spinner.css index 6da978a3..afdfdd05 100644 --- a/frontend/src/styles/components/spinner.css +++ b/frontend/src/styles/components/spinner.css @@ -10,7 +10,7 @@ &:before { --box-shadow-color-rgb: 0 0 0; - + animation: spinner 2000ms infinite linear; border-radius: 50%; box-shadow: rgba(var(--box-shadow-color-rgb) / 0.75) 1.5em 0 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) 1.1em 1.1em 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) 0 1.5em 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) -1.1em 1.1em 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) -1.5em 0 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) -1.1em -1.1em 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) 0 -1.5em 0 0, rgba(var(--box-shadow-color-rgb) / 0.75) 1.1em -1.1em 0 0;