app icon, toast theming and positioning, rename crate to nomina

This commit is contained in:
2026-03-14 20:05:49 +02:00
parent 1fed289704
commit a34664c91a
34 changed files with 144 additions and 11 deletions

2
Cargo.lock generated
View File

@@ -2206,7 +2206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]] [[package]]
name = "nomina-app" name = "nomina"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",

View File

@@ -1,3 +1,3 @@
[workspace] [workspace]
members = ["crates/nomina-core", "crates/nomina-app"] members = ["crates/nomina-core", "crates/nomina"]
resolver = "2" resolver = "2"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,5 +1,5 @@
[package] [package]
name = "nomina-app" name = "nomina"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
license = "CC0-1.0" license = "CC0-1.0"

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View File

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

View File

@@ -0,0 +1,96 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#065f46"/>
<stop offset="50%" stop-color="#047857"/>
<stop offset="100%" stop-color="#0d9488"/>
</linearGradient>
<linearGradient id="shine" x1="0%" y1="0%" x2="50%" y2="100%">
<stop offset="0%" stop-color="white" stop-opacity="0.18"/>
<stop offset="50%" stop-color="white" stop-opacity="0.05"/>
<stop offset="100%" stop-color="white" stop-opacity="0"/>
</linearGradient>
<filter id="glow" x="-15%" y="-15%" width="130%" height="130%">
<feGaussianBlur in="SourceAlpha" stdDeviation="6" result="blur"/>
<feFlood flood-color="white" flood-opacity="0.3" result="color"/>
<feComposite in="color" in2="blur" operator="in" result="glowColor"/>
<feMerge>
<feMergeNode in="glowColor"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<filter id="shadow" x="-5%" y="-3%" width="110%" height="115%">
<feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="#022c22" flood-opacity="0.35"/>
</filter>
<filter id="rayBlur">
<feGaussianBlur stdDeviation="18"/>
</filter>
<!-- Superellipse n=5 squircle -->
<clipPath id="squircle">
<path d="M 496,256 L 495.9,182.3 L 495.5,158.7 L 494.8,141.7 L 493.9,128 L 492.7,116.2 L 491.2,106 L 489.5,96.8 L 487.5,88.5 L 485.2,81 L 482.6,74.1 L 479.7,67.8 L 476.5,62 L 473,56.6 L 469.1,51.6 L 464.9,47.1 L 460.4,42.9 L 455.4,39 L 450,35.5 L 444.2,32.3 L 437.9,29.4 L 431,26.8 L 423.5,24.5 L 415.2,22.5 L 406,20.8 L 395.8,19.3 L 384,18.1 L 370.3,17.2 L 353.3,16.5 L 329.7,16.1 L 256,16 L 182.3,16.1 L 158.7,16.5 L 141.7,17.2 L 128,18.1 L 116.2,19.3 L 106,20.8 L 96.8,22.5 L 88.5,24.5 L 81,26.8 L 74.1,29.4 L 67.8,32.3 L 62,35.5 L 56.6,39 L 51.6,42.9 L 47.1,47.1 L 42.9,51.6 L 39,56.6 L 35.5,62 L 32.3,67.8 L 29.4,74.1 L 26.8,81 L 24.5,88.5 L 22.5,96.8 L 20.8,106 L 19.3,116.2 L 18.1,128 L 17.2,141.7 L 16.5,158.7 L 16.1,182.3 L 16,256 L 16.1,329.7 L 16.5,353.3 L 17.2,370.3 L 18.1,384 L 19.3,395.8 L 20.8,406 L 22.5,415.2 L 24.5,423.5 L 26.8,431 L 29.4,437.9 L 32.3,444.2 L 35.5,450 L 39,455.4 L 42.9,460.4 L 47.1,464.9 L 51.6,469.1 L 56.6,473 L 62,476.5 L 67.8,479.7 L 74.1,482.6 L 81,485.2 L 88.5,487.5 L 96.8,489.5 L 106,491.2 L 116.2,492.7 L 128,493.9 L 141.7,494.8 L 158.7,495.5 L 182.3,495.9 L 256,496 L 329.7,495.9 L 353.3,495.5 L 370.3,494.8 L 384,493.9 L 395.8,492.7 L 406,491.2 L 415.2,489.5 L 423.5,487.5 L 431,485.2 L 437.9,482.6 L 444.2,479.7 L 450,476.5 L 455.4,473 L 460.4,469.1 L 464.9,464.9 L 469.1,460.4 L 473,455.4 L 476.5,450 L 479.7,444.2 L 482.6,437.9 L 485.2,431 L 487.5,423.5 L 489.5,415.2 L 491.2,406 L 492.7,395.8 L 493.9,384 L 494.8,370.3 L 495.5,353.3 L 495.9,329.7 Z"/>
</clipPath>
</defs>
<!-- Shadow behind the squircle -->
<g filter="url(#shadow)">
<g clip-path="url(#squircle)">
<rect x="0" y="0" width="512" height="512" fill="url(#bg)"/>
</g>
</g>
<!-- Everything inside squircle clip -->
<g clip-path="url(#squircle)">
<!-- Gradient background -->
<rect x="0" y="0" width="512" height="512" fill="url(#bg)"/>
<!-- Light rays / beams -->
<g filter="url(#rayBlur)" opacity="0.12">
<line x1="-50" y1="180" x2="562" y2="80" stroke="white" stroke-width="60"/>
<line x1="-50" y1="320" x2="562" y2="200" stroke="white" stroke-width="40"/>
<line x1="-50" y1="440" x2="562" y2="310" stroke="white" stroke-width="50"/>
<line x1="100" y1="-50" x2="562" y2="420" stroke="white" stroke-width="35"/>
</g>
<!-- Shine overlay -->
<rect x="0" y="0" width="512" height="512" fill="url(#shine)"/>
<!-- Letter N - Transitional serif style -->
<g filter="url(#glow)">
<path d="
M 132 400
L 132 388
Q 132 382, 138 382
L 150 382
Q 158 382, 158 374
L 158 138
Q 158 130, 150 130
L 138 130
Q 132 130, 132 124
L 132 112
L 200 112
Q 208 112, 212 118
L 332 330
L 332 138
Q 332 130, 324 130
L 312 130
Q 306 130, 306 124
L 306 112
L 380 112
L 380 124
Q 380 130, 374 130
L 362 130
Q 354 130, 354 138
L 354 400
L 298 400
Q 290 400, 286 394
L 180 196
L 180 374
Q 180 382, 188 382
L 200 382
Q 206 382, 206 388
L 206 400
Z
" fill="white" fill-opacity="0.95"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -159,9 +159,9 @@ export function AppShell() {
</div> </div>
</div> </div>
<StatusBar /> <StatusBar />
<Toaster />
</div> </div>
</PortalContainerProvider> </PortalContainerProvider>
<Toaster />
</MotionConfig> </MotionConfig>
); );
} }

