diff --git a/example-web/my-app/src/index.css b/example-web/my-app/src/index.css index ec2585e8..4a1df4db 100644 --- a/example-web/my-app/src/index.css +++ b/example-web/my-app/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/package-lock.json b/package-lock.json index 8cfc7bfe..169f7b91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,6 @@ "nodemon": "^2.0.20", "postcss": "^8.4.21", "signify-ts": "https://github.com/WebOfTrust/signify-ts", - "tailwindcss": "^3.2.4", "ts-node": "^10.9.1", "typescript": "^4.9.4", "vite": "^4.5.1", @@ -56,17 +55,6 @@ "node": ">=0.10.0" } }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "dev": true, @@ -1627,11 +1615,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "dev": true, - "license": "MIT" - }, "node_modules/anymatch": { "version": "3.1.3", "dev": true, @@ -1644,11 +1627,6 @@ "node": ">= 8" } }, - "node_modules/arg": { - "version": "5.0.2", - "dev": true, - "license": "MIT" - }, "node_modules/argparse": { "version": "2.0.1", "dev": true, @@ -2142,14 +2120,6 @@ "node": ">=6" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/camelize": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", @@ -2295,14 +2265,6 @@ "dev": true, "license": "MIT" }, - "node_modules/commander": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/complex.js": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", @@ -2483,17 +2445,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/csstype": { "version": "3.1.3", "license": "MIT" @@ -2576,11 +2527,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/diff": { "version": "4.0.2", "dev": true, @@ -2615,11 +2561,6 @@ "node": ">=8" } }, - "node_modules/dlv": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, "node_modules/doctrine": { "version": "3.0.0", "dev": true, @@ -4238,14 +4179,6 @@ "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", "dev": true }, - "node_modules/jiti": { - "version": "1.21.0", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "license": "MIT" @@ -4374,19 +4307,6 @@ "libsodium-sumo": "^0.7.13" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -4564,16 +4484,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mz": { - "version": "2.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.7", "funding": [ @@ -4754,14 +4664,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.1", "dev": true, @@ -5058,22 +4960,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/pkg-dir": { "version": "5.0.0", "dev": true, @@ -5112,112 +4998,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-import": { - "version": "15.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-value-parser": { "version": "4.2.0", "license": "MIT" @@ -5422,14 +5202,6 @@ "react-dom": ">=16.14.0" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "dev": true, @@ -6049,46 +5821,6 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" }, - "node_modules/sucrase": { - "version": "3.34.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/supports-color": { "version": "7.2.0", "dev": true, @@ -6111,66 +5843,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tailwindcss": { - "version": "3.3.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.19.1", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/text-table": { "version": "0.2.0", "dev": true, "license": "MIT" }, - "node_modules/thenify": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/timers-browserify": { "version": "2.0.12", "dev": true, @@ -6218,11 +5895,6 @@ "nodetouch": "bin/nodetouch.js" } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/ts-node": { "version": "10.9.2", "dev": true, @@ -6729,14 +6401,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.3.4", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 14" - } - }, "node_modules/yn": { "version": "3.1.1", "dev": true, diff --git a/package.json b/package.json index 4f8f8b6a..d2df7cf7 100755 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "nodemon": "^2.0.20", "postcss": "^8.4.21", "signify-ts": "https://github.com/WebOfTrust/signify-ts", - "tailwindcss": "^3.2.4", "ts-node": "^10.9.1", "typescript": "^4.9.4", "vite": "^4.5.1", diff --git a/postcss.config.cjs b/postcss.config.cjs deleted file mode 100644 index 33ad091d..00000000 --- a/postcss.config.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/src/assets/styles/tailwind.css b/src/assets/styles/tailwind.css deleted file mode 100644 index bd6213e1..00000000 --- a/src/assets/styles/tailwind.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; \ No newline at end of file diff --git a/src/components/appbar.tsx b/src/components/appbar.tsx deleted file mode 100644 index 3b14ebe9..00000000 --- a/src/components/appbar.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import logo from "@assets/img/128_keri_logo.png"; - -interface IAppbar {} - -export function Appbar(props: IAppbar): JSX.Element { - return ( - - ); -} diff --git a/src/components/createIdentifierCard.tsx b/src/components/createIdentifierCard.tsx index 6e2874bb..81503a46 100644 --- a/src/components/createIdentifierCard.tsx +++ b/src/components/createIdentifierCard.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; -import { Button, Input } from "@components/ui"; +import { Button, Input, Text, Box, Flex, NewButton } from "@components/ui"; import { hasWhiteSpace, removeWhiteSpace } from "@pages/background/utils"; interface ICreateIdentifierCard { @@ -35,16 +35,17 @@ export function CreateIdentifierCard( hasError = true; } else if (hasWhiteSpace(name)) { setNameError( -
+ {formatMessage({ id: "identifier.error.noWhiteSpace" })}{" "} - -
+ + ); hasError = true; } @@ -57,32 +58,28 @@ export function CreateIdentifierCard( return ( <> -
-
- setName(e.target.value)} - /> -
-
- -
+ + +
+ setName(e.target.value)} + /> +
+ + + +
); diff --git a/src/components/credentialCard.tsx b/src/components/credentialCard.tsx index 7069d16e..16df803a 100644 --- a/src/components/credentialCard.tsx +++ b/src/components/credentialCard.tsx @@ -26,25 +26,23 @@ export function CredentialCard({ credential }: ICredentialCard): JSX.Element { return ( <> - -
- - {credential.schema.title} - - - {credential.schema.credentialType} - -
+ + + {credential.schema.title} + - - - {credential.schema.description} - - + + {credential.schema.credentialType} + + + {credential.schema.description} + + + <> {formatMessage({ id: "credential.issue.label" })}{" "} - + {credential.issueeName} @@ -52,23 +50,23 @@ export function CredentialCard({ credential }: ICredentialCard): JSX.Element {
- + {formatMessage({ id: "credential.lastUsed.label" })}{" "} - - November 08, 2023 - + November 08, 2023
{credential.status?.et === "iss" ? ( -
+ -

{formatMessage({ id: "credential.valid" })}

-
+ {formatMessage({ id: "credential.valid" })} +
) : ( -
+ -

{formatMessage({ id: "credential.revoked" })}

-
+ + {formatMessage({ id: "credential.revoked" })} + +
)} diff --git a/src/components/credentialList.tsx b/src/components/credentialList.tsx index 1ad70007..dd446b4a 100644 --- a/src/components/credentialList.tsx +++ b/src/components/credentialList.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; import { CredentialCard } from "@components/credentialCard"; -import { Loader } from "@components/ui"; +import { Loader, Flex, Box, Text } from "@components/ui"; import { IMessage } from "@config/types"; export function CredentialList(): JSX.Element { @@ -25,17 +25,19 @@ export function CredentialList(): JSX.Element { return ( <> {isLoading ? ( -
+ -
+ ) : null} {credentials.map((credential, index) => ( -
+ -
+ ))} {!isLoading && !credentials?.length ? ( -

{formatMessage({ id: "message.noItems" })}

+ + {formatMessage({ id: "message.noItems" })} + ) : ( <> )} diff --git a/src/components/identifierCard.tsx b/src/components/identifierCard.tsx index 0514ef25..95cbeccc 100644 --- a/src/components/identifierCard.tsx +++ b/src/components/identifierCard.tsx @@ -1,7 +1,7 @@ import { obfuscateString } from "@pages/background/utils"; import { useIntl } from "react-intl"; import { Tooltip as ReactTooltip } from "react-tooltip"; -import { Card, Text, Subtext } from "@components/ui"; +import { Card, Text, Subtext, Flex, IconButton } from "@components/ui"; import IdentifierIcon from "@components/shared/icons/identifier"; import CopyIcon from "@components/shared/icons/copy"; import { IIdentifier } from "@config/types"; @@ -16,23 +16,26 @@ export function IdentifierCard({ aid }: IIdentifierCard): JSX.Element { return ( <> -
+
- + {formatMessage({ id: "identifier.alias.label" })}{" "} - + {aid.name}
-
+
- + {formatMessage({ id: "identifier.aid.label" })}{" "} {obfuscateString(aid.prefix)} @@ -41,28 +44,33 @@ export function IdentifierCard({ aid }: IIdentifierCard): JSX.Element {
-
-

{aid.prefix}

- -
+ +
- {/* COMMENTED OUT FOR THE DEMO -
-
- Credentials Received: - 13 -
-
- Last Used: - November 08, 2023 -
-
*/} + + {/* COMMENTED OUT FOR THE DEMO + +
+ + Credentials Received:{" "} + + 13 +
+
+ + Last Used:{" "} + + November 08, 2023 +
+
*/}
); diff --git a/src/components/identifierList.tsx b/src/components/identifierList.tsx index 0b34656b..2261442f 100644 --- a/src/components/identifierList.tsx +++ b/src/components/identifierList.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; import { IdentifierCard } from "@components/identifierCard"; -import { Button, Drawer, Text, Loader } from "@components/ui"; +import { Button, Box, Drawer, Flex, Text, Loader } from "@components/ui"; import { IMessage } from "@config/types"; import { CreateIdentifierCard } from "@components/createIdentifierCard"; @@ -60,24 +60,21 @@ export function IdentifierList(): JSX.Element { return ( <> -
- -
+ {isLoading ? ( -
+ -
+ ) : null} setShowDrawer(false)} header={ - + {formatMessage({ id: "identifier.create.title" })} } @@ -89,12 +86,14 @@ export function IdentifierList(): JSX.Element { /> {aids.map((aid, index) => ( -
+ -
+ ))} {!isLoading && !aids?.length ? ( -

{formatMessage({ id: "message.noItems" })}

+ + {formatMessage({ id: "message.noItems" })} + ) : ( <> )} diff --git a/src/components/main.tsx b/src/components/main.tsx index fb5936e5..0bd25511 100644 --- a/src/components/main.tsx +++ b/src/components/main.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { styled } from "styled-components"; -import { Text } from "@components/ui"; +import { Text, MainBox, Box } from "@components/ui"; import { Sidebar, SIDEBAR, SIDEBAR_KEYS } from "@components/sidebar"; import { SelectIdentifier } from "@components/selectIdentifier"; import { SelectCredential } from "@components/selectCredential"; @@ -15,7 +15,7 @@ interface IMain { title?: string; } -const StyledMainContainer = styled.div` +const StyledMainContainer = styled(Box)` background-color: ${(props) => props.theme?.colors?.secondary}; color: ${(props) => props.theme?.colors?.text}; `; @@ -85,7 +85,7 @@ export function Main(props: IMain): JSX.Element { }; return ( -
+ - -
- + +
+ {activeSidebar?.title} -
{renderItems()}
+ + {renderItems()} +
-
+ ); } diff --git a/src/components/selectCredential.tsx b/src/components/selectCredential.tsx index 905794e8..8f54f159 100644 --- a/src/components/selectCredential.tsx +++ b/src/components/selectCredential.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; import { CredentialCard } from "@components/credentialCard"; -import { Button, Loader } from "@components/ui"; +import { Button, Loader, Flex, Box } from "@components/ui"; import { IMessage } from "@config/types"; export function SelectCredential(): JSX.Element { @@ -51,22 +51,23 @@ export function SelectCredential(): JSX.Element { return ( <> {isLoading ? ( -
+ -
+ ) : null} {credentials.map((credential, index) => ( -
-
+ + - -
-
+ + + + + ))} ); diff --git a/src/components/selectIdentifier.tsx b/src/components/selectIdentifier.tsx index b5044555..594983ea 100644 --- a/src/components/selectIdentifier.tsx +++ b/src/components/selectIdentifier.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; import { IdentifierCard } from "@components/identifierCard"; -import { Button, Drawer, Text, Loader } from "@components/ui"; +import { Box, Button, Drawer, Flex, Text, Loader } from "@components/ui"; import { IMessage } from "@config/types"; import { CreateIdentifierCard } from "@components/createIdentifierCard"; @@ -82,24 +82,21 @@ export function SelectIdentifier(): JSX.Element { return ( <> -
- -
+ {isLoading ? ( -
+ -
+ ) : null} setShowDrawer(false)} header={ - + {formatMessage({ id: "identifier.create.title" })} } @@ -111,17 +108,16 @@ export function SelectIdentifier(): JSX.Element { /> {aids.map((aid, index) => ( -
-
+ + - -
-
+ + + + + ))} ); diff --git a/src/components/shared/icons/close.tsx b/src/components/shared/icons/close.tsx new file mode 100644 index 00000000..2bd60511 --- /dev/null +++ b/src/components/shared/icons/close.tsx @@ -0,0 +1,28 @@ +export default function Close({ + size, + scale = 4, +}: { + size: number; + scale?: number; +}) { + return ( + + + + + ); +} diff --git a/src/components/shared/icons/loader.tsx b/src/components/shared/icons/loader.tsx index a71a1c67..9b6a7cd8 100644 --- a/src/components/shared/icons/loader.tsx +++ b/src/components/shared/icons/loader.tsx @@ -1,22 +1,21 @@ +import { SpinAnimationSvg } from "@components/ui/animations"; + export default function Loader({ - className, fillColor, size, scale = 4, }: { - className?: string; fillColor: string; size: number; scale?: number; }) { return ( - - + ); } diff --git a/src/components/shared/icons/popup-arrow.tsx b/src/components/shared/icons/popup-arrow.tsx index 48ccbbbd..ffd52e08 100644 --- a/src/components/shared/icons/popup-arrow.tsx +++ b/src/components/shared/icons/popup-arrow.tsx @@ -1,15 +1,14 @@ +import { BounceAnimationSvg } from "@components/ui/animations"; + export default function PopupArrow({ size, scale = 4, - className, }: { size: number; scale?: number; - className?: string; }) { return ( - - + ); } diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx deleted file mode 100644 index 4628f742..00000000 --- a/src/components/sidebar.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import { useIntl, FormattedMessage } from "react-intl"; -import { styled } from "styled-components"; -import IdentifierIcon from "@components/shared/icons/identifier"; -import CredentialIcon from "@components/shared/icons/credential"; -import SigninIcon from "@components/shared/icons/signin"; -import LockIcon from "@components/shared/icons/lock"; - -export const SIDEBAR_KEYS = { - identifiers: "identifiers", - credentials: "credentials", - signin: "sign-ins", -}; - -export const SIDEBAR = [ - { - id: SIDEBAR_KEYS.identifiers, - icon: , - title: , - }, - { - id: SIDEBAR_KEYS.credentials, - icon: , - title: , - }, - { - id: SIDEBAR_KEYS.signin, - icon: , - title: , - }, -]; - -interface ISidebar { - active: any; - onClickLink: (active: any) => void; - disabled?: boolean; - onSignout: () => void; - title?: string; - logo?: string; -} - -interface IStyledMenu { - $isActive?: boolean; -} - -const StyledMenu = styled.div` - background-color: ${({ $isActive, theme }) => - $isActive ? theme?.colors?.secondary : ""}; - color: ${({ $isActive, theme }) => ($isActive ? theme?.colors?.subtext : "")}; - &:hover { - background-color: ${({ theme }) => theme?.colors?.secondary}; - color: ${({ theme }) => theme?.colors?.subtext}; - } -`; - -const StyledBottomMenu = styled.div` - &:hover { - background-color: ${({ theme }) => theme?.colors?.error}; - color: ${({ theme }) => theme?.colors?.subtext}; - } -`; - -export function Sidebar(props: ISidebar): JSX.Element { - const { formatMessage } = useIntl(); - return ( - - ); -} diff --git a/src/components/sidebar/header.tsx b/src/components/sidebar/header.tsx new file mode 100644 index 00000000..13ab92a7 --- /dev/null +++ b/src/components/sidebar/header.tsx @@ -0,0 +1,40 @@ +import { Box, Subtext } from "@components/ui"; +import { styled } from "styled-components"; + +interface IHeader { + title?: string; + logo?: string; +} + +const StyledLogoLink = styled.a` + display: flex; + align-items: center; + column-gap: 8px; + text-decoration-line: none; + + & > img { + height: 32px; + } + + & > span { + align-self: center; + font-size: 24px; + line-height: 32px; + font-weight: 600; + white-space: nowrap; + } +`; + +export function Header(props: IHeader): JSX.Element { + return ( + + + logo + {props?.title} + + + ); +} diff --git a/src/components/sidebar/index.ts b/src/components/sidebar/index.ts new file mode 100644 index 00000000..8ed01839 --- /dev/null +++ b/src/components/sidebar/index.ts @@ -0,0 +1 @@ +export { SIDEBAR_KEYS, SIDEBAR, Sidebar } from "./sidebar"; diff --git a/src/components/sidebar/sidebar.tsx b/src/components/sidebar/sidebar.tsx new file mode 100644 index 00000000..cbdfb2ee --- /dev/null +++ b/src/components/sidebar/sidebar.tsx @@ -0,0 +1,110 @@ +import { useIntl, FormattedMessage } from "react-intl"; +import { Flex, Subtext } from "@components/ui"; +import IdentifierIcon from "@components/shared/icons/identifier"; +import CredentialIcon from "@components/shared/icons/credential"; +import SigninIcon from "@components/shared/icons/signin"; +import LockIcon from "@components/shared/icons/lock"; +import { Header } from "./header"; +import { + StyledSidebar, + StyledMenu, + StyledBottomMenu, + StyledHeaderContainer, + StyledLiContainer, +} from "./styled"; + +export const SIDEBAR_KEYS = { + identifiers: "identifiers", + credentials: "credentials", + signin: "sign-ins", +}; + +export const SIDEBAR = [ + { + id: SIDEBAR_KEYS.identifiers, + icon: , + title: , + }, + { + id: SIDEBAR_KEYS.credentials, + icon: , + title: , + }, + { + id: SIDEBAR_KEYS.signin, + icon: , + title: , + }, +]; + +interface ISidebar { + active: any; + onClickLink: (active: any) => void; + disabled?: boolean; + onSignout: () => void; + title?: string; + logo?: string; +} + +export function Sidebar(props: ISidebar): JSX.Element { + const { formatMessage } = useIntl(); + return ( + + + + +
+ + + + +
    + {SIDEBAR.map((element, index) => ( + + !props.disabled && props.onClickLink(element)} + alignItems="center" + padding={2} + borderRadius="8px" + $isActive={element.id === props.active?.id} + $flexGap={3} + > + {element.icon} + + {element.title} + + + + ))} +
+
+ +
    + + + + + {formatMessage({ id: "action.disconnect" })} + + + +
+
+ + ); +} diff --git a/src/components/sidebar/styled.tsx b/src/components/sidebar/styled.tsx new file mode 100644 index 00000000..d616b35f --- /dev/null +++ b/src/components/sidebar/styled.tsx @@ -0,0 +1,46 @@ +import { styled } from "styled-components"; +import { Flex } from "@components/ui"; + +interface IStyledMenu { + $isActive?: boolean; +} + +export const StyledMenu = styled(Flex)` + background-color: ${({ $isActive, theme }) => + $isActive ? theme?.colors?.secondary : ""}; + color: ${({ $isActive, theme }) => ($isActive ? theme?.colors?.subtext : "")}; + &:hover { + background-color: ${({ theme }) => theme?.colors?.secondary}; + color: ${({ theme }) => theme?.colors?.subtext}; + } +`; + +export const StyledSidebar = styled.aside` + position: fixed; + left: 0px; + z-index: 40; + width: 192px; + height: 100%; + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + transform: translate(-100%, 0) rotate(0) skewX(0) skewY(0) scaleX(1) scaleY(1); + @media (min-width: 640px) { + transform: translate(0, 0) rotate(0) skewX(0) skewY(0) scaleX(1) scaleY(1); + } +`; + +export const StyledBottomMenu = styled(Flex)` + &:hover { + background-color: ${({ theme }) => theme?.colors?.error}; + color: ${({ theme }) => theme?.colors?.subtext}; + } +`; + +export const StyledHeaderContainer = styled.ul` + margin: 0; +`; + +export const StyledLiContainer = styled.li<{ disabled?: boolean }>` + cursor: ${({ disabled }) => (disabled ? "not-allowed" : "pointer")}; +`; diff --git a/src/components/signinCard.tsx b/src/components/signinCard.tsx index 9799a81f..dcb143aa 100644 --- a/src/components/signinCard.tsx +++ b/src/components/signinCard.tsx @@ -1,5 +1,5 @@ import { useIntl } from "react-intl"; -import { Card, Button, Text, Switch } from "@components/ui"; +import { Card, Button, Text, Switch, Flex } from "@components/ui"; import SigninIcon from "@components/shared/icons/signin"; import AutoSigninIcon from "@components/shared/icons/auto-signin"; import { ISignin } from "@config/types"; @@ -19,41 +19,47 @@ export function SigninCard({ return ( <> -
+
- + {formatMessage({ id: "signin.website" })} - - {signin?.domain} - + {signin?.domain}
-
+ -
+
- + {signin?.identifier ? formatMessage({ id: "signin.identifierAlias" }) : formatMessage({ id: "credential.title" })} - - {signin?.identifier?.name} - + {signin?.identifier?.name}
- + {formatMessage({ id: "signin.lastUsed.label" })} - + {new Date(signin?.updatedAt).toDateString()}
-
-
+ +
- + {formatMessage({ id: "signin.autoSignin" })} } />
-
- -
-
+ +
); diff --git a/src/components/signinList.tsx b/src/components/signinList.tsx index e12c2a42..5cf8005a 100644 --- a/src/components/signinList.tsx +++ b/src/components/signinList.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; import { SigninCard } from "@components/signinCard"; -import { Loader } from "@components/ui"; +import { Loader, Flex, Box, Text } from "@components/ui"; import { IMessage, ISignin } from "@config/types"; interface IResourceSignin { @@ -90,21 +90,23 @@ export function SigninList(): JSX.Element { return ( <> {isLoading ? ( -
+ -
+ ) : null} {signins.map((signin, index) => ( -
+ deleteSignin(index)} handleAutoSignin={() => updateAutoSignin(index, signin)} /> -
+ ))} {!isLoading && !signins?.length ? ( -

{formatMessage({ id: "message.noItems" })}

+ + {formatMessage({ id: "message.noItems" })} + ) : ( <> )} diff --git a/src/components/ui/animations/bounce.tsx b/src/components/ui/animations/bounce.tsx new file mode 100644 index 00000000..b2bc878a --- /dev/null +++ b/src/components/ui/animations/bounce.tsx @@ -0,0 +1,16 @@ +import styled, { keyframes } from "styled-components"; + +const bounce = keyframes` + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8,0,1,1); + } + 50% { + transform: none; + animation-timing-function: cubic-bezier(0,0,0.2,1); + } +`; + +export const BounceAnimationSvg = styled.svg` + animation: ${bounce} 1s infinite; +`; diff --git a/src/components/ui/animations/index.ts b/src/components/ui/animations/index.ts new file mode 100644 index 00000000..ad55dbf9 --- /dev/null +++ b/src/components/ui/animations/index.ts @@ -0,0 +1,2 @@ +export { SpinAnimationSvg } from "./spin"; +export { BounceAnimationSvg } from "./bounce"; diff --git a/src/components/ui/animations/spin.tsx b/src/components/ui/animations/spin.tsx new file mode 100644 index 00000000..ffa4e1fe --- /dev/null +++ b/src/components/ui/animations/spin.tsx @@ -0,0 +1,11 @@ +import styled, { keyframes } from "styled-components"; + +const spin = keyframes` + to { + transform: rotate(360deg); + } +`; + +export const SpinAnimationSvg = styled.svg` + animation: ${spin} 1s linear infinite; +`; diff --git a/src/components/ui/box/box.tsx b/src/components/ui/box/box.tsx index 8cd676bf..103859f2 100644 --- a/src/components/ui/box/box.tsx +++ b/src/components/ui/box/box.tsx @@ -1,20 +1,76 @@ -import styled from "styled-components"; +import styled, { css } from "styled-components"; import { space, layout, typography, + opacity, + OpacityProps, color, + position, + PositionProps, + border, + BorderProps, SpaceProps, TypographyProps, + LayoutProps, } from "styled-system"; -type TBox = SpaceProps & TypographyProps; +interface IBoxCustomProps { + $breakWord?: boolean; + $hoverableOpacity?: boolean; + $float?: string; + $cursorPointer?: boolean; +} + +type TBox = IBoxCustomProps & + SpaceProps & + TypographyProps & + LayoutProps & + BorderProps & + PositionProps & + OpacityProps; + +export const MainBox = styled.main` + ${space} + ${layout} + ${typography} + ${color} + ${border} +`; + +MainBox.displayName = "MainBox"; export const Box = styled.div` ${space} ${layout} ${typography} ${color} + ${border} + ${position} + ${opacity} + ${({ $breakWord }) => + $breakWord && + css` + overflow-wrap: break-word; + `} + ${({ $hoverableOpacity }) => + $hoverableOpacity && + css` + opacity: 0.8; + &:hover { + opacity: 1; + } + `} + ${({ $float }) => + $float && + css` + float: ${$float === "right" ? "right" : "left"}; + `} + ${({ $cursorPointer }) => + $cursorPointer && + css` + cursor: pointer; + `} `; Box.displayName = "Box"; diff --git a/src/components/ui/box/index.ts b/src/components/ui/box/index.ts index 4e5c5d94..a1148f7e 100644 --- a/src/components/ui/box/index.ts +++ b/src/components/ui/box/index.ts @@ -1 +1 @@ -export { Box } from "./box"; +export { Box, MainBox } from "./box"; diff --git a/src/components/ui/button/button.tsx b/src/components/ui/button/button.tsx index 4344d4c7..13f755ec 100644 --- a/src/components/ui/button/button.tsx +++ b/src/components/ui/button/button.tsx @@ -1,26 +1,98 @@ -import { styled } from "styled-components"; -import { Loader } from "@components/ui"; +import { styled, css } from "styled-components"; +import { buttonStyle, ButtonStyleProps } from "styled-system"; +import { Loader } from "../loader"; interface IButton { type?: "button" | "reset" | "submit" | undefined; handleClick?: () => void; isLoading?: boolean; - className?: string; children?: JSX.Element | any; } +type TNewButtonCustomProps = { + $cursorPointer?: boolean; + $underline?: boolean; + $hoverUnderline?: boolean; +}; + const StyledButton = styled.button` + border: none; + cursor: pointer; background-color: ${(props) => props.theme?.colors?.primary}; text-align: center; + font-weight: 500; + border-radius: 9999px; + color: white; + display: flex; + flex-direction: row; + justify-content: center; + font-size: 14px; + line-height: 20px; + padding-left: 12px; + padding-right: 12px; + padding-top: 2px; + padding-bottom: 2px; +`; + +const CustomButton = styled.button` + ${buttonStyle} + height: fit-content; + background: none; + color: inherit; + border: none; + padding: 0; + font: inherit; + cursor: pointer; + outline: inherit; + ${({ $underline }) => + $underline && + css` + text-decoration-line: underline; + `} + ${({ $hoverUnderline }) => + $hoverUnderline && + css` + &:hover { + text-decoration-line: underline; + } + `} + ${({ $cursorPointer }) => + $cursorPointer && + css` + cursor: pointer; + `} `; +export const IconButton = styled.button` + ${buttonStyle} + height: fit-content; + background: none; + color: inherit; + border: none; + padding: 0; + font: inherit; + cursor: pointer; + outline: inherit; +`; + +const determineElementType = (as: string) => { + switch (as) { + case "button": + return "button"; + case "a": + return "a"; + default: + return "div"; // Default to a div if "as" prop is not recognized + } +}; + +export const NewButton = styled(CustomButton).attrs((props: any) => ({ + as: determineElementType(props.as || "button"), +}))``; + export function Button(props: IButton): JSX.Element { return ( - + {props.isLoading ? : null} {props.children} diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts index 01b1780a..5f8ca95b 100644 --- a/src/components/ui/button/index.ts +++ b/src/components/ui/button/index.ts @@ -1 +1 @@ -export { Button } from "./button"; \ No newline at end of file +export { Button, NewButton, IconButton } from "./button"; \ No newline at end of file diff --git a/src/components/ui/card/card.tsx b/src/components/ui/card/card.tsx index fd8eeffc..a65db954 100644 --- a/src/components/ui/card/card.tsx +++ b/src/components/ui/card/card.tsx @@ -1,17 +1,25 @@ import { styled } from "styled-components"; +import { Box } from "../box"; interface ICard { children?: JSX.Element; } -const StyledCard = styled.div` +const StyledCard = styled(Box)` + border: 1px solid; background-color: ${(props) => props.theme?.colors?.cardBg}; color: ${(props) => props.theme?.colors?.cardColor}; `; export function Card({ children }: ICard): JSX.Element { return ( - + {children} ); diff --git a/src/components/ui/drawer/drawer.tsx b/src/components/ui/drawer/drawer.tsx index c7ba227b..e1a7e0c0 100644 --- a/src/components/ui/drawer/drawer.tsx +++ b/src/components/ui/drawer/drawer.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { styled } from "styled-components"; +import { styled, css } from "styled-components"; +import { Text } from "../typography"; interface IDrawer { header: any; @@ -8,51 +8,102 @@ interface IDrawer { children?: JSX.Element; } -const StyledDrawer = styled.div` +const StyledDrawer = styled.div>` position: fixed; overflow: hidden; z-index: 50; + inset: 0px; + background-color: #1f1f205c; + transform: translate(0, 0) rotate(0) skewX(0) skewY(0) scaleX(1) scaleY(1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + ${({ isOpen }) => + isOpen + ? css` + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + opacity: 1; + transform: translate(0, 0) rotate(0) skewX(0) skewY(0) scaleX(1) + scaleY(1); + ` + : css` + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + transition-delay: 150ms; + opacity: 0; + transform: translate(100%, 0) rotate(0) skewX(0) skewY(0) scaleX(1) + scaleY(1); + `}} `; -const StyledDrawerSection = styled.section` +const StyledDrawerSection = styled.section>` border-top-width: 1px; border-left-width: 1px; border-bottom-width: 1px; border-bottom-left-radius: 1rem; border-top-left-radius: 1rem; + border-top-color: white; + border-bottom-color: white; + border-left-color: white; + box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), + 0 8px 10px -6px rgb(0 0 0 / 0.1); + transition-duration: 500ms; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + transform: translate(0, 0) rotate(0) skewX(0) skewY(0) scaleX(1) scaleY(1); width: 100vw; max-width: 320px; position: absolute; right: 0px; height: 100%; background-color: ${(props) => props.theme?.colors?.secondary}; + ${({ isOpen }) => + isOpen + ? css` + --sc-translate-x: 0px; + transform: translate(var(--sc-translate-x), 0) rotate(0) skewX(0) + skewY(0) scaleX(1) scaleY(1); + ` + : css` + --sc-translate-x: 100%; + transform: translate(var(--sc-translate-x), 0) rotate(0) skewX(0) + skewY(0) scaleX(1) scaleY(1); + `}} +`; + +const StyledDrawerArticle = styled.article` + position: relative; + width: 100vw; + max-width: 320px; + padding-bottom: 40px; + padding: 8px; + display: flex; + flex-direction: column; + overflow-y: scroll; + height: 100%; +`; + +const StyledDrawerBackdrop = styled.section` + width: 100vw; + height: 100%; + cursor: pointer; `; export function Drawer({ children, isOpen, handleClose, header }: IDrawer) { return ( - - -
-
{header}
+ + + + + {header} + {children} -
+
-
+
); } diff --git a/src/components/ui/dropdown/dropdown.tsx b/src/components/ui/dropdown/dropdown.tsx index e52e758e..e68574bb 100644 --- a/src/components/ui/dropdown/dropdown.tsx +++ b/src/components/ui/dropdown/dropdown.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; import styled from "styled-components"; +import { Text } from "../typography"; interface IDropdownOption { label: string; @@ -7,6 +8,7 @@ interface IDropdownOption { } interface IDropdown { + label?: string; options: IDropdownOption[]; selectedOption?: IDropdownOption; onSelect: (option: IDropdownOption) => void; @@ -55,7 +57,12 @@ const DropdownItem = styled.li` } `; +const DropdownLabel = styled(Text)` + padding-bottom: 4px; +`; + export const Dropdown = ({ + label, selectedOption, options, onSelect, @@ -73,22 +80,31 @@ export const Dropdown = ({ }; return ( - - - {selectedOption?.label} - - {isOpen && ( - - {options.map((option) => ( - handleOptionClick(option)} - > - {option?.label} - - ))} - + <> + {label ? ( + + {label} + + ) : ( + <> )} - + + + {selectedOption?.label} + + {isOpen && ( + + {options.map((option) => ( + handleOptionClick(option)} + > + {option?.label} + + ))} + + )} + + ); }; diff --git a/src/components/ui/flex/flex.tsx b/src/components/ui/flex/flex.tsx index 0d16e666..0e7c8742 100644 --- a/src/components/ui/flex/flex.tsx +++ b/src/components/ui/flex/flex.tsx @@ -1,4 +1,4 @@ -import styled from "styled-components"; +import styled, { css } from "styled-components"; import { alignSelf, alignItems, @@ -7,14 +7,32 @@ import { flex, FlexDirectionProps, JustifyContentProps, + AlignItemsProps, } from "styled-system"; import { Box } from "../box"; -type TFlex = FlexDirectionProps & JustifyContentProps; +type TFlexCustomProps = { + $flexGap?: number; +}; + +type TFlex = TFlexCustomProps & + FlexDirectionProps & + JustifyContentProps & + AlignItemsProps; export const Flex = styled(Box)` display: flex; ${alignSelf} ${alignItems} ${justifyContent} ${flexDirection} ${flex}; + ${({ $flexGap, flexDirection }) => + $flexGap + ? flexDirection === "column" + ? css` + row-gap: ${$flexGap * 4}px; + ` + : css` + column-gap: ${$flexGap * 4}px; + ` + : null} `; Flex.displayName = "Flex"; diff --git a/src/components/ui/grid/grid.tsx b/src/components/ui/grid/grid.tsx new file mode 100644 index 00000000..0dcf8df9 --- /dev/null +++ b/src/components/ui/grid/grid.tsx @@ -0,0 +1,18 @@ +import styled, { css } from "styled-components"; +import { + grid, + gridTemplateAreas, + GridProps, + GridTemplateAreasProps, +} from "styled-system"; +import { Box } from "../box"; + +type TGrid = GridProps & GridTemplateAreasProps; + +export const Grid = styled(Box)` + display: grid; + grid-template-columns: repeat(1, minmax(0, 1fr)); + gap: 8px; +`; + +Grid.displayName = "Grid"; diff --git a/src/components/ui/grid/index.ts b/src/components/ui/grid/index.ts new file mode 100644 index 00000000..5a46044d --- /dev/null +++ b/src/components/ui/grid/index.ts @@ -0,0 +1 @@ +export { Grid } from "./grid"; diff --git a/src/components/ui/index.ts b/src/components/ui/index.ts index 04a2beee..b9f43faa 100644 --- a/src/components/ui/index.ts +++ b/src/components/ui/index.ts @@ -9,3 +9,5 @@ export * from "./loader"; export * from "./input"; export * from "./box"; export * from "./flex"; +export * from "./animations"; +export * from "./grid"; diff --git a/src/components/ui/input/input.tsx b/src/components/ui/input/input.tsx index a335f778..2337b41f 100644 --- a/src/components/ui/input/input.tsx +++ b/src/components/ui/input/input.tsx @@ -1,5 +1,6 @@ import React, { isValidElement } from "react"; import styled from "styled-components"; +import { Flex } from "../flex"; interface IInput { label?: string; @@ -13,9 +14,22 @@ interface IInput { type?: string; } +const StyledInputLabel = styled.label` + font-size: 14px; + line-height: 20px; + font-weight: 700; +`; + const StyledInput = styled.input>` + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -o-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; border-radius: 4px; display: block; + font-size: 14px; + line-height: 20px; width: 100%; padding: 8px; border: ${({ theme, error }) => @@ -28,6 +42,7 @@ const StyledInput = styled.input>` const StyledInputError = styled.p` color: ${({ theme }) => theme?.colors?.error}; font-size: 12px; + margin: 0; `; export const Input = ({ @@ -42,18 +57,15 @@ export const Input = ({ type = "text", }: IInput) => { return ( -
+ {label ? ( - + {label} ) : ( <> )} {error} ) ) : null} -
+ ); }; diff --git a/src/components/ui/loader/loader.tsx b/src/components/ui/loader/loader.tsx index 8575730d..157ab4cd 100644 --- a/src/components/ui/loader/loader.tsx +++ b/src/components/ui/loader/loader.tsx @@ -6,5 +6,5 @@ interface ILoader { } export const Loader = ({ color = "currentColor", size = 3 }: ILoader) => { - return ; + return ; }; diff --git a/src/components/ui/radio/radio.tsx b/src/components/ui/radio/radio.tsx index 704f2a3e..7c842e9f 100644 --- a/src/components/ui/radio/radio.tsx +++ b/src/components/ui/radio/radio.tsx @@ -1,3 +1,6 @@ +import { styled } from "styled-components"; +import { Flex } from "../flex"; + interface IRadio { id?: string; component?: JSX.Element; @@ -5,6 +8,19 @@ interface IRadio { onClick: () => void; } +const StyledRadio = styled.input` + width: 16px; + height: 16px; + accent-color: #61783e; +`; + +const StyledRadioLabel = styled.label` + cursor: pointer; + width: 100%; + margin-inline-start: 4px; + font-weight: 500; +`; + export function Radio({ id, component, @@ -12,23 +28,22 @@ export function Radio({ onClick, }: IRadio): JSX.Element { return ( -
- - -
+ {component} + ); } diff --git a/src/components/ui/switch/switch.tsx b/src/components/ui/switch/switch.tsx index 03390865..86028e2a 100644 --- a/src/components/ui/switch/switch.tsx +++ b/src/components/ui/switch/switch.tsx @@ -1,4 +1,4 @@ -import { styled } from "styled-components"; +import { styled, css } from "styled-components"; interface ISwitch { isChecked: boolean; @@ -7,10 +7,24 @@ interface ISwitch { } const StyledSwitch = styled.button>` + cursor: pointer; background-color: ${(props) => props.theme?.colors?.bodyBg}; border-color: ${(props) => props.theme?.colors?.primary}; border-width: 1px; opacity: ${({ isChecked }) => (isChecked ? 1 : 0.6)}; + width: 48px; + height: 24px; + border-radius: 9999px; + display: flex; + align-items: center; + outline: 2px solid transparent; + outline-offset: 2px; + transition-property: color, background-color, border-color, + text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + transition-duration: 300ms; `; const StyledSwitchDiv = styled.div>` @@ -20,6 +34,31 @@ const StyledSwitchDiv = styled.div>` isChecked ? "unset" : `1px solid ${theme?.colors?.primary}`}; color: ${({ isChecked, theme }) => isChecked ? theme?.colors?.bodyBg : theme?.colors?.bodyColor}; + width: 16px; + height: 16px; + position: relative; + border-radius: 9999px; + transition-property: color, background-color, border-color, + text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + transition-duration: 500ms; + padding: 4px; + transform: translate(0, 0) rotate(0) skewX(0) skewY(0) scaleX(1) scaleY(1); + + ${({ isChecked }) => + isChecked + ? css` + --sc-translate-x: 100%; + transform: translate(var(--sc-translate-x), 0) rotate(0) skewX(0) + skewY(0) scaleX(1) scaleY(1); + ` + : css` + --sc-translate-x: -8px; + transform: translate(var(--sc-translate-x), 0) rotate(0) skewX(0) + skewY(0) scaleX(1) scaleY(1); + `}} `; export function Switch({ @@ -28,18 +67,8 @@ export function Switch({ icon, }: ISwitch): JSX.Element { return ( - - + + {icon} diff --git a/src/components/ui/typography/typography.tsx b/src/components/ui/typography/typography.tsx index cb40f7e8..396bd054 100644 --- a/src/components/ui/typography/typography.tsx +++ b/src/components/ui/typography/typography.tsx @@ -1,36 +1,55 @@ -import React from "react"; -import { styled } from "styled-components"; +import { styled, css } from "styled-components"; +import { + typography, + TypographyProps, + maxWidth, + MaxWidthProps, +} from "styled-system"; interface ITypography { children: JSX.Element | any; - className?: string; $color: string; + $capitalize?: boolean; + $breakWord?: boolean; + $cursorPointer?: boolean; } -interface IStyledTypography { - $color: string; -} +type TText = TypographyProps & ITypography & MaxWidthProps; -const StyledTypography = styled.p` +export const Text = styled.p` + margin: 0; + ${typography} color: ${({ $color, theme }) => theme?.colors?.[$color]}; + ${({ $capitalize }) => + $capitalize && + css` + text-transform: capitalize; + `} + ${({ $breakWord }) => + $breakWord && + css` + overflow-wrap: break-word; + `} + ${({ $cursorPointer }) => + $cursorPointer && + css` + cursor: pointer; + `} `; -const StyledSubtext = styled.span` +export const Subtext = styled.span` + ${typography} + ${maxWidth} + margin: 0; color: ${({ $color, theme }) => theme?.colors?.[$color]}; + ${({ $breakWord }) => + $breakWord && + css` + overflow-wrap: break-word; + `} + ${({ $cursorPointer }) => + $cursorPointer && + css` + cursor: pointer; + `} `; - -export function Text(props: ITypography): JSX.Element { - return ( - - {props.children} - - ); -} - -export function Subtext(props: ITypography): JSX.Element { - return ( - - {props.children} - - ); -} diff --git a/src/pages/content/index.tsx b/src/pages/content/index.tsx index f939d345..74ce136a 100644 --- a/src/pages/content/index.tsx +++ b/src/pages/content/index.tsx @@ -3,7 +3,7 @@ import { LocaleProvider } from "@src/_locales"; import { IMessage } from "@config/types"; import { TAB_STATE } from "@pages/popup/constants"; import { Dialog } from "../dialog/Dialog"; -import "./style.css"; +// import "./style.css"; var tabState = TAB_STATE.NONE; diff --git a/src/pages/content/style.css b/src/pages/content/style.css deleted file mode 100644 index 954c6f5f..00000000 --- a/src/pages/content/style.css +++ /dev/null @@ -1,6 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; -.langin{ - color: aliceblue; -} \ No newline at end of file diff --git a/src/pages/dialog/Dialog.tsx b/src/pages/dialog/Dialog.tsx index c295c5e8..3d046ae8 100644 --- a/src/pages/dialog/Dialog.tsx +++ b/src/pages/dialog/Dialog.tsx @@ -1,14 +1,15 @@ import { useState, useEffect } from "react"; import { ThemeProvider, styled } from "styled-components"; import { useIntl } from "react-intl"; -import { Text, Subtext } from "@components/ui"; +import { Text, Subtext, Box, Flex, IconButton } from "@components/ui"; +import CloseIcon from "@components/shared/icons/close"; import { IVendorData, ISignin } from "@config/types"; import { TAB_STATE } from "@pages/popup/constants"; import { setTabState } from "@pages/content"; import { PopupPrompt } from "./popupPrompt"; import { SigninItem } from "./signin"; -const StyledMain = styled.div` +const StyledMain = styled(Box)` border: ${(props) => `1px solid ${ props.theme?.colors?.bodyBorder ?? props.theme?.colors?.bodyBg @@ -17,6 +18,34 @@ const StyledMain = styled.div` color: ${(props) => props.theme?.colors?.bodyColor}; `; +const StyledClose = styled(IconButton)` + position: absolute; + top: 24px; + left: 0px; + font-size: 12px; + padding: 4px 8px; + text-align: center; + border-radius: 50%; + background: ${(props) => props.theme?.colors?.bodyBg}; + color: ${(props) => props.theme?.colors?.bodyColor}; + &:hover { + background-color: #f55877; + color: white; + } + border: ${(props) => + `1px solid ${ + props.theme?.colors?.bodyBorder ?? props.theme?.colors?.bodyBg + }`}; +`; + +const StyledImgSpan = styled.span` + display: inline-block; +`; + +const StyledImg = styled.img` + height: ${({ height }) => height}; +`; + interface IDialog { isConnected: boolean; tabUrl: string; @@ -77,69 +106,72 @@ export function Dialog({ return ( {" "} -
+ {showPopupPrompt ? ( + {formatMessage({ id: "action.open" })}{" "} - - logo - {" "} + + + {" "} {formatMessage({ id: "action.toProceed" })} } /> ) : null} - - -
- logo - + + x + + + + + {formatMessage({ id: "signin.with" })} {vendorData?.title} -
+ {showRequestAuthPrompt ? ( - - - {tabUrl} - {" "} - {formatMessage({ id: "signin.requestAuth" })}{" "} - {formatMessage({ id: getTextKeyByEventType() })} - + + + {tabUrl}{" "} + {formatMessage({ id: "signin.requestAuth" })}{" "} + {formatMessage({ id: getTextKeyByEventType() })} + + ) : ( <> {signins?.map((signin) => ( ))} {eventType !== TAB_STATE.NONE ? ( -
{formatMessage({ id: "action.click" })}{" "} - - logo - {" "} + + + {" "} {formatMessage({ id: "action.toSelectOther" })}{" "} {formatMessage({ id: getTextKeyByEventType() })} -
+
) : ( <> )} )} -
+
); } diff --git a/src/pages/dialog/index.css b/src/pages/dialog/index.css index 35f1727a..6aa8c2bf 100644 --- a/src/pages/dialog/index.css +++ b/src/pages/dialog/index.css @@ -1,13 +1,12 @@ body { - width: 300px; - height: 260px; - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - position: relative; - } - \ No newline at end of file + width: 300px; + height: 260px; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + position: relative; +} diff --git a/src/pages/dialog/index.tsx b/src/pages/dialog/index.tsx index a68bdeda..3fdb2fa1 100644 --- a/src/pages/dialog/index.tsx +++ b/src/pages/dialog/index.tsx @@ -1,6 +1,5 @@ import { createRoot } from "react-dom/client"; import "@pages/popup/index.css"; -import "@assets/styles/tailwind.css"; import Popup from "@pages/popup/Popup"; function init() { diff --git a/src/pages/dialog/popupPrompt.tsx b/src/pages/dialog/popupPrompt.tsx index ef391a52..7799c746 100644 --- a/src/pages/dialog/popupPrompt.tsx +++ b/src/pages/dialog/popupPrompt.tsx @@ -1,23 +1,34 @@ import { styled } from "styled-components"; +import { Flex, Box } from "@components/ui"; import PopupArrowIcon from "@src/components/shared/icons/popup-arrow"; interface IPopupPrompt { message: JSX.Element; } -const StyledContainer = styled.div` +const StyledContainer = styled(Flex)` + border: solid; background-color: ${({ theme }) => theme?.colors?.secondary}; color: ${({ theme }) => theme?.colors?.subtext}; `; export const PopupPrompt = ({ message }: IPopupPrompt): JSX.Element => { return ( - + {message} - + + + ); }; diff --git a/src/pages/dialog/signin.tsx b/src/pages/dialog/signin.tsx index 678edff2..88f557a0 100644 --- a/src/pages/dialog/signin.tsx +++ b/src/pages/dialog/signin.tsx @@ -1,14 +1,19 @@ import { styled } from "styled-components"; -import { Button, Text, Subtext } from "@components/ui"; +import { Box, Button, Text, Subtext, Flex } from "@components/ui"; import SigninIcon from "@src/components/shared/icons/signin"; import { resetTabState } from "@pages/content"; import { ISignin } from "@config/types"; -const StyledSigninItem = styled.div` +const StyledSigninItem = styled(Flex)` + border: 1px solid; background-color: ${(props) => props.theme?.colors?.cardBg}; color: ${(props) => props.theme?.colors?.cardColor}; `; +const AutoSigninTag = styled(Box)<{ visible?: boolean }>` + visibility: ${({ visible }) => (visible ? "visible" : "hidden")}; +`; + // TODO do not pass the full signins stored object (only AID name, schema name, web url) export const SigninItem = ({ signin }: { signin: ISignin }): JSX.Element => { const handleClick = async () => { @@ -25,18 +30,26 @@ export const SigninItem = ({ signin }: { signin: ISignin }): JSX.Element => { }; return ( - -
- + + + URL:{" "} - + {signin.domain} {signin?.identifier ? ( - + AID: {" "} - + {signin?.identifier?.name} @@ -44,36 +57,40 @@ export const SigninItem = ({ signin }: { signin: ISignin }): JSX.Element => { <> )} {signin?.credential ? ( - + Cred: {" "} - + {signin?.credential?.schema?.title} ) : ( <> )} - + Last used:{" "} - + {new Date(signin.updatedAt).toDateString()} -
-
-
-

Auto Sign in

-
+ + + + + Auto Sign in + + -
-
- -
+
); }; diff --git a/src/pages/popup/Popup.tsx b/src/pages/popup/Popup.tsx index fc875b98..024e6562 100644 --- a/src/pages/popup/Popup.tsx +++ b/src/pages/popup/Popup.tsx @@ -12,7 +12,7 @@ import { IVendorData, IMessage } from "@config/types"; import { Permission } from "@src/screens/permission"; import { Signin } from "@src/screens/signin"; import { Signup } from "@src/screens/signup"; -import { Loader } from "@components/ui"; +import { Loader, Box } from "@components/ui"; import { Main } from "@components/main"; interface IBootAndConnect { @@ -34,9 +34,18 @@ export const GlobalStyles = createGlobalStyle` `1px solid ${theme?.colors?.bodyBorder ?? theme?.colors?.bodyBg}`}; transition: background 0.2s ease-in, color 0.2s ease-in; } + + ul { + list-style-type: none; + padding: 0; + + > li { + margin-bottom: 8px; + } + } `; -const StyledLoader = styled.div` +const StyledLoaderBox = styled(Box)` color: ${(props) => props.theme?.colors?.primary}; `; @@ -191,15 +200,15 @@ export default function Popup(): JSX.Element {
{isCheckingInitialConnection ? ( -
- + + - -
+ + ) : ( <> {permissionData ? ( -
+ -
+ ) : showSignup ? ( -
+ -
+ ) : ( <> {isConnected ? ( @@ -227,7 +236,7 @@ export default function Popup(): JSX.Element { title={vendorData?.title} /> ) : ( -
+ setShowSignup(true)} /> -
+ )} )} diff --git a/src/pages/popup/index.css b/src/pages/popup/index.css index b23cc5c7..be2786ac 100644 --- a/src/pages/popup/index.css +++ b/src/pages/popup/index.css @@ -2,8 +2,8 @@ body { min-height: 386px; height: 100%; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/src/pages/popup/index.tsx b/src/pages/popup/index.tsx index 45ff4f88..6999f55f 100644 --- a/src/pages/popup/index.tsx +++ b/src/pages/popup/index.tsx @@ -1,7 +1,6 @@ import { createRoot } from "react-dom/client"; import Popup from "@pages/popup/Popup"; import "@pages/popup/index.css"; -import "@assets/styles/tailwind.css"; function init() { const rootContainer = document.querySelector("#__root"); @@ -14,8 +13,10 @@ function init() { sender, sendResponse ) { - if ((sender.url?.startsWith('moz-extension://') || sender.url?.startsWith('chrome-extension://')) && - sender.url?.endsWith('/service-worker-loader.js') && + if ( + (sender.url?.startsWith("moz-extension://") || + sender.url?.startsWith("chrome-extension://")) && + sender.url?.endsWith("/service-worker-loader.js") && sender.id === chrome.runtime.id && request.type === "popup" && request.subtype === "isOpened" diff --git a/src/screens/config/config.tsx b/src/screens/config/config.tsx index 43c04efc..cd62d660 100644 --- a/src/screens/config/config.tsx +++ b/src/screens/config/config.tsx @@ -3,7 +3,7 @@ import { useIntl } from "react-intl"; import { configService } from "@pages/background/services/config"; import { useLocale, languageCodeMap } from "@src/_locales"; import { isValidUrl, setActionIcon } from "@pages/background/utils"; -import { Button, Dropdown, Input } from "@components/ui"; +import { Box, Button, Dropdown, Input, Text, Flex } from "@components/ui"; const langMap = Object.entries(languageCodeMap).map((s) => ({ label: s[1], @@ -114,7 +114,7 @@ export function Config(props: any): JSX.Element { return ( <> -
+ setVendorUrl(e.target.value)} onBlur={checkErrorVendorUrl} /> -
- -
-
-
+ + + setAgentUrl(e.target.value)} onBlur={() => handleSetAgentUrl(agentUrl)} /> -
-
-

- {formatMessage({ id: "config.language.label" })} -

+ + s.value === currentLocale)} options={langMap} onSelect={(option) => changeLocale(option.value)} /> -
+ {hasOnboarded ? ( -
- -
+ ) : ( <> )} diff --git a/src/screens/permission/permission.tsx b/src/screens/permission/permission.tsx index a411d3cb..bb94e3f8 100644 --- a/src/screens/permission/permission.tsx +++ b/src/screens/permission/permission.tsx @@ -5,7 +5,7 @@ import { configService, } from "@pages/background/services/config"; import { isValidUrl, setActionIcon } from "@pages/background/utils"; -import { Card, Button, Text } from "@components/ui"; +import { Box, Card, Button, Text, Flex } from "@components/ui"; import { IMessage } from "@config/types"; interface IPermissions { @@ -137,57 +137,46 @@ export function Permission({ }; return ( -
-
-

+ + + {formatMessage({ id: "permissions.label.permissionRequired", })} -

-
+ + {containsAgentUrl ? ( <> -
- + + {formatMessage( { id: "permissions.warning.containsAgentUrl" }, { url: receivedVendorData?.agentUrl } )} -
-
- - - -
+ ) : ( <> - + {formatMessage( { id: "permissions.desc.loadVendorUrl" }, { @@ -198,31 +187,27 @@ export function Permission({ {vendorUrlError ? ( -

{vendorUrlError}

+ {vendorUrlError} ) : null} -
+ - -
+ )}
-
+ ); } diff --git a/src/screens/signin/index.tsx b/src/screens/signin/index.tsx index 307b8ecc..4eda8994 100644 --- a/src/screens/signin/index.tsx +++ b/src/screens/signin/index.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; import { useIntl } from "react-intl"; -import { Text } from "@components/ui"; +import { Box, Text, Flex, NewButton, IconButton, Grid } from "@components/ui"; import SettingIcon from "@src/components/shared/icons/setting"; import { configService } from "@pages/background/services/config"; import { Config } from "@src/screens/config"; @@ -36,17 +36,17 @@ export function Signin(props: ISignin): JSX.Element { }, []); return ( -
-
- + + + {props.showConfig ? formatMessage({ id: "account.settings" }) : props.title} - -
+ + {props.showConfig ? ( { @@ -63,35 +63,34 @@ export function Signin(props: ISignin): JSX.Element { logo={props.logo} /> )} -
+ {hasOnboarded ? ( -
- -
+ +
) : null} - -
-
+ + + + ); } diff --git a/src/screens/signin/signin.tsx b/src/screens/signin/signin.tsx index f9792a3c..7d30ca72 100644 --- a/src/screens/signin/signin.tsx +++ b/src/screens/signin/signin.tsx @@ -1,5 +1,6 @@ import { useState, useEffect } from "react"; -import { Button, Input } from "@components/ui"; +import { styled } from "styled-components"; +import { Button, Box, Flex, Input, Text } from "@components/ui"; import { useIntl } from "react-intl"; interface ISignin { @@ -10,6 +11,11 @@ interface ISignin { logo?: string; } +const StyledLogo = styled.img` + width: 128px; + height: 128px; +`; + export function Signin(props: ISignin): JSX.Element { const { formatMessage } = useIntl(); const [passcode, setPasscode] = useState(""); @@ -45,10 +51,10 @@ export function Signin(props: ISignin): JSX.Element { return ( <> -
- logo -
-
+ + + + setPasscode(e.target.value)} onBlur={onBlurPasscode} /> -
-
- -
+ ); } diff --git a/src/screens/signup/signup.tsx b/src/screens/signup/signup.tsx index 6ce491b5..d50e0052 100644 --- a/src/screens/signup/signup.tsx +++ b/src/screens/signup/signup.tsx @@ -1,7 +1,15 @@ import { useState, useEffect } from "react"; import styled, { css } from "styled-components"; import { useIntl } from "react-intl"; -import { Card, Button, Text, Input } from "@components/ui"; +import { + Box, + Card, + Button, + Flex, + Text, + Input, + IconButton, +} from "@components/ui"; import EyeIcon from "@components/shared/icons/eye"; import EyeOffIcon from "@components/shared/icons/eye-off"; import { IMessage } from "@config/types"; @@ -13,6 +21,7 @@ interface ISignup { } const StyledGeneratedPassword = styled.p<{ blur: boolean }>` + margin: 0; ${({ blur, theme }) => blur && css` @@ -72,9 +81,9 @@ export function Signup({ }; return ( -
-
-

+ + + {generatedPasscode ? formatMessage({ id: "signup.title.saveYourPasscode", @@ -82,35 +91,40 @@ export function Signup({ : formatMessage({ id: "signup.title.generatePasscode", })} -

-
-
-

+ + + + {formatMessage({ id: "signup.desc.safegaurd", })} -

-

+ + {formatMessage({ id: "signup.desc.storeYourPasscode", })} -

-
+ + <> -
- + + {formatMessage({ id: "signup.warning.cannotRetrieve" })} -
+ {generatedPasscode ? ( -
+ {generatedPasscode} - -
+ +
) : ( <> )} -
+ {generatedPasscode ? ( copiedToClipboard ? (
-
+ setPasscode(e.target.value)} onBlur={onBlurPasscode} /> -
+
) : ( @@ -155,28 +170,24 @@ export function Signup({ navigator.clipboard.writeText(generatedPasscode); setCopiedToClipboard(true); }} - className="text-white flex flex-row focus:outline-none font-medium rounded-full text-sm px-3 py-[2px]" > -

+ {formatMessage({ id: "signup.action.copyToClipboard", })} -

+ ) ) : ( - )} -
+
-
+ ); }