Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move CSS reset, font loading and theme switch outside React to prevent flicker #494

Open
wants to merge 11 commits into
base: development
Choose a base branch
from
Open
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{sh,bash}]
end_of_line = lf
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PLASMO_PUBLIC_APP_TYPE=extension
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ keys.json
.tsbuildinfo

# temporary remove development icon
assets/icon.development.png
assets/icon.development.png
Binary file added assets/icon512.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/icon.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/offline/logo128.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/offline/logo256.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/offline/logo64.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/online/logo128.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/online/logo256.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/online/logo64.development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 changes: 122 additions & 0 deletions assets/popup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
@font-face {
font-family: "ManropeLocal";
font-style: normal;
font-weight: 300;
src: url(/assets/fonts/Manrope-Light.woff2) format('woff2');
}

@font-face {
font-family: "ManropeLocal";
font-style: normal;
font-weight: 400;
src: url(/assets/fonts/Manrope-Regular.woff2) format('woff2');
}

@font-face {
font-family: "ManropeLocal";
font-style: normal;
font-weight: 500;
src: url(/assets/fonts/Manrope-Medium.woff2) format('woff2');
}

@font-face {
font-family: "ManropeLocal";
font-style: normal;
font-weight: 600;
src: url(/assets/fonts/Manrope-SemiBold.woff2) format('woff2');
}

@font-face {
font-family: "ManropeLocal";
font-style: normal;
font-weight: 600;
src: url(/assets/fonts/Manrope-Bold.woff2) format('woff2');
}

@font-face {
font-family: "ManropeLocal";
font-style: normal;
font-weight: 700;
src: url(/assets/fonts/Manrope-ExtraBold.woff2) format('woff2');
}

* {
scrollbar-width: none;
}

*::-webkit-scrollbar {
display: none
}

::selection {
background-color: rgba(171, 154, 255, .6);
color: #fff;
}

:root {
--defaultBackgroundColor: white;
}

@media (prefers-color-scheme: dark) {
:root {
--defaultBackgroundColor: black;
}
}

body {
margin: 0;
padding: 0;
}

body#popup {
width: 377px;
height: 600px;
}

body.fullscreen {
width: 377px;
height: 100vh;
margin: 0 auto;
}

body.fullscreen::before {
content: "";
position: fixed;
top: 50%;
left: 50%;
width: 377px;
height: 100vh;
transform: translate(-50%, -50%);
pointer-events: none;
box-shadow: 0 0 128px 0 rgba(171, 154, 255, .4);
}

body,
button,
input,
select,
textarea {
font-family: "ManropeLocal", "Manrope VF", "Manrope", sans-serif !important;
}

button {
background: transparent;
border: 0;
padding: 0;
}

#cover {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 99999999;
background-color: var(--backgroundColor, var(--defaultBackgroundColor, white));
transition: background-color linear 230ms;
}

#cover[aria-hidden] {
background: transparent;
pointer-events: none;
}
3 changes: 3 additions & 0 deletions assets/popup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const backgroundColor = localStorage.getItem("ARCONNECT_THEME_BACKGROUND_COLOR");

