From 063da474f90c0f75dda2fb825774c53530c61361 Mon Sep 17 00:00:00 2001 From: boban Date: Sat, 16 May 2026 15:19:17 +0200 Subject: [PATCH] feat(design): refined dark editorial design audit across all views - CSS: metric-num glow, card-shadow depth, card-accent-top treatment, table-row-hover with left accent bar, badge utility, nim-reveal staggered page-load animation, nim-skeleton shimmer, bg-grid, polished scrollbar, tighter letter-spacing on headings - Dashboard: accent-topped metric cards, gradient fill chart, JetBrains Mono tooltips, leading-zero rank numbers, improved top-links table - Links: refined table with tracking-widest thead, badge status pills with dot indicator, blue slug hover on A/B action - QR Codes: type-colored icons, display_type badge, bar-chart empty state SVG - Bio: bars icon, slug with blue highlight, published dot indicator - Analytics: grouped range button pill, progress bar distributions per country/device, nim-reveal stagger, three metric cards with card-accent-top - Topbar: sticky + backdrop-blur, accent-gradient avatar Co-Authored-By: Claude Sonnet 4.6 --- resources/css/app.css | 114 +++++++++- resources/views/components/topbar.blade.php | 16 +- .../livewire/pages/analytics/index.blade.php | 102 ++++++--- .../views/livewire/pages/bio/index.blade.php | 60 +++--- .../pages/dashboard/overview.blade.php | 194 +++++++++++------- .../livewire/pages/links/index.blade.php | 49 ++--- .../livewire/pages/qr-codes/index.blade.php | 81 +++++--- 7 files changed, 413 insertions(+), 203 deletions(-) diff --git a/resources/css/app.css b/resources/css/app.css index 1a041ca..53df06d 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -89,9 +89,116 @@ html { font-size: 14px; } body { font-size: 0.875rem; line-height: 1.5; } -h1 { font-size: 1.5rem; line-height: 2rem; font-weight: 600; } -h2 { font-size: 1.25rem; line-height: 1.75rem; font-weight: 600; } -h3 { font-size: 1.125rem; line-height: 1.5rem; font-weight: 500; } +h1 { font-size: 1.5rem; line-height: 2rem; font-weight: 700; letter-spacing: -0.02em; } +h2 { font-size: 1.25rem; line-height: 1.75rem; font-weight: 600; letter-spacing: -0.015em; } +h3 { font-size: 1.125rem; line-height: 1.5rem; font-weight: 500; letter-spacing: -0.01em; } + +/* Refined scrollbar */ +::-webkit-scrollbar { width: 4px; height: 4px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: var(--color-t3); border-radius: 2px; } +::-webkit-scrollbar-thumb:hover { background: var(--color-t2); } + +/* Text rendering */ +body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } +.font-mono, code, pre { font-variant-numeric: tabular-nums; } + +/* Number glow for metrics */ +.metric-num { + font-family: var(--font-mono); + font-weight: 700; + letter-spacing: -0.03em; + text-shadow: 0 0 24px color-mix(in srgb, var(--color-accent) 30%, transparent); +} + +/* Card depth shadow */ +.card-shadow { + box-shadow: + 0 1px 0 0 rgba(255,255,255,0.04) inset, + 0 -1px 0 0 rgba(0,0,0,0.2) inset, + 0 4px 16px rgba(0,0,0,0.3); +} + +/* Accent-top card — top border is accent gradient */ +.card-accent-top { + position: relative; +} +.card-accent-top::before { + content: ''; + position: absolute; + top: 0; left: 0; right: 0; + height: 1px; + background: linear-gradient(90deg, var(--color-accent) 0%, var(--color-accent-2) 100%); + border-radius: inherit; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +/* Page-load stagger reveal */ +@keyframes nim-fade-up { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} +.nim-reveal { + opacity: 0; + animation: nim-fade-up 0.35s ease forwards; +} +.nim-reveal-1 { animation-delay: 0.05s; } +.nim-reveal-2 { animation-delay: 0.12s; } +.nim-reveal-3 { animation-delay: 0.19s; } +.nim-reveal-4 { animation-delay: 0.26s; } +.nim-reveal-5 { animation-delay: 0.33s; } + +/* Shimmer for loading skeletons */ +@keyframes nim-shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} +.nim-skeleton { + background: linear-gradient(90deg, var(--color-s2) 25%, var(--color-s3) 50%, var(--color-s2) 75%); + background-size: 200% 100%; + animation: nim-shimmer 1.4s infinite; + border-radius: 4px; +} + +/* Subtle grid background for stat sections */ +.bg-grid { + background-image: + linear-gradient(rgba(255,255,255,0.015) 1px, transparent 1px), + linear-gradient(90deg, rgba(255,255,255,0.015) 1px, transparent 1px); + background-size: 24px 24px; +} + +/* Table row hover with left accent bar */ +.table-row-hover { + position: relative; + transition: background 0.12s ease; +} +.table-row-hover::before { + content: ''; + position: absolute; + left: 0; top: 0; bottom: 0; + width: 2px; + background: linear-gradient(180deg, var(--color-accent), var(--color-accent-2)); + transform: scaleY(0); + transition: transform 0.15s ease; + border-radius: 0 2px 2px 0; +} +.table-row-hover:hover::before { + transform: scaleY(1); +} + +/* Pill badge base */ +.badge { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.125rem 0.5rem; + border-radius: 9999px; + font-size: 0.6875rem; + font-weight: 500; + letter-spacing: 0.01em; +} @layer utilities { .bg-accent-gradient { @@ -106,4 +213,5 @@ h3 { font-size: 1.125rem; line-height: 1.5rem; font-weight: 500; } .border-accent-gradient { border-image: linear-gradient(135deg, var(--color-accent), var(--color-accent-2)) 1; } + .tabular-nums { font-variant-numeric: tabular-nums; } } diff --git a/resources/views/components/topbar.blade.php b/resources/views/components/topbar.blade.php index e54233e..3068898 100644 --- a/resources/views/components/topbar.blade.php +++ b/resources/views/components/topbar.blade.php @@ -7,7 +7,7 @@ } @endphp -
+
@@ -56,23 +56,13 @@ -
- - 3 -
+
@endforeach @@ -53,51 +56,82 @@
{{-- Summary metrics --}} -
-
-
{{ strtoupper($range) }} Clicks
-
{{ number_format($totalFiltered) }}
+
+
+
{{ strtoupper($range) }}
+
{{ number_format($totalFiltered) }}
+
filtered clicks
-
-
All-time Clicks
-
{{ number_format($allTime) }}
+
+
All-time
+
{{ number_format($allTime) }}
+
total clicks
-
-
Today
-
{{ number_format($totalToday) }}
+
+
Today
+
{{ number_format($totalToday) }}
+
since midnight
{{-- Top Countries --}} -
-

