Repository: reown-com/appkit (2025-06-20T02:48:30Z)

Issue:
[feature] Remove unnessesary third party import if we use custom fonts.
### What problem does this new feature solve?

https://github.com/reown-com/appkit/blob/2c3c763378cfd57a416e5af97c62f0e062ee9686/packages/ui/src/utils/ThemeUtil.ts#L47

Problem in additional network requests to third parties which not required.

### Describe the solution you'd like

Simply solution:
If we have custom --w3m-font-family variable just not include css font @import to core
Thanks.


Discussion:
<p><a href="https://linear.app/reown/issue/APKT-3028/feature-remove-unnessesary-third-party-import-if-we-use-custom-fonts">APKT-3028 [feature] Remove unnessesary third party import if we use custom fonts.</a></p>
How long we should wait until fix will be merged? 



Patch:
diff --git a/packages/ui-new/src/utils/ThemeUtil.ts b/packages/ui-new/src/utils/ThemeUtil.ts
index 7a0b95ba37..2618b9b86e 100644
--- a/packages/ui-new/src/utils/ThemeUtil.ts
+++ b/packages/ui-new/src/utils/ThemeUtil.ts
@@ -81,36 +81,40 @@ export function setThemeVariables(themeVariables: ThemeVariables) {
   }
 }
 