if (backgroundColor) document.documentElement.style.setProperty('--backgroundColor', backgroundColor);
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"packageManager": "[email protected]",
"homepage": "https://arconnect.io",
"scripts": {
"dev:chrome": "plasmo dev",
"dev:chrome": "plasmo dev --verbose",
"build:chrome": "plasmo build --no-hoist",
"dev:firefox": "plasmo dev --target=firefox-mv2",
"build:firefox": "plasmo build --target=firefox-mv2 --no-hoist",
"nuke": "rm -rf node_modules build .plasmo",
"fmt": "prettier --write .",
"fmt:check": "prettier --check .",
"prepare": "husky install"
Expand Down Expand Up @@ -69,7 +70,7 @@
"check-password-strength": "^2.0.7",
"copy-to-clipboard": "^3.3.2",
"dayjs": "^1.11.6",
"framer-motion": "7.5.3",
"framer-motion": "^11.11.7",
"human-crypto-keys": "^0.1.4",
"js-confetti": "^0.11.0",
"mitt": "^3.0.0",
Expand Down
12 changes: 10 additions & 2 deletions src/components/SliderMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import styled, { useTheme } from "styled-components";

interface SliderMenuProps {
title: string;
hasNav?: boolean;
isOpen: boolean;
onClose?: () => void;
children?: React.ReactNode;
}

export default function SliderMenu({
title,
hasNav,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Send view, the last option inside the menus was covered by the bottom navigation.

isOpen,
onClose,
children
Expand All @@ -37,6 +39,7 @@ export default function SliderMenu({

<Wrapper
displayTheme={theme.displayTheme}
hasNav={hasNav}
ref={wrapperElementRef}
variants={animationSlideFromBottom}
initial="hidden"
Expand All @@ -61,12 +64,15 @@ const ExitButton = styled(CloseIcon)`
cursor: pointer;
`;

const Wrapper = styled(motion.div)<{ displayTheme: DisplayTheme }>`
const Wrapper = styled(motion.div)<{
displayTheme: DisplayTheme;
hasNav: boolean;
}>`
position: fixed;
bottom: 0;
left: 0;
height: auto;
max-height: 93%;
max-height: calc(100% - 66px);
border-top: ${(props) =>
props.displayTheme === "light"
? `1px solid ${props.theme.primary}`
Expand All @@ -79,6 +85,8 @@ const Wrapper = styled(motion.div)<{ displayTheme: DisplayTheme }>`
background-color: ${(props) =>
props.displayTheme === "light" ? "#ffffff" : "#191919"};
border-radius: 10px 10px 0 0;
padding-bottom: ${(props) => (props.hasNav ? "66px" : "0")};
box-sizing: border-box;
`;

export const animationSlideFromBottom: Variants = {
Expand Down
1 change: 0 additions & 1 deletion src/components/dashboard/Wallets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useStorage } from "@plasmohq/storage/hook";
import { type AnsUser, getAnsProfile } from "~lib/ans";
import { ExtensionStorage } from "~utils/storage";
import { useLocation, useRoute } from "wouter";
import { PlusIcon } from "@iconicicons/react";
import type { StoredWallet } from "~wallets";
import { Reorder } from "framer-motion";
import WalletListItem from "./list/WalletListItem";
Expand Down
103 changes: 73 additions & 30 deletions src/components/hardware/HardwareWalletTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,81 @@
import { type DefaultTheme, ThemeProvider } from "styled-components";
import { type PropsWithChildren, useMemo } from "react";
import { ThemeProvider, type DefaultTheme } from "styled-components";
import { useEffect, type PropsWithChildren } from "react";
import { useHardwareApi } from "~wallets/hooks";
import { useTheme } from "~utils/theme";
import { Provider } from "@arconnect/components";
import { useTheme as useStyledComponentsTheme } from "styled-components";
import { MotionGlobalConfig } from "framer-motion";

export default function HardwareWalletTheme({
children
}: PropsWithChildren<{}>) {
// hardware api type
const ARCONNECT_THEME_BACKGROUND_COLOR = "ARCONNECT_THEME_BACKGROUND_COLOR";

/**
* Modify the theme if the active wallet is a hardware wallet. We transform the
* default accent color to match the hardware wallet's accent.
*/
function hardwareThemeModifier(theme: DefaultTheme): DefaultTheme {
return {
...theme,
theme: "154, 184, 255",
primary: "#9AB8FF",
primaryBtnHover: "#6F93E1"
};
}

function noThemeModifier(theme: DefaultTheme): DefaultTheme {
return theme;
}

export function ArConnectThemeProvider({ children }: PropsWithChildren<{}>) {
const hardwareApi = useHardwareApi();
const theme = useTheme();
const themeModifier = hardwareApi ? hardwareThemeModifier : noThemeModifier;

useEffect(() => {
const reducedMotionPreference = window.matchMedia(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this here. It could eventually be added in settings too, just like the system theme can be overridden.

"(prefers-reduced-motion)"
);

// hardware wallet accent color
const hardwareApiTheme = useMemo<string | false>(() => {
if (!hardwareApi) return false;
if (reducedMotionPreference.matches) {
// This could also be always set to `true` at the top of the file and then set to `false` after the application
// loads if we still notice some flicker due to any animation/transition playing when the view first loads.

MotionGlobalConfig.skipAnimations = true;
}
}, []);

return (
<Provider theme={theme}>
<ThemeProvider theme={themeModifier}>
<ThemeBackgroundObserver />

{children}
</ThemeProvider>
</Provider>
);
}

export function ThemeBackgroundObserver() {
const styledComponentsTheme = useStyledComponentsTheme();
const backgroundColor = styledComponentsTheme.background;

useEffect(() => {
let formattedBackgroundColor = "";

if (backgroundColor.length === 3 || backgroundColor.length === 6) {
formattedBackgroundColor = `#${backgroundColor}`;
} else if (/\d{1,3}, ?\d{1,3}, ?\d{1,3}/.test(backgroundColor)) {
formattedBackgroundColor = `rgb(${backgroundColor})`;
} else if (/\d{1,3}, ?\d{1,3}, ?\d{1,3}, ?.+/.test(backgroundColor)) {
formattedBackgroundColor = `rgba(${backgroundColor})`;
}

if (hardwareApi === "keystone") {
return "154, 184, 255";
if (formattedBackgroundColor) {
localStorage.setItem(
ARCONNECT_THEME_BACKGROUND_COLOR,
formattedBackgroundColor
);
}
}, [backgroundColor]);

return false;
}, [hardwareApi]);

// modify theme if the active wallet is a
// hardware wallet
// we transform the default accent color
// to match the hardware wallet's accent
function themeModifier(theme: DefaultTheme): DefaultTheme {
if (!hardwareApiTheme) return theme;

return {
...theme,
theme: hardwareApiTheme,
primary: "#9AB8FF",
primaryBtnHover: "#6F93E1"
};
}

return <ThemeProvider theme={themeModifier}>{children}</ThemeProvider>;
return null;
}
Loading