Polish app branding with shared brand components
Extract the shield mark into reusable brand-icon/brand-mark components and use them in the app shell, auth layout, and marketing nav/footer. Align the palette on emerald (badges, selection, dark zinc-950 body), and add a subtle grid/glow backdrop to the app layout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ac340d125c
commit
a3b3d7d029
20 changed files with 100 additions and 70 deletions
|
|
@ -13,7 +13,7 @@ enum ExpiryStatus: string
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
self::Expired => 'red',
|
self::Expired => 'red',
|
||||||
self::ExpiringSoon => 'amber',
|
self::ExpiringSoon => 'amber',
|
||||||
self::Valid => 'green',
|
self::Valid => 'emerald',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,20 @@
|
||||||
@theme {
|
@theme {
|
||||||
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
|
||||||
--color-zinc-50: #fafafa;
|
--color-zinc-50: #f8fafc;
|
||||||
--color-zinc-100: #f5f5f5;
|
--color-zinc-100: #f1f5f9;
|
||||||
--color-zinc-200: #e5e5e5;
|
--color-zinc-200: #e2e8f0;
|
||||||
--color-zinc-300: #d4d4d4;
|
--color-zinc-300: #cbd5e1;
|
||||||
--color-zinc-400: #a3a3a3;
|
--color-zinc-400: #94a3b8;
|
||||||
--color-zinc-500: #737373;
|
--color-zinc-500: #64748b;
|
||||||
--color-zinc-600: #525252;
|
--color-zinc-600: #475569;
|
||||||
--color-zinc-700: #404040;
|
--color-zinc-700: #334155;
|
||||||
--color-zinc-800: #262626;
|
--color-zinc-800: #1e293b;
|
||||||
--color-zinc-900: #171717;
|
--color-zinc-900: #0f172a;
|
||||||
--color-zinc-950: #0a0a0a;
|
--color-zinc-950: #020617;
|
||||||
|
|
||||||
--color-accent: var(--color-neutral-800);
|
--color-accent: var(--color-emerald-600);
|
||||||
--color-accent-content: var(--color-neutral-800);
|
--color-accent-content: var(--color-emerald-600);
|
||||||
--color-accent-foreground: var(--color-white);
|
--color-accent-foreground: var(--color-white);
|
||||||
|
|
||||||
/* Marketing pages */
|
/* Marketing pages */
|
||||||
|
|
@ -92,9 +92,9 @@
|
||||||
|
|
||||||
@layer theme {
|
@layer theme {
|
||||||
.dark {
|
.dark {
|
||||||
--color-accent: var(--color-white);
|
--color-accent: var(--color-emerald-500);
|
||||||
--color-accent-content: var(--color-white);
|
--color-accent-content: var(--color-emerald-400);
|
||||||
--color-accent-foreground: var(--color-neutral-800);
|
--color-accent-foreground: var(--color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@
|
||||||
input:focus[data-flux-control],
|
input:focus[data-flux-control],
|
||||||
textarea:focus[data-flux-control],
|
textarea:focus[data-flux-control],
|
||||||
select:focus[data-flux-control] {
|
select:focus[data-flux-control] {
|
||||||
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
|
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-white dark:ring-offset-slate-900;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \[:where(&)\]:size-4 {
|
/* \[:where(&)\]:size-4 {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@
|
||||||
])
|
])
|
||||||
|
|
||||||
@if($sidebar)
|
@if($sidebar)
|
||||||
<flux:sidebar.brand name="Laravel Starter Kit" {{ $attributes }}>
|
<flux:sidebar.brand name="Certified" {{ $attributes }}>
|
||||||
<x-slot name="logo" class="flex aspect-square size-8 items-center justify-center rounded-md bg-accent-content text-accent-foreground">
|
<x-slot name="logo" class="flex aspect-square size-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600">
|
||||||
<x-app-logo-icon class="size-5 fill-current text-white dark:text-black" />
|
<x-brand-icon class="size-4.5 text-white" />
|
||||||
</x-slot>
|
</x-slot>
|
||||||
</flux:sidebar.brand>
|
</flux:sidebar.brand>
|
||||||
@else
|
@else
|
||||||
<flux:brand name="Laravel Starter Kit" {{ $attributes }}>
|
<flux:brand name="Certified" {{ $attributes }}>
|
||||||
<x-slot name="logo" class="flex aspect-square size-8 items-center justify-center rounded-md bg-accent-content text-accent-foreground">
|
<x-slot name="logo" class="flex aspect-square size-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600">
|
||||||
<x-app-logo-icon class="size-5 fill-current text-white dark:text-black" />
|
<x-brand-icon class="size-4.5 text-white" />
|
||||||
</x-slot>
|
</x-slot>
|
||||||
</flux:brand>
|
</flux:brand>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
])
|
])
|
||||||
|
|
||||||
@if ($status)
|
@if ($status)
|
||||||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600']) }}>
|
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-emerald-600']) }}>
|
||||||
{{ $status }}
|
{{ $status }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
4
resources/views/components/brand-icon.blade.php
Normal file
4
resources/views/components/brand-icon.blade.php
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{{-- Certified shield-check mark --}}
|
||||||
|
<svg {{ $attributes }} fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z" />
|
||||||
|
</svg>
|
||||||
16
resources/views/components/brand-mark.blade.php
Normal file
16
resources/views/components/brand-mark.blade.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{{-- Certified gradient logo tile --}}
|
||||||
|
@props([
|
||||||
|
'size' => 'md', // sm | md | lg
|
||||||
|
])
|
||||||
|
|
||||||
|
@php
|
||||||
|
[$tile, $icon] = match ($size) {
|
||||||
|
'sm' => ['size-8 rounded-lg', 'size-4.5'],
|
||||||
|
'lg' => ['size-12 rounded-2xl shadow-lg shadow-emerald-500/25', 'size-7'],
|
||||||
|
default => ['size-9 rounded-xl shadow-lg shadow-emerald-500/25', 'size-5'],
|
||||||
|
};
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<span {{ $attributes->class(['flex items-center justify-center bg-gradient-to-br from-emerald-500 to-teal-600', $tile]) }}>
|
||||||
|
<x-brand-icon class="{{ $icon }} text-white" />
|
||||||
|
</span>
|
||||||
|
|
@ -82,7 +82,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template x-if="supported && showForm">
|
<template x-if="supported && showForm">
|
||||||
<div class="space-y-4 rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50 p-4">
|
<div class="space-y-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50 p-4">
|
||||||
<flux:input
|
<flux:input
|
||||||
label="{{ __('Passkey name') }}"
|
label="{{ __('Passkey name') }}"
|
||||||
x-model="name"
|
x-model="name"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
<x-layouts::app.sidebar :title="$title ?? null">
|
<x-layouts::app.sidebar :title="$title ?? null">
|
||||||
<flux:main>
|
<flux:main class="relative isolate">
|
||||||
|
<div aria-hidden="true" class="pointer-events-none absolute inset-x-0 top-0 -z-10 h-[24rem] bg-grid-slate opacity-60 [mask-image:radial-gradient(ellipse_60%_40%_at_50%_0%,black,transparent)]"></div>
|
||||||
|
<div aria-hidden="true" class="pointer-events-none absolute -top-24 right-[10%] -z-10 h-64 w-96 rounded-full bg-gradient-to-br from-emerald-400/15 via-teal-400/10 to-transparent blur-3xl"></div>
|
||||||
|
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</flux:main>
|
</flux:main>
|
||||||
</x-layouts::app.sidebar>
|
</x-layouts::app.sidebar>
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,23 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
<head>
|
<head>
|
||||||
@include('partials.head')
|
@include('partials.head')
|
||||||
</head>
|
</head>
|
||||||
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
|
<body class="min-h-screen bg-slate-50 antialiased selection:bg-emerald-200 selection:text-emerald-950 dark:bg-slate-950 dark:selection:bg-emerald-900 dark:selection:text-emerald-100">
|
||||||
|
<div aria-hidden="true" class="pointer-events-none fixed inset-x-0 top-0 h-[32rem] bg-grid-slate [mask-image:radial-gradient(ellipse_70%_60%_at_50%_0%,black,transparent)]"></div>
|
||||||
|
<div aria-hidden="true" class="pointer-events-none fixed -top-32 left-1/2 h-80 w-[36rem] -translate-x-1/2 rounded-full bg-gradient-to-br from-emerald-400/20 via-teal-400/10 to-transparent blur-3xl"></div>
|
||||||
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
<div class="absolute top-4 right-4 z-10">
|
||||||
<x-language-switcher />
|
<x-language-switcher />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
|
<div class="relative flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
|
||||||
<div class="flex w-full max-w-sm flex-col gap-2">
|
<div class="flex w-full max-w-sm flex-col gap-6">
|
||||||
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
|
<a href="{{ route('home') }}" class="group flex flex-col items-center gap-3 font-medium" wire:navigate>
|
||||||
<span class="flex h-9 w-9 mb-1 items-center justify-center rounded-md">
|
<x-brand-mark size="lg" class="transition-transform duration-300 group-hover:scale-105 group-hover:-rotate-3" />
|
||||||
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
|
<span class="text-lg font-semibold tracking-tight text-slate-900 dark:text-white">Certified</span>
|
||||||
</span>
|
|
||||||
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
|
|
||||||
</a>
|
</a>
|
||||||
<div class="flex flex-col gap-6">
|
<div class="flex flex-col gap-6 rounded-2xl border border-slate-200 bg-white p-8 shadow-xl shadow-slate-900/5 dark:border-slate-800 dark:bg-slate-900">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,7 @@
|
||||||
<div class="grid gap-10 md:grid-cols-4">
|
<div class="grid gap-10 md:grid-cols-4">
|
||||||
<div class="md:col-span-2">
|
<div class="md:col-span-2">
|
||||||
<a href="{{ route('home') }}" class="flex items-center gap-2.5">
|
<a href="{{ route('home') }}" class="flex items-center gap-2.5">
|
||||||
<span class="flex size-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600">
|
<x-brand-mark size="sm" />
|
||||||
<svg class="size-4.5 text-white" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span class="text-base font-semibold tracking-tight text-slate-900 dark:text-white">Certified</span>
|
<span class="text-base font-semibold tracking-tight text-slate-900 dark:text-white">Certified</span>
|
||||||
</a>
|
</a>
|
||||||
<p class="mt-4 max-w-sm text-sm leading-relaxed text-slate-500 dark:text-slate-400">
|
<p class="mt-4 max-w-sm text-sm leading-relaxed text-slate-500 dark:text-slate-400">
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,7 @@
|
||||||
|
|
||||||
{{-- Logo --}}
|
{{-- Logo --}}
|
||||||
<a href="{{ route('home') }}" class="group flex items-center gap-2.5" aria-label="Certified — home">
|
<a href="{{ route('home') }}" class="group flex items-center gap-2.5" aria-label="Certified — home">
|
||||||
<span class="flex size-9 items-center justify-center rounded-xl bg-gradient-to-br from-emerald-500 to-teal-600 shadow-lg shadow-emerald-500/25 transition-transform duration-300 group-hover:scale-105 group-hover:-rotate-3">
|
<x-brand-mark class="transition-transform duration-300 group-hover:scale-105 group-hover:-rotate-3" />
|
||||||
<svg class="size-5 text-white" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span class="text-lg font-semibold tracking-tight text-slate-900 dark:text-white">Certified</span>
|
<span class="text-lg font-semibold tracking-tight text-slate-900 dark:text-white">Certified</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
</flux:text>
|
</flux:text>
|
||||||
|
|
||||||
@if (session('status') == 'verification-link-sent')
|
@if (session('status') == 'verification-link-sent')
|
||||||
<flux:text class="text-center font-medium !dark:text-green-400 !text-green-600">
|
<flux:text class="text-center font-medium !dark:text-emerald-400 !text-emerald-600">
|
||||||
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
|
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
|
||||||
</flux:text>
|
</flux:text>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -63,12 +63,15 @@ new #[Title('Categories')] class extends Component {
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@if ($this->categories->isEmpty())
|
@if ($this->categories->isEmpty())
|
||||||
<flux:card class="flex flex-col items-center gap-2 py-12 text-center">
|
<flux:card class="flex flex-col items-center gap-3 rounded-2xl py-12 text-center">
|
||||||
<flux:icon.tag class="size-8 text-zinc-400" />
|
<span class="flex size-10 items-center justify-center rounded-xl bg-emerald-100 text-emerald-600 dark:bg-emerald-500/15 dark:text-emerald-400">
|
||||||
|
<flux:icon.tag class="size-6" />
|
||||||
|
</span>
|
||||||
<flux:heading size="lg">{{ __('No categories yet') }}</flux:heading>
|
<flux:heading size="lg">{{ __('No categories yet') }}</flux:heading>
|
||||||
<flux:text>{{ __('Create your first category to organize your certificates.') }}</flux:text>
|
<flux:text>{{ __('Create your first category to organize your certificates.') }}</flux:text>
|
||||||
</flux:card>
|
</flux:card>
|
||||||
@else
|
@else
|
||||||
|
<div class="max-w-3xl overflow-hidden rounded-2xl border border-zinc-200 bg-white px-4 shadow-sm sm:px-6 dark:border-zinc-800 dark:bg-zinc-900">
|
||||||
<flux:table>
|
<flux:table>
|
||||||
<flux:table.columns>
|
<flux:table.columns>
|
||||||
<flux:table.column>{{ __('Name') }}</flux:table.column>
|
<flux:table.column>{{ __('Name') }}</flux:table.column>
|
||||||
|
|
@ -115,5 +118,6 @@ new #[Title('Categories')] class extends Component {
|
||||||
@endforeach
|
@endforeach
|
||||||
</flux:table.rows>
|
</flux:table.rows>
|
||||||
</flux:table>
|
</flux:table>
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,14 @@ new #[Title('Add certificate')] class extends Component {
|
||||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2 lg:items-start">
|
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2 lg:items-start">
|
||||||
{{-- Left: live document preview (client-side, before upload completes) --}}
|
{{-- Left: live document preview (client-side, before upload completes) --}}
|
||||||
<div class="lg:sticky lg:top-6">
|
<div class="lg:sticky lg:top-6">
|
||||||
<div class="relative flex h-[60vh] items-center justify-center overflow-hidden rounded-xl border border-zinc-200 bg-zinc-50 lg:h-[calc(100vh-9rem)] dark:border-zinc-700 dark:bg-zinc-800/40">
|
<div
|
||||||
<div x-show="! previewUrl" class="flex flex-col items-center gap-2 px-6 text-center text-zinc-400">
|
class="relative flex h-[60vh] items-center justify-center overflow-hidden rounded-2xl border bg-zinc-50 transition-colors duration-200 lg:h-[calc(100vh-9rem)] dark:bg-zinc-800/40"
|
||||||
<flux:icon.document-arrow-up class="size-10" />
|
:class="previewUrl ? 'border-zinc-200 dark:border-zinc-700' : 'border-2 border-dashed border-emerald-400/60 dark:border-emerald-500/40'"
|
||||||
|
>
|
||||||
|
<div x-show="! previewUrl" class="flex flex-col items-center gap-3 px-6 text-center text-zinc-400">
|
||||||
|
<span class="flex size-12 items-center justify-center rounded-2xl bg-emerald-100 text-emerald-600 dark:bg-emerald-500/15 dark:text-emerald-400">
|
||||||
|
<flux:icon.document-arrow-up class="size-6" />
|
||||||
|
</span>
|
||||||
<flux:text>{{ __('Select a document to preview it here.') }}</flux:text>
|
<flux:text>{{ __('Select a document to preview it here.') }}</flux:text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ new #[Title('Edit certificate')] class extends Component {
|
||||||
<flux:text class="mt-1">{{ __('Update the details or replace the stored document.') }}</flux:text>
|
<flux:text class="mt-1">{{ __('Update the details or replace the stored document.') }}</flux:text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form wire:submit="save" class="space-y-6">
|
<form wire:submit="save" class="space-y-6 rounded-2xl border border-zinc-200 bg-white p-6 shadow-sm sm:p-8 dark:border-zinc-800 dark:bg-zinc-900">
|
||||||
<flux:input wire:model="title" :label="__('Title')" required />
|
<flux:input wire:model="title" :label="__('Title')" required />
|
||||||
|
|
||||||
<flux:select wire:model="category_id" :label="__('Category')">
|
<flux:select wire:model="category_id" :label="__('Category')">
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ new class extends Component {
|
||||||
}; ?>
|
}; ?>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="py-6 space-y-6 border shadow-sm rounded-xl border-zinc-200 dark:border-white/10"
|
class="py-6 space-y-6 border shadow-sm rounded-2xl border-zinc-200 dark:border-white/10"
|
||||||
wire:cloak
|
wire:cloak
|
||||||
x-data="{ showRecoveryCodes: false }"
|
x-data="{ showRecoveryCodes: false }"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ new #[Title('Profile settings')] class extends Component {
|
||||||
</flux:text>
|
</flux:text>
|
||||||
|
|
||||||
@if (session('status') === 'verification-link-sent')
|
@if (session('status') === 'verification-link-sent')
|
||||||
<flux:text class="mt-2 font-medium !dark:text-green-400 !text-green-600">
|
<flux:text class="mt-2 font-medium !dark:text-emerald-400 !text-emerald-600">
|
||||||
{{ __('A new verification link has been sent to your email address.') }}
|
{{ __('A new verification link has been sent to your email address.') }}
|
||||||
</flux:text>
|
</flux:text>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ new #[Title('Security settings')] class extends Component {
|
||||||
<flux:subheading>{{ __('Manage your passkeys for passwordless sign-in') }}</flux:subheading>
|
<flux:subheading>{{ __('Manage your passkeys for passwordless sign-in') }}</flux:subheading>
|
||||||
|
|
||||||
<div class="mt-6 flex flex-col w-full mx-auto space-y-6 text-sm" wire:cloak>
|
<div class="mt-6 flex flex-col w-full mx-auto space-y-6 text-sm" wire:cloak>
|
||||||
<div class="border rounded-lg border-zinc-200 dark:border-zinc-700 overflow-hidden">
|
<div class="border rounded-2xl border-zinc-200 dark:border-zinc-700 overflow-hidden">
|
||||||
@forelse ($passkeys as $passkey)
|
@forelse ($passkeys as $passkey)
|
||||||
<div class="flex items-center justify-between p-4 {{ ! $loop->last ? 'border-b border-zinc-200 dark:border-zinc-700' : '' }}">
|
<div class="flex items-center justify-between p-4 {{ ! $loop->last ? 'border-b border-zinc-200 dark:border-zinc-700' : '' }}">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
|
|
|
||||||
|
|
@ -298,7 +298,7 @@ new class extends Component {
|
||||||
<flux:icon.check
|
<flux:icon.check
|
||||||
x-show="copied"
|
x-show="copied"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
class="text-green-500"
|
class="text-emerald-500"
|
||||||
></flux:icon>
|
></flux:icon>
|
||||||
</button>
|
</button>
|
||||||
@endempty
|
@endempty
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,11 @@ new #[Title('Dashboard')] class extends Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($this->stats['total'] === 0)
|
@if ($this->stats['total'] === 0)
|
||||||
<flux:card class="flex flex-col items-center gap-3 py-16 text-center">
|
<flux:card class="flex flex-col items-center gap-3 rounded-2xl py-16 text-center">
|
||||||
<flux:icon.shield-check class="size-10 text-zinc-400" />
|
<span class="inline-flex items-center gap-2 rounded-full border border-emerald-200 bg-emerald-50 px-4 py-1.5 text-sm font-medium text-emerald-700 dark:border-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-400">
|
||||||
|
{{ __('Get started') }}
|
||||||
|
</span>
|
||||||
|
<x-brand-mark size="lg" class="mt-2" />
|
||||||
<flux:heading size="lg">{{ __('No certificates yet') }}</flux:heading>
|
<flux:heading size="lg">{{ __('No certificates yet') }}</flux:heading>
|
||||||
<flux:text class="max-w-sm">
|
<flux:text class="max-w-sm">
|
||||||
{{ __('Upload your first certificate to start tracking issue dates, expiry, and reminders.') }}
|
{{ __('Upload your first certificate to start tracking issue dates, expiry, and reminders.') }}
|
||||||
|
|
@ -102,18 +105,20 @@ new #[Title('Dashboard')] class extends Component {
|
||||||
<div class="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
<div class="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
||||||
@php
|
@php
|
||||||
$tiles = [
|
$tiles = [
|
||||||
['label' => __('Total'), 'value' => $this->stats['total'], 'icon' => 'rectangle-stack', 'class' => 'text-zinc-800 dark:text-white'],
|
['label' => __('Total'), 'value' => $this->stats['total'], 'icon' => 'rectangle-stack', 'class' => 'text-zinc-800 dark:text-white', 'tile' => 'bg-gradient-to-br from-emerald-500 to-teal-600 text-white shadow-md shadow-emerald-500/25'],
|
||||||
['label' => __('Valid'), 'value' => $this->stats['valid'], 'icon' => 'check-badge', 'class' => 'text-green-600 dark:text-green-400'],
|
['label' => __('Valid'), 'value' => $this->stats['valid'], 'icon' => 'check-badge', 'class' => 'text-emerald-600 dark:text-emerald-400', 'tile' => 'bg-emerald-50 text-emerald-600 dark:bg-emerald-500/10 dark:text-emerald-400'],
|
||||||
['label' => __('Expiring soon'), 'value' => $this->stats['expiringSoon'], 'icon' => 'clock', 'class' => 'text-amber-600 dark:text-amber-400'],
|
['label' => __('Expiring soon'), 'value' => $this->stats['expiringSoon'], 'icon' => 'clock', 'class' => 'text-amber-600 dark:text-amber-400', 'tile' => 'bg-amber-50 text-amber-600 dark:bg-amber-500/10 dark:text-amber-400'],
|
||||||
['label' => __('Expired'), 'value' => $this->stats['expired'], 'icon' => 'exclamation-triangle', 'class' => 'text-red-600 dark:text-red-400'],
|
['label' => __('Expired'), 'value' => $this->stats['expired'], 'icon' => 'exclamation-triangle', 'class' => 'text-red-600 dark:text-red-400', 'tile' => 'bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400'],
|
||||||
];
|
];
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@foreach ($tiles as $tile)
|
@foreach ($tiles as $tile)
|
||||||
<flux:card class="flex flex-col gap-2">
|
<flux:card class="flex flex-col gap-2 rounded-2xl transition-all duration-300 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-emerald-500/10 dark:hover:shadow-black/30">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<flux:text class="text-sm">{{ $tile['label'] }}</flux:text>
|
<flux:text class="text-sm">{{ $tile['label'] }}</flux:text>
|
||||||
<flux:icon :name="$tile['icon']" class="size-5 text-zinc-400" />
|
<span @class(['flex size-9 items-center justify-center rounded-xl', $tile['tile']])>
|
||||||
|
<flux:icon :name="$tile['icon']" class="size-5" />
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<flux:heading size="xl" @class(['text-3xl font-semibold', $tile['class']])>{{ $tile['value'] }}</flux:heading>
|
<flux:heading size="xl" @class(['text-3xl font-semibold', $tile['class']])>{{ $tile['value'] }}</flux:heading>
|
||||||
</flux:card>
|
</flux:card>
|
||||||
|
|
@ -122,7 +127,7 @@ new #[Title('Dashboard')] class extends Component {
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
||||||
{{-- Needs attention --}}
|
{{-- Needs attention --}}
|
||||||
<flux:card class="lg:col-span-2">
|
<flux:card class="rounded-2xl lg:col-span-2">
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<flux:heading size="lg">{{ __('Needs attention') }}</flux:heading>
|
<flux:heading size="lg">{{ __('Needs attention') }}</flux:heading>
|
||||||
<flux:link :href="route('certificates.index')" wire:navigate variant="subtle">{{ __('View all') }}</flux:link>
|
<flux:link :href="route('certificates.index')" wire:navigate variant="subtle">{{ __('View all') }}</flux:link>
|
||||||
|
|
@ -130,7 +135,7 @@ new #[Title('Dashboard')] class extends Component {
|
||||||
|
|
||||||
@if ($this->attention->isEmpty())
|
@if ($this->attention->isEmpty())
|
||||||
<div class="flex flex-col items-center gap-2 py-8 text-center">
|
<div class="flex flex-col items-center gap-2 py-8 text-center">
|
||||||
<flux:icon.check-badge class="size-8 text-green-500" />
|
<flux:icon.check-badge class="size-8 text-emerald-500" />
|
||||||
<flux:text>{{ __('Nothing needs attention. All your certificates are up to date.') }}</flux:text>
|
<flux:text>{{ __('Nothing needs attention. All your certificates are up to date.') }}</flux:text>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
|
|
@ -161,7 +166,7 @@ new #[Title('Dashboard')] class extends Component {
|
||||||
|
|
||||||
<div class="flex flex-col gap-6">
|
<div class="flex flex-col gap-6">
|
||||||
{{-- By category --}}
|
{{-- By category --}}
|
||||||
<flux:card>
|
<flux:card class="rounded-2xl">
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<flux:heading size="lg">{{ __('By category') }}</flux:heading>
|
<flux:heading size="lg">{{ __('By category') }}</flux:heading>
|
||||||
<flux:link :href="route('categories.index')" wire:navigate variant="subtle">{{ __('Manage') }}</flux:link>
|
<flux:link :href="route('categories.index')" wire:navigate variant="subtle">{{ __('Manage') }}</flux:link>
|
||||||
|
|
@ -182,7 +187,7 @@ new #[Title('Dashboard')] class extends Component {
|
||||||
</flux:card>
|
</flux:card>
|
||||||
|
|
||||||
{{-- Recently added --}}
|
{{-- Recently added --}}
|
||||||
<flux:card>
|
<flux:card class="rounded-2xl">
|
||||||
<flux:heading size="lg" class="mb-4">{{ __('Recently added') }}</flux:heading>
|
<flux:heading size="lg" class="mb-4">{{ __('Recently added') }}</flux:heading>
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
@foreach ($this->recent as $certificate)
|
@foreach ($this->recent as $certificate)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue