feat: upgrade typography - Plus Jakarta Sans headings, JetBrains Mono data, 14px base
Heading font: Plus Jakarta Sans (500/600/700) for all h1-h3, stat values, dialog titles, timer display, and wordmark. Body font: Inter (400/500/600/700) unchanged but base bumped from 13px to 14px. Mono font: JetBrains Mono replaces IBM Plex Mono for code and tabular data.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<title>ZeroClock</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -50,7 +50,7 @@ async function handleDoubleClick() {
|
||||
<!-- Left: App name -->
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="text-accent-text text-[0.6875rem] font-medium tracking-[0.1em] uppercase"
|
||||
class="text-accent-text text-[0.6875rem] font-medium font-[family-name:var(--font-heading)] tracking-[0.1em] uppercase"
|
||||
>
|
||||
ZeroClock
|
||||
</span>
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
|
||||
/* Fonts */
|
||||
--font-sans: 'Inter', system-ui, sans-serif;
|
||||
--font-mono: 'IBM Plex Mono', monospace;
|
||||
--font-heading: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', 'IBM Plex Mono', monospace;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@@ -48,7 +49,7 @@
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.8125rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
background-color: var(--color-bg-base);
|
||||
color: var(--color-text-primary);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<template v-else>
|
||||
<!-- Greeting header -->
|
||||
<div class="mb-8">
|
||||
<p class="text-lg text-text-secondary">{{ greeting }}</p>
|
||||
<p class="text-xl font-[family-name:var(--font-heading)] text-text-secondary">{{ greeting }}</p>
|
||||
<p class="text-xs text-text-tertiary mt-1">{{ formattedDate }}</p>
|
||||
</div>
|
||||
|
||||
@@ -22,25 +22,25 @@
|
||||
<div class="grid grid-cols-4 gap-6 mb-8">
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Today</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatDuration(todayStats.totalSeconds) }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatDuration(todayStats.totalSeconds) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">This Week</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatDuration(weekStats.totalSeconds) }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatDuration(weekStats.totalSeconds) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">This Month</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatDuration(monthStats.totalSeconds) }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatDuration(monthStats.totalSeconds) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Active Projects</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ activeProjectsCount }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ activeProjectsCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Weekly chart -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Weekly Hours</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Weekly Hours</h2>
|
||||
<div class="h-48">
|
||||
<Bar v-if="chartData" :data="chartData" :options="chartOptions" />
|
||||
</div>
|
||||
@@ -49,7 +49,7 @@
|
||||
<!-- Recent entries -->
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-[1rem] font-medium text-text-primary">Recent Entries</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary">Recent Entries</h2>
|
||||
<router-link to="/entries" class="text-xs text-text-tertiary hover:text-text-secondary transition-colors">View all</router-link>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="p-6">
|
||||
<h1 class="text-[1.5rem] font-medium text-text-primary mb-6">Entries</h1>
|
||||
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Entries</h1>
|
||||
|
||||
<!-- Filters -->
|
||||
<div class="bg-bg-surface rounded-lg p-4 mb-6 flex flex-wrap items-end gap-4">
|
||||
@@ -133,7 +133,7 @@
|
||||
@click.self="closeEditDialog"
|
||||
>
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md mx-4 p-6 animate-modal-enter">
|
||||
<h2 class="text-[1rem] font-semibold text-text-primary mb-4">Edit Entry</h2>
|
||||
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Edit Entry</h2>
|
||||
|
||||
<form @submit.prevent="handleEdit" class="space-y-4">
|
||||
<!-- Project -->
|
||||
@@ -213,7 +213,7 @@
|
||||
@click.self="cancelDelete"
|
||||
>
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
|
||||
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Delete Entry</h2>
|
||||
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Entry</h2>
|
||||
<p class="text-[0.75rem] text-text-secondary mb-6">
|
||||
Are you sure you want to delete this time entry? This action cannot be undone.
|
||||
</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="p-6">
|
||||
<h1 class="text-[1.5rem] font-medium text-text-primary mb-6">Invoices</h1>
|
||||
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Invoices</h1>
|
||||
|
||||
<!-- View tabs -->
|
||||
<div class="flex gap-6 mb-6 border-b border-border-subtle">
|
||||
@@ -120,7 +120,7 @@
|
||||
|
||||
<!-- Create View -->
|
||||
<div v-else-if="view === 'create'" class="max-w-lg">
|
||||
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Create Invoice</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Create Invoice</h2>
|
||||
|
||||
<form @submit.prevent="handleCreate" class="space-y-4">
|
||||
<!-- Client -->
|
||||
@@ -247,7 +247,7 @@
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-2xl mx-4 p-6 max-h-[90vh] overflow-y-auto animate-modal-enter">
|
||||
<div class="flex items-start justify-between mb-6">
|
||||
<div>
|
||||
<h2 class="text-[1.5rem] font-medium text-text-primary">{{ selectedInvoice?.invoice_number }}</h2>
|
||||
<h2 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary">{{ selectedInvoice?.invoice_number }}</h2>
|
||||
<p class="text-[0.75rem] text-text-secondary">{{ getClientName(selectedInvoice?.client_id || 0) }}</p>
|
||||
</div>
|
||||
<button
|
||||
@@ -315,7 +315,7 @@
|
||||
@click.self="showDeleteDialog = false"
|
||||
>
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
|
||||
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Delete Invoice</h2>
|
||||
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Invoice</h2>
|
||||
<p class="text-[0.75rem] text-text-secondary mb-6">
|
||||
Are you sure you want to delete invoice "{{ invoiceToDelete?.invoice_number }}"? This action cannot be undone.
|
||||
</p>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="p-6">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h1 class="text-[1.5rem] font-medium text-text-primary">Projects</h1>
|
||||
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary">Projects</h1>
|
||||
<button
|
||||
@click="openCreateDialog"
|
||||
class="px-3 py-1.5 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150"
|
||||
@@ -72,7 +72,7 @@
|
||||
@click.self="closeDialog"
|
||||
>
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md mx-4 p-6 animate-modal-enter">
|
||||
<h2 class="text-[1rem] font-semibold text-text-primary mb-4">
|
||||
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">
|
||||
{{ editingProject ? 'Edit Project' : 'Create Project' }}
|
||||
</h2>
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
@click.self="cancelDelete"
|
||||
>
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
|
||||
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Delete Project</h2>
|
||||
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Project</h2>
|
||||
<p class="text-[0.75rem] text-text-secondary mb-6">
|
||||
Are you sure you want to delete "{{ projectToDelete?.name }}"? This action cannot be undone.
|
||||
</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="p-6">
|
||||
<h1 class="text-[1.5rem] font-medium text-text-primary mb-6">Reports</h1>
|
||||
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Reports</h1>
|
||||
|
||||
<!-- Date Range Selector -->
|
||||
<div class="bg-bg-surface rounded-lg p-4 mb-6 flex flex-wrap items-end gap-4">
|
||||
@@ -38,21 +38,21 @@
|
||||
<div class="grid grid-cols-3 gap-6 mb-8">
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Total Hours</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatHours(reportData.totalSeconds) }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatHours(reportData.totalSeconds) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Earnings</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">${{ reportData.totalEarnings?.toFixed(2) || '0.00' }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">${{ reportData.totalEarnings?.toFixed(2) || '0.00' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Projects</p>
|
||||
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ reportData.byProject?.length || 0 }}</p>
|
||||
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ reportData.byProject?.length || 0 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chart -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Hours by Project</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Hours by Project</h2>
|
||||
<div class="h-64">
|
||||
<Bar v-if="chartData" :data="chartData" :options="chartOptions" />
|
||||
<div v-else class="flex flex-col items-center justify-center h-full">
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
<!-- Project Breakdown -->
|
||||
<div>
|
||||
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Breakdown</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Breakdown</h2>
|
||||
|
||||
<div v-if="reportData.byProject && reportData.byProject.length > 0">
|
||||
<div
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div class="flex-1 p-6 overflow-y-auto">
|
||||
<!-- General -->
|
||||
<div v-if="activeTab === 'general'">
|
||||
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">General</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">General</h2>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
<!-- Timer -->
|
||||
<div v-if="activeTab === 'timer'">
|
||||
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">Timer</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">Timer</h2>
|
||||
|
||||
<div class="space-y-5">
|
||||
<!-- Idle Detection toggle -->
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
<!-- Billing -->
|
||||
<div v-if="activeTab === 'billing'">
|
||||
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">Billing</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">Billing</h2>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
@@ -129,7 +129,7 @@
|
||||
|
||||
<!-- Data -->
|
||||
<div v-if="activeTab === 'data'">
|
||||
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">Data</h2>
|
||||
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">Data</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Export -->
|
||||
@@ -173,7 +173,7 @@
|
||||
@click.self="showClearDataDialog = false"
|
||||
>
|
||||
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
|
||||
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Clear All Data</h2>
|
||||
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Clear All Data</h2>
|
||||
<p class="text-[0.75rem] text-text-secondary mb-4">
|
||||
Are you sure? This action cannot be undone.
|
||||
</p>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="p-6">
|
||||
<!-- Hero timer display -->
|
||||
<div class="text-center pt-4 pb-8">
|
||||
<p class="text-[3rem] font-mono font-medium tracking-wider mb-6">
|
||||
<p class="text-[3.5rem] font-medium font-[family-name:var(--font-heading)] tracking-tighter mb-6">
|
||||
<span class="text-text-primary">{{ timerParts.hours }}</span>
|
||||
<span :class="timerStore.isRunning ? 'text-accent-text animate-pulse-colon' : 'text-text-primary'">:</span>
|
||||
<span class="text-text-primary">{{ timerParts.minutes }}</span>
|
||||
|
||||
Reference in New Issue
Block a user