app icon, toast theming and positioning, rename crate to nomina
2
Cargo.lock
generated
@@ -2206,7 +2206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
|
||||
[[package]]
|
||||
name = "nomina-app"
|
||||
name = "nomina"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[workspace]
|
||||
members = ["crates/nomina-core", "crates/nomina-app"]
|
||||
members = ["crates/nomina-core", "crates/nomina"]
|
||||
resolver = "2"
|
||||
|
||||
|
Before Width: | Height: | Size: 395 B |
|
Before Width: | Height: | Size: 859 B |
|
Before Width: | Height: | Size: 113 B |
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "nomina-app"
|
||||
name = "nomina"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "CC0-1.0"
|
||||
BIN
crates/nomina/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
crates/nomina/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
crates/nomina/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
crates/nomina/icons/icon-512.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 762 B |
BIN
crates/nomina/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 279 KiB |
96
crates/nomina/icons/icon.svg
Normal 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 |
@@ -159,9 +159,9 @@ export function AppShell() {
|
||||
</div>
|
||||
</div>
|
||||
<StatusBar />
|
||||
<Toaster />
|
||||
</div>
|
||||
</PortalContainerProvider>
|
||||
<Toaster />
|
||||
</MotionConfig>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
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() {
|
||||
const theme = useResolvedTheme();
|
||||
return (
|
||||
<Sonner
|
||||
position="bottom-right"
|
||||
theme={theme}
|
||||
position="top-center"
|
||||
closeButton
|
||||
toastOptions={{
|
||||
classNames: {
|
||||
toast: "bg-card text-card-foreground border-border shadow-lg font-sans text-[13px]",
|
||||
title: "font-medium",
|
||||
description: "text-muted-foreground text-[12px]",
|
||||
success: "border-success/30",
|
||||
error: "border-destructive/30",
|
||||
toast: "!border-border !shadow-lg !font-sans !text-[13px] toast-themed",
|
||||
title: "!font-medium",
|
||||
description: "!text-muted-foreground !text-[12px]",
|
||||
success: "!border-success/30",
|
||||
error: "!border-destructive/30",
|
||||
},
|
||||
}}
|
||||
offset={8}
|
||||
offset={64}
|
||||
gap={6}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -414,6 +414,25 @@ button:not([data-no-target-expand])::after,
|
||||
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 */
|
||||
.os-scrollbar {
|
||||
--os-size: 8px;
|
||||
|
||||