Skip to content

Commit 8f86848

Browse files
JavaZerooclaude
andcommitted
feat: visual polish — Inter + JetBrains Mono fonts, card hover, stagger entrance, tabular nums
- Self-host Inter Variable and JetBrains Mono Variable via @fontsource-variable (~135 KB woff2, loaded on-demand by subset). Enable cv11 + ss03 stylistic sets on Inter for a more refined default. - Apply JetBrains Mono to code/pre/kbd/samp automatically. - Card lift: .card gains transition-shadow + shadow-lg on hover, giving a subtle "floating" feedback on all sidebar / stats cards. - Sidebar stagger entrance: each card fades + translates in 40 ms apart on mount (total ~500 ms); respects prefers-reduced-motion. - Add .tabular utility (font-variant-numeric: tabular-nums) and apply to both stats tables so number columns no longer jitter. Additive only — no existing visuals (logo gradient, emojis, page background, chart colors, animations) were removed. JS bundle unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 30c7e72 commit 8f86848

6 files changed

Lines changed: 84 additions & 5 deletions

File tree

package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"test:stress": "node scripts/stress-test.js"
1515
},
1616
"dependencies": {
17+
"@fontsource-variable/inter": "^5.2.8",
18+
"@fontsource-variable/jetbrains-mono": "^5.2.8",
1719
"@tailwindcss/forms": "^0.5.10",
1820
"autoprefixer": "^10.4.21",
1921
"chart.js": "^4.5.0",

src/App.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ function App() {
543543
>
544544
{sidebarVisible && (
545545
<aside
546-
className="xl:col-span-1 space-y-3"
546+
className="xl:col-span-1 space-y-3 sidebar-stagger"
547547
role="complementary"
548548
aria-label={t('sidebar.controlPanel')}
549549
>

src/components/ChartContainer.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ export default function ChartContainer({
959959
{perFileStats.length > 0 && (
960960
<div className="card overflow-x-auto">
961961
<h4 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">{key} {t('chart.summaryStats')}</h4>
962-
<table className="min-w-full text-xs">
962+
<table className="min-w-full text-xs tabular">
963963
<thead>
964964
<tr className="text-left">
965965
<th className="pr-2">{t('chart.stats.file')}</th>
@@ -990,7 +990,7 @@ export default function ChartContainer({
990990
{stats && (
991991
<div className="card overflow-x-auto">
992992
<h4 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">{key} {t('chart.diffStats')}</h4>
993-
<table className="min-w-full text-xs">
993+
<table className="min-w-full text-xs tabular">
994994
<thead>
995995
<tr className="text-left">
996996
<th className="pr-2">{t('comparison.pair')}</th>

src/index.css

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44

55
/* Accessibility improvements */
66
@layer base {
7+
html {
8+
font-family: 'Inter Variable', 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
9+
/* Inter's stylistic sets: cv11 = single-storey a, ss03 = better default cursive. Subtle polish. */
10+
font-feature-settings: 'cv11', 'ss03';
11+
-webkit-font-smoothing: antialiased;
12+
-moz-osx-font-smoothing: grayscale;
13+
}
14+
code, pre, kbd, samp {
15+
font-family: 'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
16+
}
717
body {
818
@apply bg-gray-50 text-gray-900 dark:bg-gray-900 dark:text-gray-100;
919
}
@@ -67,7 +77,11 @@
6777

6878
@layer components {
6979
.card {
70-
@apply bg-white dark:bg-gray-800 rounded-lg shadow-md p-3;
80+
@apply bg-white dark:bg-gray-800 rounded-lg shadow-md p-3 transition-shadow duration-200 ease-out;
81+
}
82+
/* Subtle lift on hover — adds life without being distracting */
83+
.card:hover {
84+
@apply shadow-lg;
7185
}
7286

7387
.card-title {
@@ -101,6 +115,20 @@
101115
.resizable-chart-container {
102116
@apply relative min-h-[200px] max-h-[600px] resize-y overflow-hidden border border-gray-200 dark:border-gray-700 rounded-lg;
103117
}
118+
119+
/* Tabular figures — for number columns / stats so digits don't jitter */
120+
.tabular {
121+
font-variant-numeric: tabular-nums;
122+
font-feature-settings: 'tnum';
123+
}
124+
125+
/* Subtle card hover affordance — gentle lift + shadow bump. Cheap visual feedback. */
126+
.card-hover {
127+
@apply transition-[transform,box-shadow] duration-200 ease-out;
128+
}
129+
.card-hover:hover {
130+
@apply -translate-y-px shadow-lg;
131+
}
104132
}
105133

106134
/* Custom styles */
@@ -242,8 +270,33 @@ input[type="checkbox"]:focus {
242270
animation: pageFadeIn 0.5s ease-out;
243271
}
244272

273+
/* Sidebar cards stagger entrance — 40ms apart, small translateY for a "settling in" feel.
274+
`backwards` fill keeps each card invisible until its delay elapses. */
275+
@keyframes cardSettleIn {
276+
from {
277+
opacity: 0;
278+
transform: translateY(6px);
279+
}
280+
to {
281+
opacity: 1;
282+
transform: translateY(0);
283+
}
284+
}
285+
286+
.sidebar-stagger > * {
287+
animation: cardSettleIn 0.3s ease-out backwards;
288+
}
289+
.sidebar-stagger > *:nth-child(1) { animation-delay: 0ms; }
290+
.sidebar-stagger > *:nth-child(2) { animation-delay: 40ms; }
291+
.sidebar-stagger > *:nth-child(3) { animation-delay: 80ms; }
292+
.sidebar-stagger > *:nth-child(4) { animation-delay: 120ms; }
293+
.sidebar-stagger > *:nth-child(5) { animation-delay: 160ms; }
294+
.sidebar-stagger > *:nth-child(6) { animation-delay: 200ms; }
295+
.sidebar-stagger > *:nth-child(7) { animation-delay: 240ms; }
296+
245297
@media (prefers-reduced-motion: reduce) {
246-
.page-fade-in {
298+
.page-fade-in,
299+
.sidebar-stagger > * {
247300
animation: none !important;
248301
}
249302
}

src/main.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { StrictMode } from 'react';
22
import { createRoot } from 'react-dom/client';
3+
// Self-hosted variable fonts — Inter for UI, JetBrains Mono for numeric/code.
4+
// Variable files are small (~25-30KB each) and cover all weights we need.
5+
import '@fontsource-variable/inter';
6+
import '@fontsource-variable/jetbrains-mono';
37
import './index.css';
48
import './i18n';
59
import App from './App.jsx';

0 commit comments

Comments
 (0)