fix(splash): Draw the wordmark as outlines so it can't swap fonts

The splash set its wordmark in Inter, a web font with font-display: swap. When
the font arrived late (on a cold dev start the dev server took up to seconds to
serve it), the splash showed the system font first and switched to Inter just
before fading, so the word grew and shifted. It is now an inline SVG of the same
text in Inter 500, so it renders identically from the first frame. This replaces
the previous attempt, which only moved where the font faces load.
This commit is contained in:
l0ng-ai
2026-10-27 17:35:37 +08:00
parent 866af3d9cb
commit 482f391fd1
4 changed files with 10 additions and 14 deletions
+5 -3
View File
@@ -5,18 +5,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OpenIDEA</title>
<script src="/boot.js"></script>
<link rel="stylesheet" href="/src/styles/fonts.css" />
<link rel="stylesheet" href="/splash.css" />
</head>
<body>
<div id="root"></div>
<div id="splash" class="splash" data-tauri-drag-region>
<svg viewBox="0 0 64 64" aria-hidden="true">
<svg class="splash-logo" viewBox="0 0 64 64" aria-hidden="true">
<rect width="64" height="64" rx="15" fill="#0E0E10" />
<circle cx="26" cy="32" r="11" fill="none" stroke="#FFFFFF" stroke-width="8" />
<rect x="43" y="18" width="8" height="28" rx="1.5" fill="#FF4F1A" />
</svg>
<span>OpenIDEA</span>
<!-- "OpenIDEA" in Inter 500 as outlines: the web font loads late in dev and would swap in. -->
<svg class="splash-wordmark" viewBox="0 -1984 9994 2478" role="img" aria-label="OpenIDEA">
<path fill="currentColor" d="M785.8 20Q592.6 20 440.4 -71.7Q288.2 -163.4 200.4 -334.7Q112.6 -506 112.6 -744Q112.6 -983.2 200.4 -1154.6Q288.2 -1326 440.4 -1418Q592.6 -1510 785.8 -1510Q979 -1510 1130.7 -1418Q1282.4 -1326 1369.8 -1154.6Q1457.3 -983.2 1457.3 -744Q1457.3 -505.8 1369.8 -334.5Q1282.4 -163.2 1130.7 -71.6Q979 20 785.8 20ZM785.8 -187.7Q913 -187.7 1013.5 -251.6Q1114 -315.5 1172.4 -439.9Q1230.7 -564.3 1230.7 -744Q1230.7 -925.6 1172.4 -1050Q1114 -1174.5 1013.5 -1238.4Q913 -1302.3 785.8 -1302.3Q657.9 -1302.3 557 -1238Q456.1 -1173.7 397.7 -1049.2Q339.2 -924.7 339.2 -744Q339.2 -564.3 397.7 -440.3Q456.1 -316.3 557 -252Q657.9 -187.7 785.8 -187.7ZM1717.9 418V-1118H1932.2V-935.9H1950.4Q1970 -970.8 2005.4 -1016.7Q2040.9 -1062.7 2104.6 -1097.3Q2168.3 -1132 2272.6 -1132Q2407.4 -1132 2512.7 -1064Q2617.9 -996 2678.8 -867Q2739.8 -738 2739.8 -556.4Q2739.8 -375.7 2679.8 -246.2Q2619.8 -116.7 2514.5 -47.3Q2409.1 22.2 2272.7 22.2Q2171.8 22.2 2107.4 -12.4Q2043 -47 2006.6 -93.2Q1970.2 -139.3 1950.4 -175H1937.9V418ZM2224 -165.3Q2320.1 -165.3 2384.9 -217.3Q2449.6 -269.3 2482.4 -358.3Q2515.2 -447.3 2515.2 -558Q2515.2 -668.1 2482.8 -755.4Q2450.4 -842.8 2385.7 -893.7Q2321 -944.5 2224 -944.5Q2129.6 -944.5 2065 -896.1Q2000.4 -847.7 1967.4 -761.2Q1934.4 -674.6 1934.4 -558Q1934.4 -441.7 1967.8 -353.2Q2001.2 -264.7 2066.2 -215Q2131.2 -165.3 2224 -165.3ZM3465.8 23.3Q3300.7 23.3 3181.1 -48.1Q3061.4 -119.5 2996.9 -248.5Q2932.4 -377.5 2932.4 -551.1Q2932.4 -723.3 2995.8 -854Q3059.1 -984.7 3175.1 -1058.4Q3291 -1132 3446.8 -1132Q3542.6 -1132 3632 -1100.7Q3721.4 -1069.4 3792.3 -1002.3Q3863.3 -935.2 3904.7 -828.3Q3946.2 -721.5 3946.2 -570.3V-492.2H3054.8V-656.5H3832.8L3730.1 -602.3Q3730.1 -704.7 3698.2 -783.2Q3666.3 -861.7 3603.5 -905.9Q3540.8 -950 3447.5 -950Q3354.2 -950 3288.2 -905Q3222.1 -860 3187.4 -786.5Q3152.6 -712.9 3152.6 -626.1V-514.4Q3152.6 -399.4 3192.1 -319.8Q3231.6 -240.1 3302.9 -199.4Q3374.2 -158.7 3468.1 -158.7Q3529.6 -158.7 3579.9 -176.3Q3630.2 -194 3666.5 -229.4Q3702.8 -264.9 3722.2 -317.2L3928.6 -268.5Q3902.2 -181.6 3838.6 -115.9Q3775 -50.2 3680.4 -13.4Q3585.8 23.3 3465.8 23.3ZM4406.9 -662.4V0H4186.9V-1118H4396.6L4398.9 -844.3H4376.2Q4424.9 -994.3 4517.8 -1063.1Q4610.7 -1132 4742.5 -1132Q4856.6 -1132 4942 -1084.2Q5027.5 -1036.3 5075.1 -942.5Q5122.7 -848.8 5122.7 -710.4V0H4902.7V-682.9Q4902.7 -803.7 4839.8 -872.1Q4776.9 -940.5 4667.3 -940.5Q4592.9 -940.5 4533.8 -907.9Q4474.8 -875.3 4440.8 -813.3Q4406.9 -751.2 4406.9 -662.4ZM5664.4 -1490V0H5435.9V-1490ZM6478.5 0H6109.9V-199.7H6465.8Q6635 -199.7 6747.1 -263Q6859.2 -326.3 6915 -448.6Q6970.8 -571 6970.8 -747.3Q6970.8 -922.1 6915.2 -1043.3Q6859.7 -1164.4 6750.5 -1227.4Q6641.3 -1290.3 6478.4 -1290.3H6102.2V-1490H6493Q6713.2 -1490 6869.9 -1400.9Q7026.7 -1311.8 7110.7 -1145.2Q7194.7 -978.6 7194.7 -747.3Q7194.7 -514.5 7110.4 -347.1Q7026 -179.6 6865.8 -89.8Q6705.5 0 6478.5 0ZM6222.4 -1490V0H5993.9V-1490ZM7471.9 0V-1490H8409.8V-1293.6H7700.4V-849.7H8359.5V-654.7H7700.4V-196.4H8416.4V0ZM8592.9 0 9123.5 -1490H9403.2L9942.8 0H9696.3L9406.1 -828.9Q9372.2 -930 9331.8 -1066.9Q9291.4 -1203.8 9238.4 -1395.6H9284.5Q9232.7 -1202.2 9192.5 -1063.6Q9152.4 -925.1 9121.4 -828.9L8839.9 0ZM8880.4 -392.6V-583.1H9655.3V-392.6Z" />
</svg>
<div class="splash-bar" role="progressbar" aria-label="Loading"><i></i></div>
</div>
<script type="module" src="/src/main.tsx"></script>
+3 -7
View File
@@ -17,22 +17,18 @@ body, .splash { background: #e9eaee; }
gap: 14px;
padding-bottom: 38px;
box-sizing: border-box;
font: 500 15px/1.2 "Inter Variable", Inter, system-ui, -apple-system, sans-serif;
color: #6c707e;
/* As on body: picking it up when the app CSS arrives would change the wordmark's weight. */
-webkit-font-smoothing: antialiased;
-webkit-user-select: none;
user-select: none;
cursor: default;
animation: splash-in 240ms ease-out 120ms both;
transition: opacity 160ms ease-out;
/* One compositing layer for its whole life: WebKit layers it only while the opacity animates,
and the fade-out's fresh layer re-snaps the centred text, which then jumps up half a pixel. */
will-change: opacity;
}
.splash.splash-out { opacity: 0; pointer-events: none; }
:root[data-theme^="dark"] .splash { color: #8c8f95; }
.splash svg { width: 56px; height: 56px; }
.splash-logo { width: 56px; height: 56px; }
/* 15px Inter: 2048 units per em, the line box from ascender to descender. */
.splash-wordmark { width: 73.2px; height: 18.15px; }
.splash-bar { width: 120px; height: 2px; border-radius: 1px; overflow: hidden; background: rgb(127 127 127 / 0.18); }
/* Fake progress: eases towards ~90% over the 4 s cap; hideSplash() fills it before fading out. */
.splash-bar > i {
-4
View File
@@ -1,4 +0,0 @@
/* Linked from index.html rather than imported by global.css, so the faces are known before the
splash first paints: the dev server injects the app CSS only once the bundle runs. */
@import "@fontsource-variable/inter";
@import "@fontsource-variable/jetbrains-mono";
+2
View File
@@ -1,3 +1,5 @@
@import "@fontsource-variable/inter";
@import "@fontsource-variable/jetbrains-mono";
@import "./tokens.css";
/* Monochrome icons default to the theme icon grey; callers override for selected / disabled. */