Top Countries

- @forelse($byCountry as $row) -
- - {{ number_format($row->total) }} + @endif +
+ @forelse($byCountry as $row) + @php $pct = $totalFiltered > 0 ? round(($row->total / $totalFiltered) * 100) : 0; @endphp +
+
+ + {{ number_format($row->total) }} +
+
+
+
@empty -

No data for this period

+
No data for this period
@endforelse
{{-- By Device --}} -
-

By Device

- @forelse($byDevice as $row) -
- - {{ number_format($row->total) }} + @endif +
+ @forelse($byDevice as $row) + @php $pct = $totalFiltered > 0 ? round(($row->total / $totalFiltered) * 100) : 0; @endphp +
+
+ + {{ number_format($row->total) }} +
+
+
+
@empty -

No data for this period

+
No data for this period
@endforelse
diff --git a/resources/views/livewire/pages/bio/index.blade.php b/resources/views/livewire/pages/bio/index.blade.php index 668d115..af32b57 100644 --- a/resources/views/livewire/pages/bio/index.blade.php +++ b/resources/views/livewire/pages/bio/index.blade.php @@ -1,54 +1,62 @@
@php $ws = current_workspace(); @endphp -
-

Link-in-Bio

+
+
+

Link-in-Bio

+

{{ $bioPages->total() }} pages

+
@if($ws) @endif
-
+
@forelse($bioPages as $page) -
-
- - - + @php $title = is_array($page->title) ? ($page->title['en'] ?? $page->slug) : ($page->title ?? $page->slug); @endphp +
+
+
+
-
{{ is_array($page->title) ? ($page->title['en'] ?? $page->slug) : ($page->title ?? $page->slug) }}
-
nimu.li/{{ $page->slug }}
+
{{ $title }}
+
nimu.li/{{ $page->slug }}
- + + + @if($page->is_published) + + @endif {{ $page->is_published ? 'Published' : 'Draft' }} -
+ +
+ class="text-t2 text-xs hover:text-t1 transition-colors">Edit + class="text-t3 text-xs hover:text-red transition-colors">Delete
@empty -
-
- - - -
-

No bio pages yet

-

Create a beautiful link-in-bio page for Instagram, TikTok and more.

+
+ + + + +

No bio pages yet

+

Create a link-in-bio page for Instagram, TikTok and more.

@if($ws) @endif
diff --git a/resources/views/livewire/pages/dashboard/overview.blade.php b/resources/views/livewire/pages/dashboard/overview.blade.php index c492698..5bec026 100644 --- a/resources/views/livewire/pages/dashboard/overview.blade.php +++ b/resources/views/livewire/pages/dashboard/overview.blade.php @@ -1,54 +1,60 @@
- {{-- Quick Actions --}} - - - {{-- Hero Metrics --}} -
- {{-- Clicks Today --}} -
-
Clicks Today
-
{{ number_format($today) }}
-
since midnight
+ {{-- Page header --}} +
+
+

Overview

+

{{ now()->format('l, F j') }}