-function createRootStyles(themeVariables?: ThemeVariables) {
+export function createRootStyles(themeVariables?: ThemeVariables) {
   return {
     core: css`
-      @font-face {
-        font-family: 'KHTeka';
-        src: url(${unsafeCSS(fonts['KHTeka-500'])}) format('woff');
-        font-weight: 500;
-        font-style: normal;
-      }
-
-      @font-face {
-        font-family: 'KHTeka';
-        src: url(${unsafeCSS(fonts['KHTeka-300'])}) format('woff');
-        font-weight: 300;
-        font-style: normal;
-      }
-
-      @font-face {
-        font-family: 'KHTekaMono';
-        src: url(${unsafeCSS(fonts['KHTekaMono-400'])}) format('woff');
-        font-weight: 400;
-        font-style: normal;
-      }
-
-      @font-face {
-        font-family: 'KHTeka';
-        src: url(${unsafeCSS(fonts['KHTeka-400'])}) format('woff');
-        font-weight: 400;
-        font-style: normal;
-      }
+      ${themeVariables?.['--w3m-font-family']
+        ? css``
+        : css`
+            @font-face {
+              font-family: 'KHTeka';
+              src: url(${unsafeCSS(fonts['KHTeka-500'])}) format('woff');
+              font-weight: 500;
+              font-style: normal;
+            }
+
+            @font-face {
+              font-family: 'KHTeka';
+              src: url(${unsafeCSS(fonts['KHTeka-300'])}) format('woff');
+              font-weight: 300;
+              font-style: normal;
+            }
+
+            @font-face {
+              font-family: 'KHTekaMono';
+              src: url(${unsafeCSS(fonts['KHTekaMono-400'])}) format('woff');
+              font-weight: 400;
+              font-style: normal;
+            }
+
+            @font-face {
+              font-family: 'KHTeka';
+              src: url(${unsafeCSS(fonts['KHTeka-400'])}) format('woff');
+              font-weight: 400;
+              font-style: normal;
+            }
+          `}
 
       @keyframes w3m-shake {
         0% {
diff --git a/packages/ui/src/utils/ThemeUtil.ts b/packages/ui/src/utils/ThemeUtil.ts
index 75d6c0a3b5..6526b2db41 100644
--- a/packages/ui/src/utils/ThemeUtil.ts
+++ b/packages/ui/src/utils/ThemeUtil.ts
@@ -41,10 +41,14 @@ export function setThemeVariables(themeVariables: ThemeVariables) {
   }
 }
 
-function createRootStyles(themeVariables?: ThemeVariables) {
+export function createRootStyles(themeVariables?: ThemeVariables) {
   return {
     core: css`
-      @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
+      ${themeVariables?.['--w3m-font-family']
+        ? css``
+        : css`
+            @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
+          `}
       @keyframes w3m-shake {
         0% {
           transform: scale(1) rotate(0deg);


Test patch:
diff --git a/packages/ui-new/tests/ThemeUtil.test.ts b/packages/ui-new/tests/ThemeUtil.test.ts
new file mode 100644
index 0000000000..4e331cc5d0
--- /dev/null
+++ b/packages/ui-new/tests/ThemeUtil.test.ts
@@ -0,0 +1,61 @@
+import { describe, expect, it } from 'vitest'
+
+import type { ThemeVariables } from '@reown/appkit-common'
+
+import { createRootStyles } from '../src/utils/ThemeUtil.js'
+
+describe('ThemeUtil', () => {
+  describe('createRootStyles', () => {
+    it('should include KHTeka font-face declarations when no custom font family is provided', () => {
+      const themeVariables: ThemeVariables = {}
+      const styles = createRootStyles(themeVariables)
+
+      expect(styles.core.cssText).toContain("font-family: 'KHTeka'")
+      expect(styles.core.cssText).toContain("font-family: 'KHTekaMono'")
+      expect(styles.core.cssText).toContain('font-weight: 500')
+      expect(styles.core.cssText).toContain('font-weight: 300')
+      expect(styles.core.cssText).toContain('font-weight: 400')
+    })
+
+    it('should include KHTeka font-face declarations when custom font family is undefined', () => {
+      const themeVariables: ThemeVariables = {
+        '--w3m-font-family': undefined
+      }
+      const styles = createRootStyles(themeVariables)
+
+      expect(styles.core.cssText).toContain("font-family: 'KHTeka'")
+      expect(styles.core.cssText).toContain("font-family: 'KHTekaMono'")
+    })
+
+    it('should not include KHTeka font-face declarations when custom font family is provided', () => {
+      const themeVariables: ThemeVariables = {
+        '--w3m-font-family': 'Custom Font, sans-serif'
+      }
+      const styles = createRootStyles(themeVariables)
+
+      expect(styles.core.cssText).not.toContain("font-family: 'KHTeka'")
+      expect(styles.core.cssText).not.toContain("font-family: 'KHTekaMono'")
+    })
+
+    it('should not include KHTeka font-face declarations when custom font family is empty string', () => {
+      const themeVariables: ThemeVariables = {
+        '--w3m-font-family': ''
+      }
+      const styles = createRootStyles(themeVariables)
+
+      expect(styles.core.cssText).not.toContain("font-family: 'KHTeka'")
+      expect(styles.core.cssText).not.toContain("font-family: 'KHTekaMono'")
+    })
+
+    it('should always include keyframe animations regardless of font family setting', () => {
+      const withCustomFont: ThemeVariables = { '--w3m-font-family': 'Custom Font' }
+      const withoutCustomFont: ThemeVariables = {}
+
+      const stylesWithCustom = createRootStyles(withCustomFont)
+      const stylesWithoutCustom = createRootStyles(withoutCustomFont)
+
+      expect(stylesWithCustom.core.cssText).toContain('@keyframes w3m-shake')
+      expect(stylesWithoutCustom.core.cssText).toContain('@keyframes w3m-shake')
+    })
+  })
+})
diff --git a/packages/ui/tests/ThemeUtil.test.ts b/packages/ui/tests/ThemeUtil.test.ts
new file mode 100644
index 0000000000..bead05e980
--- /dev/null
+++ b/packages/ui/tests/ThemeUtil.test.ts
@@ -0,0 +1,40 @@
+import { describe, expect, it } from 'vitest'
+
+import type { ThemeVariables } from '@reown/appkit-common'
+
+import { createRootStyles } from '../src/utils/ThemeUtil.js'
+
+describe('ThemeUtil', () => {
+  describe('createRootStyles', () => {
+    it('should include Google Fonts import when no custom font family is provided', () => {
+      const themeVariables: ThemeVariables = {}
+      const styles = createRootStyles(themeVariables)
+
+      expect(styles.core.cssText).toContain(
+        "@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap')"
+      )
+    })
+
+    it('should not include Google Fonts import when custom font family is provided', () => {
+      const themeVariables: ThemeVariables = {
+        '--w3m-font-family': 'Custom Font, sans-serif'
+      }
+      const styles = createRootStyles(themeVariables)
+
+      expect(styles.core.cssText).not.toContain(
+        "@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap')"
+      )
+    })
+
+    it('should always include keyframe animations regardless of font family setting', () => {
+      const withCustomFont: ThemeVariables = { '--w3m-font-family': 'Custom Font' }
+      const withoutCustomFont: ThemeVariables = {}
+
+      const stylesWithCustom = createRootStyles(withCustomFont)
+      const stylesWithoutCustom = createRootStyles(withoutCustomFont)
+
+      expect(stylesWithCustom.core.cssText).toContain('@keyframes w3m-shake')
+      expect(stylesWithoutCustom.core.cssText).toContain('@keyframes w3m-shake')
+    })
+  })
+})