diff --git a/frontend/__tests__/components/Button.spec.tsx b/frontend/__tests__/components/Button.spec.tsx
index ba13e6ee0581..e78e9e3eabc9 100644
--- a/frontend/__tests__/components/Button.spec.tsx
+++ b/frontend/__tests__/components/Button.spec.tsx
@@ -1,3 +1,4 @@
+import { faKeyboard } from "@fortawesome/free-solid-svg-icons";
import { render, cleanup } from "@solidjs/testing-library";
import { describe, it, expect, vi, afterEach } from "vitest";
@@ -52,7 +53,7 @@ describe("Button component", () => {
//
}}
fa={{
- icon: "keyboard",
+ icon: faKeyboard,
}}
/>
));
@@ -70,7 +71,7 @@ describe("Button component", () => {
//
}}
fa={{
- icon: "keyboard",
+ icon: faKeyboard,
fixedWidth: true,
}}
/>
@@ -88,7 +89,7 @@ describe("Button component", () => {
}}
fa={{
fixedWidth: true,
- icon: "keyboard",
+ icon: faKeyboard,
}}
text="Hello"
/>
@@ -105,7 +106,7 @@ describe("Button component", () => {
//
}}
fa={{
- icon: "keyboard",
+ icon: faKeyboard,
}}
text="Hello"
/>
diff --git a/frontend/package.json b/frontend/package.json
index bac5f695da18..bd6f507f52b5 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -23,6 +23,10 @@
},
"dependencies": {
"@date-fns/utc": "1.2.0",
+ "@fortawesome/fontawesome-svg-core": "7.1.0",
+ "@fortawesome/free-brands-svg-icons": "5.15.4",
+ "@fortawesome/free-regular-svg-icons": "5.15.4",
+ "@fortawesome/free-solid-svg-icons": "5.15.4",
"@monkeytype/contracts": "workspace:*",
"@monkeytype/funbox": "workspace:*",
"@monkeytype/schemas": "workspace:*",
@@ -60,7 +64,7 @@
},
"devDependencies": {
"@eslint/json": "0.14.0",
- "@fortawesome/fontawesome-free": "5.15.4",
+ "@fortawesome/fontawesome-common-types": "0.2.36",
"@monkeytype/oxlint-config": "workspace:*",
"@monkeytype/typescript-config": "workspace:*",
"@solidjs/testing-library": "0.8.10",
@@ -83,7 +87,6 @@
"eslint-plugin-compat": "6.0.2",
"eslint-plugin-solid": "0.14.5",
"firebase-tools": "13.15.1",
- "fontawesome-subset": "4.4.0",
"happy-dom": "20.0.10",
"jsdom": "27.4.0",
"madge": "8.0.0",
diff --git a/frontend/src/html/pages/test-result.html b/frontend/src/html/pages/test-result.html
index f40f5a3a80f8..88416a6324ed 100644
--- a/frontend/src/html/pages/test-result.html
+++ b/frontend/src/html/pages/test-result.html
@@ -6,6 +6,7 @@
wpm
+
')
+ center / 75% no-repeat;
+ background: transparent;
+ transition: background 0.125s;
}
&:checked:after {
- color: var(--main-color);
+ background: var(--main-color);
}
&:hover:after {
- color: var(--bg-color);
+ background: var(--bg-color);
}
&:hover:checked:after {
- color: var(--text-color);
+ background: var(--text-color);
}
&[disabled] {
opacity: 0.33;
pointer-events: none;
&:hover:after {
- color: var(--sub-alt-color);
+ background: var(--sub-alt-color);
}
&:hover:checked:after {
- color: var(--main-color);
+ background: var(--main-color);
}
}
}
diff --git a/frontend/src/styles/nav.scss b/frontend/src/styles/nav.scss
index 91c58ceb8ceb..5b414b1f5975 100644
--- a/frontend/src/styles/nav.scss
+++ b/frontend/src/styles/nav.scss
@@ -19,7 +19,7 @@ nav {
.text {
font-size: 0.75em;
align-self: center;
- .fas {
+ .fa {
margin-left: 0.33em;
}
}
diff --git a/frontend/src/styles/popups.scss b/frontend/src/styles/popups.scss
index 5418f2f68af1..20d24b8d32b8 100644
--- a/frontend/src/styles/popups.scss
+++ b/frontend/src/styles/popups.scss
@@ -340,7 +340,7 @@ body.darkMode {
display: grid;
gap: 0.5rem;
grid-template-columns: 2fr 3rem;
- .button .fas {
+ .button .fa {
pointer-events: none;
}
}
@@ -365,7 +365,7 @@ body.darkMode {
display: grid;
gap: 0.5rem;
grid-template-columns: 2fr auto auto;
- .button .fas {
+ .button .fa {
pointer-events: none;
}
}
@@ -1299,7 +1299,7 @@ body.darkMode {
.length.red {
color: var(--error-color);
}
- i.fas {
+ .fa {
margin-right: 0.5em;
}
}
@@ -1618,7 +1618,7 @@ body.darkMode {
font-size: 0.75em;
margin-bottom: 1rem;
width: 100%;
- .fas {
+ .fa {
margin-right: 0.25em;
}
}
diff --git a/frontend/src/styles/settings.scss b/frontend/src/styles/settings.scss
index 6aa5b86db954..a7418e16aadb 100644
--- a/frontend/src/styles/settings.scss
+++ b/frontend/src/styles/settings.scss
@@ -34,11 +34,11 @@
margin: -0.25em;
padding: 0.25em;
- .fas {
+ .fa {
transition: transform 0.25s;
}
- &.rotateIcon .fas {
+ &.rotateIcon .fa {
transform: rotate(-90deg);
}
}
@@ -117,7 +117,7 @@
.button {
height: auto;
- .fas {
+ .fa {
margin-right: 0rem;
}
}
@@ -268,7 +268,7 @@
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem;
}
- .fas {
+ .fa {
margin-right: 0rem;
}
}
@@ -287,18 +287,18 @@
font-weight: 300;
display: flex;
align-items: baseline;
- .fab,
- .fas,
- .far,
+ .fa,
+ .fa,
+ .fa,
.textIcon {
margin-right: 0.5em;
}
}
&.themes .groupTitle {
- .fab,
- .fas,
- .far {
+ .fa,
+ .fa,
+ .fa {
margin-bottom: 0;
}
}
@@ -431,8 +431,8 @@
width: 1.25rem;
transition: 0.25s;
opacity: 0;
- .far,
- .fas {
+ .fa,
+ .fa {
margin: 0;
pointer-events: none;
}
@@ -460,8 +460,8 @@
width: 1.25rem;
transition: 0.25s;
opacity: 0;
- .far,
- .fas {
+ .fa,
+ .fa {
margin: 0;
pointer-events: none;
}
@@ -502,7 +502,7 @@
transition: 0.25s;
opacity: 0;
color: inherit;
- .far {
+ .fa {
margin: 0;
}
&.active {
@@ -597,7 +597,7 @@
margin-left: 0.5em;
align-self: center;
opacity: 0;
- .fas {
+ .fa {
margin-right: 0;
}
}
diff --git a/frontend/src/styles/test.scss b/frontend/src/styles/test.scss
index d0064f2c7c24..0f313410b0a3 100644
--- a/frontend/src/styles/test.scss
+++ b/frontend/src/styles/test.scss
@@ -109,7 +109,7 @@
gap: 0 1em;
flex-wrap: wrap;
- .fas {
+ .fa {
margin-left: 0.33em;
}
}
@@ -895,7 +895,7 @@
}
}
- .fas {
+ .fa {
color: var(--color);
line-height: 0;
}
@@ -1078,7 +1078,7 @@
max-width: 30rem;
}
- .tags .bottom .fas {
+ .tags .bottom .fa {
margin-left: 0.5rem;
}
@@ -1175,7 +1175,7 @@
.bottom {
font-size: 1rem;
line-height: 1.25;
- .lbChange .fas {
+ .lbChange .fa {
margin-right: 0.15rem;
}
}
@@ -1469,7 +1469,7 @@
}
}
- .fas {
+ .fa {
margin-right: 0.5rem;
}
}
diff --git a/frontend/src/styles/vendor.scss b/frontend/src/styles/vendor.scss
index 0b716f23a71d..a3ce6dbb3f29 100644
--- a/frontend/src/styles/vendor.scss
+++ b/frontend/src/styles/vendor.scss
@@ -1,25 +1,3 @@
-@import "fontawesome-5"; // the screenshotting library has some issues with css layers
-
-/* fontawesome icon styles do not respect the hidden class from the hidden layer.
-* By having these rules outside any layer we make sure that the display none is
-* correctly applied when an element possesses both a .fa* class and the hidden class */
-.fas.hidden,
-.fab.hidden,
-.fa.hidden,
-.far.hidden {
- display: none;
-}
-
-// same for invisible
-.fas.invisible,
-.fab.invisible,
-.fa.invisible,
-.far.invisible {
- opacity: 0;
- pointer-events: none;
- visibility: hidden;
-}
-
@import "normalize.css" layer(normalize);
@layer vendor {
@import "slim-select/styles";
diff --git a/frontend/src/ts/commandline/commandline.ts b/frontend/src/ts/commandline/commandline.ts
index bce663b31544..f016a63250ed 100644
--- a/frontend/src/ts/commandline/commandline.ts
+++ b/frontend/src/ts/commandline/commandline.ts
@@ -417,7 +417,7 @@ function getCommandIconsHtml(command: Command & { isActive: boolean }): {
}
}
- let configIconHtml = `
`;
+ let configIconHtml = `
`;
if (command.isActive) {
configIconHtml = `
`;
}
diff --git a/frontend/src/ts/components/common/AsyncContent.tsx b/frontend/src/ts/components/common/AsyncContent.tsx
index a36f82caa3fb..e2d4c29189a5 100644
--- a/frontend/src/ts/components/common/AsyncContent.tsx
+++ b/frontend/src/ts/components/common/AsyncContent.tsx
@@ -1,3 +1,4 @@
+import { faCircleNotch } from "@fortawesome/free-solid-svg-icons";
import { ErrorBoundary, JSXElement, Resource, Show, Suspense } from "solid-js";
import * as Notifications from "../../elements/notifications";
@@ -52,7 +53,7 @@ export default function AsyncContent
(
<>
-
+
{p.children(value())}
@@ -66,7 +67,7 @@ export default function AsyncContent(
-
+
}
>
diff --git a/frontend/src/ts/components/common/Fa.module.css b/frontend/src/ts/components/common/Fa.module.css
new file mode 100644
index 000000000000..8b2fc65429b7
--- /dev/null
+++ b/frontend/src/ts/components/common/Fa.module.css
@@ -0,0 +1,12 @@
+.spin {
+ animation: spin 2s 0s infinite linear;
+}
+
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
diff --git a/frontend/src/ts/components/common/Fa.tsx b/frontend/src/ts/components/common/Fa.tsx
index aa994ac26dfd..cd829726130d 100644
--- a/frontend/src/ts/components/common/Fa.tsx
+++ b/frontend/src/ts/components/common/Fa.tsx
@@ -1,28 +1,68 @@
-import { JSXElement } from "solid-js";
+import { IconDefinition } from "@fortawesome/fontawesome-common-types";
+import { createMemo, JSXElement, Show } from "solid-js";
-import { FaObject } from "../../types/font-awesome";
+import style from "./Fa.module.css";
export type FaProps = {
fixedWidth?: boolean;
spin?: boolean;
size?: number;
-} & FaObject;
+ icon: IconDefinition;
+};
export function Fa(props: FaProps): JSXElement {
- const variant = (): string => props.variant ?? "solid";
+ const i = createMemo(() => props.icon?.icon);
+
return (
-
+
+ viewBox={`0 0 ${i()[0]} ${i()[1]}`}
+ aria-hidden="true"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+
+ {/* */}
+
+
+
+ >
+ }
+ >
+
+
+
+
+ //
);
}
diff --git a/frontend/src/ts/components/layout/footer/Footer.tsx b/frontend/src/ts/components/layout/footer/Footer.tsx
index fd6dbe21c6ba..847768108bc7 100644
--- a/frontend/src/ts/components/layout/footer/Footer.tsx
+++ b/frontend/src/ts/components/layout/footer/Footer.tsx
@@ -1,3 +1,12 @@
+import { faDiscord, faTwitter } from "@fortawesome/free-brands-svg-icons";
+import {
+ faCode,
+ faDonate,
+ faEnvelope,
+ faFileContract,
+ faLock,
+ faShieldAlt,
+} from "@fortawesome/free-solid-svg-icons";
import { JSXElement } from "solid-js";
import { getFocus, getIsScreenshotting } from "../../../signals/core";
@@ -17,7 +26,6 @@ export function Footer(): JSXElement {
})}
>
-
showModal("Contact")}
@@ -38,7 +46,7 @@ export function Footer(): JSXElement {
type="text"
text="support"
fa={{
- icon: "donate",
+ icon: faDonate,
fixedWidth: true,
}}
onClick={() => showModal("Support")}
@@ -47,7 +55,7 @@ export function Footer(): JSXElement {
type="text"
text="github"
fa={{
- icon: "code",
+ icon: faCode,
fixedWidth: true,
}}
href="https://github.com/monkeytypegame/monkeytype"
@@ -56,8 +64,7 @@ export function Footer(): JSXElement {
type="text"
text="discord"
fa={{
- icon: "discord",
- variant: "brand",
+ icon: faDiscord,
fixedWidth: true,
}}
href="https://www.discord.gg/monkeytype"
@@ -66,8 +73,7 @@ export function Footer(): JSXElement {
type="text"
text="twitter"
fa={{
- icon: "twitter",
- variant: "brand",
+ icon: faTwitter,
fixedWidth: true,
}}
href="https://x.com/monkeytype"
@@ -76,7 +82,7 @@ export function Footer(): JSXElement {
type="text"
text="terms"
fa={{
- icon: "file-contract",
+ icon: faFileContract,
fixedWidth: true,
}}
href="/terms-of-service.html"
@@ -86,7 +92,7 @@ export function Footer(): JSXElement {
type="text"
text="security"
fa={{
- icon: "shield-alt",
+ icon: faShieldAlt,
fixedWidth: true,
}}
/>
@@ -95,7 +101,7 @@ export function Footer(): JSXElement {
type="text"
text="privacy"
fa={{
- icon: "lock",
+ icon: faLock,
fixedWidth: true,
}}
/>
diff --git a/frontend/src/ts/components/layout/footer/ScrollToTop.tsx b/frontend/src/ts/components/layout/footer/ScrollToTop.tsx
index 7c6238a0bb2f..db67d006ecb2 100644
--- a/frontend/src/ts/components/layout/footer/ScrollToTop.tsx
+++ b/frontend/src/ts/components/layout/footer/ScrollToTop.tsx
@@ -1,3 +1,4 @@
+import { faAngleDoubleUp } from "@fortawesome/free-solid-svg-icons";
import { JSXElement, createSignal, onMount, onCleanup } from "solid-js";
import { getActivePage } from "../../../signals/core";
@@ -43,7 +44,7 @@ export function ScrollToTop(): JSXElement {
});
}}
>
-
+
);
diff --git a/frontend/src/ts/components/layout/footer/ThemeIndicator.tsx b/frontend/src/ts/components/layout/footer/ThemeIndicator.tsx
index ed4d13ff6098..d661098adbb7 100644
--- a/frontend/src/ts/components/layout/footer/ThemeIndicator.tsx
+++ b/frontend/src/ts/components/layout/footer/ThemeIndicator.tsx
@@ -1,3 +1,4 @@
+import { faPalette, faStar } from "@fortawesome/free-solid-svg-icons";
import { JSXElement, Show } from "solid-js";
import * as Commandline from "../../../commandline/commandline";
@@ -43,10 +44,10 @@ export function ThemeIndicator(): JSXElement {
{getThemeIndicator().text}
diff --git a/frontend/src/ts/components/layout/footer/VersionButton.tsx b/frontend/src/ts/components/layout/footer/VersionButton.tsx
index a335878452e0..db013fea6264 100644
--- a/frontend/src/ts/components/layout/footer/VersionButton.tsx
+++ b/frontend/src/ts/components/layout/footer/VersionButton.tsx
@@ -1,3 +1,4 @@
+import { faCodeBranch } from "@fortawesome/free-solid-svg-icons";
import { COMPATIBILITY_CHECK } from "@monkeytype/contracts";
import { JSXElement, Show, createSignal } from "solid-js";
import { envConfig } from "virtual:env-config";
@@ -46,7 +47,7 @@ export function VersionButton(): JSXElement {
return (