View File

@@ -1,19 +1,37 @@
import { Toaster as Sonner } from "sonner"; import { Toaster as Sonner } from "sonner";
import { useEffect, useState } from "react";
function useResolvedTheme() {
const [dark, setDark] = useState(() =>
document.documentElement.classList.contains("dark")
);
useEffect(() => {
const observer = new MutationObserver(() => {
setDark(document.documentElement.classList.contains("dark"));
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
return () => observer.disconnect();
}, []);
return dark ? "dark" as const : "light" as const;
}
export function Toaster() { export function Toaster() {
const theme = useResolvedTheme();
return ( return (
<Sonner <Sonner
position="bottom-right" theme={theme}
position="top-center"
closeButton
toastOptions={{ toastOptions={{
classNames: { classNames: {
toast: "bg-card text-card-foreground border-border shadow-lg font-sans text-[13px]", toast: "!border-border !shadow-lg !font-sans !text-[13px] toast-themed",
title: "font-medium", title: "!font-medium",
description: "text-muted-foreground text-[12px]", description: "!text-muted-foreground !text-[12px]",
success: "border-success/30", success: "!border-success/30",
error: "border-destructive/30", error: "!border-destructive/30",
}, },
}} }}
offset={8} offset={64}
gap={6} gap={6}
/> />
); );

View File

@@ -414,6 +414,25 @@ button:not([data-no-target-expand])::after,
overscroll-behavior: contain; overscroll-behavior: contain;
} }
/* Sonner toast overrides */
[data-sonner-toaster] {
pointer-events: auto;
}
[data-sonner-toaster] .toast-themed {
background: oklch(0.30 0 0) !important;
color: var(--foreground) !important;
}
:root:not(.dark) [data-sonner-toaster] .toast-themed {
background: oklch(0.95 0 0) !important;
}
[data-sonner-toaster] [data-close-button] {
pointer-events: auto !important;
cursor: pointer !important;
background: var(--muted) !important;
color: var(--foreground) !important;
border-color: var(--border) !important;
}
/* OverlayScrollbars theme */ /* OverlayScrollbars theme */
.os-scrollbar { .os-scrollbar {
--os-size: 8px; --os-size: 8px;