- - {{-- Last 7 Days --}} -
-
Last 7 Days
-
{{ number_format($last7) }}
-
rolling 7-day window
-
- - {{-- Last 30 Days --}} -
-
Last 30 Days
-
{{ number_format($last30) }}
-
rolling 30-day window
-
- - {{-- Total Links --}} -
-
Total Links
-
{{ number_format($totalLinks) }}
-
active links
+
- {{-- 30-Day Chart --}} + {{-- Metric cards --}} +
+
+
Today
+
{{ number_format($today) }}
+
clicks since midnight
+
+ +
+
7 Days
+
{{ number_format($last7) }}
+
rolling window
+
+ +
+
30 Days
+
{{ number_format($last30) }}
+
rolling window
+
+ +
+
Links
+
{{ number_format($totalLinks) }}
+
active links
+
+
+ + {{-- Chart --}}
-

Clicks — Last 30 Days

-
+
+
CLICKS — LAST 30 DAYS
+
+
+
- {{-- Top 5 Links --}} -
-
-

Top Links

+ {{-- Top Links --}} +
+
+
Top Links
+ View all →
- +
- - - - - + + + + + - + @forelse($topLinks as $index => $link) - - + + - - + + @empty - + @endforelse diff --git a/resources/views/livewire/pages/links/index.blade.php b/resources/views/livewire/pages/links/index.blade.php index da0e7d0..60e9e21 100644 --- a/resources/views/livewire/pages/links/index.blade.php +++ b/resources/views/livewire/pages/links/index.blade.php @@ -1,8 +1,8 @@
@php $ws = current_workspace(); @endphp {{-- Header --}} -
-

Links

+
+

Links

@if($ws)
#SlugTitleClicks
#SlugClicks
{{ $index + 1 }}
{{ str_pad($index + 1, 2, '0', STR_PAD_LEFT) }} - {{ $link->slug }} - - {{ $link->title ?: '—' }} - - {{ number_format($link->total_clicks) }} +
+ nimu.li/{{ $link->slug }} +
{{ number_format($link->total_clicks) }}
No links yet. +
+ + + + +

No links yet — create your first one

+
+
- - - - - - - - + + + + + + + + - + @forelse($links as $link) - + {{-- Slug + title --}} {{-- Target URL --}} - @@ -70,7 +70,7 @@ @if(!empty($link->tags))
@foreach($link->tags as $tag) - {{ $tag }} + {{ $tag }} @endforeach
@else @@ -79,27 +79,30 @@ {{-- Clicks --}} - {{-- Status Badge --}} {{-- Actions --}}
LinkTargetClicksStatus
LinkTargetClicksStatus
nimu.li/ - {{ $link->slug }} + {{ $link->slug }}
@if($link->title)
{{ $link->title }}
@@ -61,7 +61,7 @@
+ {{ $link->target_url }} + {{ number_format($link->clicks_count ?? 0) }} @if($link->status === 'active') - active + + + active + @elseif($link->status === 'expired') - expired + expired @else - {{ $link->status }} + {{ $link->status }} @endif -
+
@@ -110,7 +113,7 @@
diff --git a/resources/views/livewire/pages/qr-codes/index.blade.php b/resources/views/livewire/pages/qr-codes/index.blade.php index a0d1b88..f593c7c 100644 --- a/resources/views/livewire/pages/qr-codes/index.blade.php +++ b/resources/views/livewire/pages/qr-codes/index.blade.php @@ -1,54 +1,79 @@
@php $ws = current_workspace(); @endphp -
-

QR Codes

+
+
+

QR Codes

+

{{ $qrCodes->total() }} total

+
@if($ws) @endif
-
+ @if($search ?? false) +
+ +
+ @endif + +
@forelse($qrCodes as $qr) -
-
- - - +
+ {{-- QR type icon --}} +
+ @php + $displayType = $qr->payload['display_type'] ?? $qr->type; + $typeColors = ['url' => 'text-blue', 'vcard' => 'text-green', 'wifi' => 'text-amber', 'email' => 'text-purple', 'default' => 'text-t3']; + $typeColor = $typeColors[$displayType] ?? $typeColors['default']; + @endphp +
+
-
{{ $qr->label ?: $qr->ulid }}
-
{{ $qr->type }} · {{ $qr->payload['url'] ?? '' }}
+
{{ $qr->payload['label'] ?? ($qr->label ?? $qr->ulid) }}
+
{{ $qr->payload['data'] ?? ($qr->payload['url'] ?? '') }}
- - {{ $qr->is_dynamic ? 'Dynamic' : 'Static' }} - -
+ +
+ {{ strtoupper($qr->payload['display_type'] ?? $qr->type) }} + + {{ $qr->is_dynamic ? 'Dynamic' : 'Static' }} + +
+ +
+ class="text-t2 text-xs hover:text-t1 transition-colors">Edit + class="text-t3 text-xs hover:text-red transition-colors">Delete
@empty -
-
- - - -
-

No QR Codes yet

-

Create QR codes for URLs, vCards, WiFi and more.

+
+ + + + + + + + + +

No QR codes yet

+

Create QR codes for URLs, vCards, WiFi and more.

@if($ws) @endif