Polish brand presentation

This commit is contained in:
null 2026-07-10 19:49:20 -05:00
parent 562da73a76
commit e7974cf4c0
15 changed files with 53 additions and 47 deletions

View File

@ -37,7 +37,7 @@ Username: guest · Password: guest123
## Screenshots ## Screenshots
Screenshots below were refreshed from the linked demo server. Screenshots below were refreshed from the current product build.
![Login screen](docs/images/login.png) ![Login screen](docs/images/login.png)

View File

@ -1,4 +1,5 @@
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { ListFilter, RefreshCw, ShieldCheck, Sparkles, type LucideIcon } from 'lucide-react';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -11,6 +12,14 @@ import { RELEASE_NOTES } from '@/lib/version';
import { BrandGlyph } from '@/components/brand/Brand'; import { BrandGlyph } from '@/components/brand/Brand';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { api } from '@/api'; import { api } from '@/api';
import type { ReleaseHighlightIcon } from '@/lib/version';
const releaseIcon: Record<ReleaseHighlightIcon, LucideIcon> = {
sparkles: Sparkles,
filter: ListFilter,
sync: RefreshCw,
shield: ShieldCheck,
};
export function ReleaseNotesDialog() { export function ReleaseNotesDialog() {
const { hasNewVersion, setHasNewVersion } = useAuth(); const { hasNewVersion, setHasNewVersion } = useAuth();
@ -55,17 +64,25 @@ export function ReleaseNotesDialog() {
</DialogHeader> </DialogHeader>
<div className="mt-2 space-y-3" role="list" aria-label="Release highlights"> <div className="mt-2 space-y-3" role="list" aria-label="Release highlights">
{RELEASE_NOTES.highlights.map((item, i) => ( {RELEASE_NOTES.highlights.map((item) => {
<div key={i} className="flex gap-3 items-start" role="listitem"> const Icon = releaseIcon[item.icon];
<span className="text-lg leading-none mt-0.5" aria-hidden="true"> return (
{item.icon} <div key={item.title} className="flex gap-3 items-start" role="listitem">
<span
className="mt-0.5 grid h-8 w-8 shrink-0 place-items-center rounded-lg border border-primary/20 bg-primary/10 text-primary"
aria-hidden="true"
>
<Icon className="h-4 w-4" />
</span> </span>
<div> <div>
<p className="text-sm font-medium text-foreground">{item.title}</p> <p className="text-sm font-medium text-foreground">{item.title}</p>
<p className="text-xs text-muted-foreground mt-0.5 leading-relaxed">{item.desc}</p> <p className="text-xs text-muted-foreground mt-0.5 leading-relaxed">
{item.desc}
</p>
</div> </div>
</div> </div>
))} );
})}
</div> </div>
{RELEASE_NOTES.image && ( {RELEASE_NOTES.image && (

View File

@ -146,7 +146,7 @@ export function MetricCard({
</div> </div>
{action} {action}
</div> </div>
<p className="metric-value mt-4 text-2xl leading-none sm:text-[1.72rem]">{value}</p> <div className="metric-value mt-4 text-2xl leading-none sm:text-[1.72rem]">{value}</div>
{hint && <p className="mt-2 text-xs leading-5 text-muted-foreground">{hint}</p>} {hint && <p className="mt-2 text-xs leading-5 text-muted-foreground">{hint}</p>}
</div> </div>
); );

View File

@ -57,7 +57,9 @@
--color-sidebar-border: oklch(var(--sidebar-border)); --color-sidebar-border: oklch(var(--sidebar-border));
--color-sidebar-ring: oklch(var(--sidebar-ring)); --color-sidebar-ring: oklch(var(--sidebar-ring));
--font-sans: var(--font-sans), ui-sans-serif, system-ui, sans-serif; --font-sans:
Inter, Roboto, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
sans-serif;
--font-serif: var(--font-serif), ui-serif, serif; --font-serif: var(--font-serif), ui-serif, serif;
--font-mono: var(--font-mono), ui-monospace, SFMono-Regular, monospace; --font-mono: var(--font-mono), ui-monospace, SFMono-Regular, monospace;
@ -277,7 +279,7 @@
font-family: 'GeorgiaDigits'; font-family: 'GeorgiaDigits';
src: local('Georgia'); src: local('Georgia');
unicode-range: unicode-range:
U+0030- U+0039, U+0030-0039,
/* 09 */ U+002C, /* 09 */ U+002C,
/* , thousands separator */ U+002E, /* , thousands separator */ U+002E,
/* . decimal point */ U+002D, /* . decimal point */ U+002D,
@ -327,11 +329,11 @@
--sidebar-accent-foreground: 0.205 0.02 190; --sidebar-accent-foreground: 0.205 0.02 190;
--sidebar-border: 0.875 0.01 235; --sidebar-border: 0.875 0.01 235;
--sidebar-ring: 0.64 0.15 154; --sidebar-ring: 0.64 0.15 154;
--font-sans: 'GeorgiaDigits', Inter, Roboto, ui-sans-serif, system-ui, sans-serif; --font-sans:
Inter, Roboto, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
sans-serif;
--font-serif: Merriweather, ui-serif, serif; --font-serif: Merriweather, ui-serif, serif;
--font-mono: --font-mono: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
'GeorgiaDigits', 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
--radius: 1rem; --radius: 1rem;
} }

View File

@ -4,8 +4,10 @@ declare const __APP_VERSION__: string;
export const APP_VERSION = __APP_VERSION__; export const APP_VERSION = __APP_VERSION__;
export type ReleaseHighlightIcon = 'sparkles' | 'filter' | 'sync' | 'shield';
export interface ReleaseHighlight { export interface ReleaseHighlight {
icon: string; icon: ReleaseHighlightIcon;
title: string; title: string;
desc: string; desc: string;
} }
@ -19,42 +21,27 @@ export interface ReleaseNotes {
export const RELEASE_NOTES: ReleaseNotes = { export const RELEASE_NOTES: ReleaseNotes = {
version: APP_VERSION, version: APP_VERSION,
date: '2026-05-31', date: '2026-07-10',
highlights: [ highlights: [
{ {
icon: '🚀', icon: 'sparkles',
title: 'v0.35.0', title: 'Product brand refresh',
desc: 'Version bump and container rebuild.', desc: 'Updated the app identity surfaces, README artwork, favicon family, and preview imagery so Bill Tracker presents like one coherent product.',
}, },
{ {
icon: '🧠', icon: 'filter',
title: 'Advisory non-bill transaction filters', title: 'Smarter transaction triage',
desc: '5,000+ advisory patterns with 83 bill-like override terms. High-confidence unmatched transactions show "Probably not a bill" instead of "Create Bill". Medium confidence mutes the button. Lazy in-memory cache, seeded on first startup.', desc: 'Unmatched bank activity now gets advisory filtering, with bill-like overrides and gentler calls to action for transactions that probably are not bills.',
}, },
{ {
icon: '🔄', icon: 'sync',
title: 'SimpleFIN transaction table fix', title: 'Steadier SimpleFIN workflows',
desc: "Transaction table now uses fixed column sizing so long text can't push action buttons off-screen. Action buttons are compact icon-only with accessible labels.", desc: 'Transaction tables hold their shape, action buttons stay reachable, and subscription bills can backfill missing payment history from matched bank activity.',
}, },
{ {
icon: '🔄', icon: 'shield',
title: 'SimpleFIN payment backfill', title: 'Safer history and privacy details',
desc: 'Subscription bills with merchant rules now have a Sync Payments button in the edit modal. It scans unmatched SimpleFIN transactions and auto-creates payment records for missing history.', desc: 'Destructive actions use clearer confirmation and undo paths, while profile login details remain visible only to the signed-in user.',
},
{
icon: '🛡️',
title: 'Safer financial history',
desc: 'Bill, category, and payment deletes now use confirmations, recovery windows, and undo actions so accidental clicks do not immediately destroy important records.',
},
{
icon: '🔐',
title: 'Security checks tightened',
desc: 'Logout-all now uses the normal CSRF header, password length rules match the backend, and CSRF SPA documentation now matches the actual cookie/header flow.',
},
{
icon: '🔑',
title: 'Private login details',
desc: 'Your Profile now shows recent login date, IP, browser, OS, device type, and a short device ID. These details are shown only to you in the app UI.',
}, },
], ],
image: { image: {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 262 KiB