Unify primary buttons with gradient pill design across Ladill Mini.
Deploy Ladill Mini / deploy (push) Successful in 33s

Add shared btn-primary components and plus icons on create/new actions for a consistent Ladill UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-06-08 22:40:40 +00:00
co-authored by Cursor
parent 7ffa44b128
commit b203774cc6
28 changed files with 127 additions and 34 deletions
+55
View File
@@ -104,6 +104,61 @@ html.qr-mobile-page body {
width: calc(66.666667% - 0.5rem);
}
@layer components {
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
border-radius: 9999px;
background-image: linear-gradient(to right, rgb(79 70 229), rgb(124 58 237));
padding: 0.5rem 1rem;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #fff;
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
transition: filter 0.15s ease;
}
.btn-primary:hover {
filter: brightness(0.92);
}
.btn-primary:disabled {
opacity: 0.6;
pointer-events: none;
}
.btn-primary-sm {
padding: 0.375rem 0.75rem;
font-size: 0.75rem;
line-height: 1rem;
}
.btn-primary-lg {
padding: 0.625rem 1.25rem;
}
.btn-fab {
display: inline-flex;
height: 2.75rem;
width: 2.75rem;
align-items: center;
justify-content: center;
border-radius: 9999px;
background-image: linear-gradient(to right, rgb(79 70 229), rgb(124 58 237));
color: #fff;
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
transition: filter 0.15s ease;
}
.btn-fab:hover {
filter: brightness(0.92);
}
}
@media (min-width: 640px) {
.mobile-stats-card {
width: auto;
@@ -0,0 +1,17 @@
@props([
'href' => null,
'type' => 'button',
])
@php
$tag = $href ? 'a' : 'button';
@endphp
<{{ $tag }}
@if ($href) href="{{ $href }}" @endif
@if ($tag === 'button') type="{{ $type }}" @endif
{{ $attributes->class(['btn-primary']) }}
>
<svg class="h-4 w-4 shrink-0" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
{{ $slot }}
</{{ $tag }}>
@@ -0,0 +1,16 @@
@props([
'href' => null,
'type' => 'button',
])
@php
$tag = $href ? 'a' : 'button';
@endphp
<{{ $tag }}
@if ($href) href="{{ $href }}" @endif
@if ($tag === 'button') type="{{ $type }}" @endif
{{ $attributes->class(['btn-primary']) }}
>
{{ $slot }}
</{{ $tag }}>
@@ -113,7 +113,7 @@
Cancel
</button>
<button type="submit" :disabled="loading"
class="w-full rounded-xl bg-indigo-600 px-5 py-2.5 text-sm font-semibold text-white hover:bg-indigo-700 disabled:opacity-60 sm:w-auto">
class="btn-primary w-full sm:w-auto">
<span x-text="loading ? 'Processing…' : 'Add credits'">Add credits</span>
</button>
</div>
@@ -30,7 +30,7 @@
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@error('name')<p class="mt-1 text-xs text-rose-600">{{ $message }}</p>@enderror
</div>
<button class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Generate token</button>
<button class="btn-primary">Generate token</button>
</form>
</div>
@@ -63,7 +63,7 @@
</select>
@error('mailbox_address')<p class="mt-1 text-xs text-rose-600">{{ $message }}</p>@enderror
</div>
<button class="rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-700">Link mailbox</button>
<button class="btn-primary">Link mailbox</button>
</form>
@endif
</div>
@@ -104,7 +104,7 @@
</label>
</div>
<button class="rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-700">Save settings</button>
<button class="btn-primary">Save settings</button>
</form>
</div>
@endsection
+1 -1
View File
@@ -23,7 +23,7 @@
<option value="admin">Admin</option>
</select>
</div>
<button class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Send invite</button>
<button class="btn-primary">Send invite</button>
</form>
<p class="mt-2 text-[11px] text-slate-400">Admins can manage mailboxes and the team. Members can manage mailboxes. Invitees join by signing in with that email.</p>
</div>
+1 -1
View File
@@ -7,7 +7,7 @@
<h1 class="text-xl font-semibold tracking-tight text-slate-900">Overview</h1>
<p class="mt-0.5 text-sm text-slate-500">Your mailboxes at a glance.</p>
</div>
<a href="{{ route('email.mailboxes.create') }}" class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-indigo-700">New mailbox</a>
<x-btn.create :href="route('email.mailboxes.create')">New mailbox</x-btn.create>
</div>
@if($error)<div class="mt-4 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800">{{ $error }}</div>@endif
@@ -9,7 +9,7 @@
<form method="POST" action="{{ route('email.domains.store') }}" class="mt-5 flex gap-2 rounded-2xl border border-slate-200 bg-white p-2">
@csrf
<input name="domain" required placeholder="yourdomain.com" class="flex-1 rounded-xl border-0 bg-transparent px-3 py-2 text-sm focus:outline-none focus:ring-0">
<button class="rounded-xl bg-indigo-600 px-5 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Add domain</button>
<x-btn.create type="submit">Add domain</x-btn.create>
</form>
@if(!empty($domains))
+1 -1
View File
@@ -40,7 +40,7 @@
</div>
<form method="POST" action="{{ route('email.domains.verify', $domain['id']) }}" class="mt-4">
@csrf
<button class="rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-indigo-700">Verify domain</button>
<button class="btn-primary">Verify domain</button>
<span class="ml-2 text-xs text-slate-400">DNS changes can take time to propagate.</span>
</form>
@else
@@ -86,8 +86,10 @@
</div>
@error('password')<p class="text-xs text-rose-600">{{ $message }}</p>@enderror
<button class="w-full rounded-xl bg-indigo-600 px-4 py-3 text-sm font-semibold text-white hover:bg-indigo-700"
x-text="free ? 'Create free mailbox' : ('Create mailbox — ' + fmt(price) + '/mo')">Create mailbox</button>
<button class="btn-primary w-full btn-primary-lg">
<svg class="h-4 w-4 shrink-0" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
<span x-text="free ? 'Create free mailbox' : ('Create mailbox — ' + fmt(price) + '/mo')">Create mailbox</span>
</button>
</form>
</div>
@endif
@@ -4,7 +4,7 @@
<div class="mx-auto max-w-4xl">
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold tracking-tight text-slate-900">Mailboxes</h1>
<a href="{{ route('email.mailboxes.create') }}" class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">New mailbox</a>
<x-btn.create :href="route('email.mailboxes.create')">New mailbox</x-btn.create>
</div>
@if($error)<div class="mt-4 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800">{{ $error }}</div>@endif
@@ -12,7 +12,7 @@
<div class="mt-6 rounded-2xl border border-dashed border-slate-300 bg-white p-12 text-center">
<p class="text-sm font-semibold text-slate-700">No mailboxes yet</p>
<p class="mx-auto mt-1 max-w-sm text-xs text-slate-400">Verify a domain, then create a mailbox like you@yourdomain.com.</p>
<a href="{{ route('email.mailboxes.create') }}" class="mt-4 inline-block rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Create mailbox</a>
<x-btn.create :href="route('email.mailboxes.create')" class="mt-4">Create mailbox</x-btn.create>
</div>
@else
<div class="mt-6 divide-y divide-slate-100 overflow-hidden rounded-2xl border border-slate-200 bg-white">
@@ -20,7 +20,7 @@
<div class="flex justify-between"><dt class="text-slate-500">IMAP</dt><dd class="font-mono text-slate-800">{{ $host }}:993 (SSL)</dd></div>
<div class="flex justify-between"><dt class="text-slate-500">SMTP</dt><dd class="font-mono text-slate-800">{{ $host }}:587 (STARTTLS)</dd></div>
</dl>
<a href="https://{{ $host }}" class="mt-4 inline-block rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Open Webmail </a>
<a href="https://{{ $host }}" class="btn-primary mt-4">Open Webmail </a>
</div>
@php
@@ -46,7 +46,7 @@
</p>
</div>
@if($quotaMb < $maxMb)
<a href="{{ route('email.mailboxes.upgrade', $mailbox['id']) }}" class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Upgrade</a>
<a href="{{ route('email.mailboxes.upgrade', $mailbox['id']) }}" class="btn-primary">Upgrade</a>
@else
<span class="rounded-lg bg-slate-100 px-3 py-2 text-xs font-medium text-slate-500">Top plan</span>
@endif
@@ -44,7 +44,7 @@
</div>
@error('quota_mb')<p class="mt-1 text-xs text-rose-600">{{ $message }}</p>@enderror
</div>
<button class="w-full rounded-xl bg-indigo-600 px-4 py-3 text-sm font-semibold text-white hover:bg-indigo-700"
<button class="btn-primary w-full btn-primary-lg"
x-text="'Upgrade — ' + fmt(price) + '/mo'">Upgrade</button>
</form>
</div>
@@ -39,7 +39,10 @@
<input type="text" name="branch_label" value="{{ old('branch_label') }}" maxlength="80" placeholder="e.g. Osu branch"
class="mt-1 w-full rounded-xl border-slate-200 text-sm focus:border-indigo-500 focus:ring-indigo-500">
</div>
<button type="submit" class="w-full rounded-xl bg-indigo-600 py-2.5 text-sm font-semibold text-white hover:bg-indigo-700">Create payment QR</button>
<button type="submit" class="btn-primary w-full">
<svg class="h-4 w-4 shrink-0" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
Create payment QR
</button>
</form>
</div>
</x-user-layout>
@@ -6,7 +6,7 @@
<h1 class="text-xl font-semibold text-slate-900">My Payment QR</h1>
<p class="mt-1 text-sm text-slate-500">Static QRs to print or display one per till or branch.</p>
</div>
<a href="{{ route('mini.payment-qrs.create') }}" class="inline-flex rounded-xl bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">New payment QR</a>
<x-btn.create :href="route('mini.payment-qrs.create')">New payment QR</x-btn.create>
</div>
@if(session('success'))
<div class="rounded-xl border border-emerald-100 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">{{ session('success') }}</div>
@@ -61,7 +61,7 @@
<input type="checkbox" name="is_active" value="1" @checked($qrCode->is_active) class="rounded border-slate-300 text-indigo-600">
QR is active (accepts payments)
</label>
<button type="submit" class="rounded-xl bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Save changes</button>
<button type="submit" class="btn-primary">Save changes</button>
</form>
<div class="rounded-2xl border border-red-100 bg-red-50/40 p-6">
+1 -1
View File
@@ -19,7 +19,7 @@
<div class="rounded-2xl border border-amber-100 bg-amber-50/60 px-6 py-4 text-sm text-amber-800">
Withdraw to bank or MoMo from your Ladill account wallet. Ladill Pay integration will add in-app withdrawal history here.
</div>
<a href="{{ $accountWalletUrl }}" class="inline-flex items-center gap-2 rounded-xl bg-indigo-600 px-5 py-2.5 text-sm font-semibold text-white hover:bg-indigo-700">
<a href="{{ $accountWalletUrl }}" class="btn-primary">
Open wallet & withdraw
<span aria-hidden="true"></span>
</a>
+1 -1
View File
@@ -56,7 +56,7 @@
</label>
</div>
<button type="submit" class="rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-700">
<button type="submit" class="btn-primary">
Save settings
</button>
</form>
+1 -1
View File
@@ -96,7 +96,7 @@
<input type="text" x-ref="input" x-model="input" :disabled="loading" placeholder="Message Afia…"
class="flex-1 rounded-xl border border-slate-200 bg-slate-50 px-4 py-2.5 text-sm text-slate-700 placeholder-slate-400 focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
<button type="submit" :disabled="loading || !input.trim()"
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-indigo-600 text-white transition hover:bg-indigo-700 disabled:opacity-40">
class="btn-fab shrink-0 disabled:opacity-40">
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18"/></svg>
</button>
</form>
@@ -34,7 +34,7 @@
<div class="flex items-center justify-center">
<button type="button"
@click="$dispatch('compose-open')"
class="flex h-11 w-11 -translate-y-1 items-center justify-center rounded-full bg-indigo-600 text-white shadow-md ring-4 ring-white transition hover:bg-indigo-700"
class="btn-fab -translate-y-1 ring-4 ring-white shadow-md"
aria-label="Compose">
<svg class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z"/></svg>
</button>
+2 -2
View File
@@ -56,7 +56,7 @@
class="shrink-0">
@csrf
<button type="submit" :disabled="busy"
class="w-full rounded-xl bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-700 disabled:opacity-60 sm:w-auto">
class="btn-primary w-full sm:w-auto">
<span x-text="busy ? 'Sending…' : 'Share with attendees'">Share with attendees</span>
</button>
</form>
@@ -96,7 +96,7 @@
<div class="flex flex-wrap items-center gap-2">
<span x-show="selected.length" x-cloak class="text-xs font-medium text-slate-500"><span x-text="selected.length"></span> selected</span>
<button type="button" x-show="selected.length" x-cloak @click="printSelected()"
class="rounded-xl bg-indigo-600 px-3.5 py-2 text-xs font-semibold text-white hover:bg-indigo-700 transition">Print selected</button>
class="btn-primary btn-primary-sm">Print selected</button>
<button type="button" x-show="selected.length" x-cloak @click="zplSelected()"
class="rounded-xl border border-slate-200 px-3.5 py-2 text-xs font-semibold text-slate-600 hover:bg-slate-50 transition">ZPL selected</button>
<a href="{{ route('events.badges', $qrCode) }}?auto=1" target="_blank"
+4 -4
View File
@@ -212,11 +212,11 @@
Back
</button>
<button type="button" x-show="wizard && step < 3" x-cloak @click="nextStep()"
class="flex-1 rounded-xl bg-indigo-600 py-3 text-sm font-semibold text-white shadow-sm transition hover:bg-indigo-700">
class="btn-primary flex-1">
Continue
</button>
<button type="button" x-show="!wizard || step === 3" @click="wizardSubmit($event)"
class="flex-1 rounded-xl bg-indigo-600 py-3 text-sm font-semibold text-white shadow-sm transition hover:bg-indigo-700">
class="btn-primary flex-1">
{{ $isProgramme ? 'Create programme' : 'Create event' }}
</button>
</div>
@@ -240,11 +240,11 @@
Preview
</button>
<button type="button" x-show="wizard && step < 3" x-cloak @click="nextStep()"
class="flex flex-1 items-center justify-center gap-2 rounded-xl bg-indigo-600 py-2.5 text-sm font-semibold text-white shadow-sm transition hover:bg-indigo-700">
class="btn-primary flex-1">
Continue
</button>
<button type="button" x-show="!wizard || step === 3" @click="wizardSubmit($event)"
class="flex flex-1 items-center justify-center gap-2 rounded-xl bg-indigo-600 py-2.5 text-sm font-semibold text-white shadow-sm transition hover:bg-indigo-700">
class="btn-primary flex-1">
Create
</button>
</div>
+2 -2
View File
@@ -31,8 +31,8 @@
<div class="mt-6">
<button type="button"
@click="goOrTopup($event)"
class="inline-flex items-center gap-2 rounded-xl bg-indigo-600 px-5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-700 transition">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
class="btn-primary">
<svg class="h-4 w-4 shrink-0" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
Create event
</button>
</div>
+1 -1
View File
@@ -7,7 +7,7 @@
<div class="mt-6 rounded-2xl border border-slate-200 bg-white p-6">
<p class="text-xs font-medium uppercase tracking-wide text-slate-400">Current balance</p>
<p class="mt-1 text-3xl font-semibold text-slate-900">{{ $fmt($balanceMinor) }}</p>
<a href="{{ $topupUrl }}" class="mt-4 inline-flex rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Top up wallet</a>
<a href="{{ $topupUrl }}" class="btn-primary mt-4">Top up wallet</a>
</div>
</div>
</x-user-layout>
@@ -28,7 +28,7 @@
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@error('name')<p class="mt-1 text-xs text-rose-600">{{ $message }}</p>@enderror
</div>
<button class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Generate token</button>
<button class="btn-primary">Generate token</button>
</form>
</div>
@@ -247,7 +247,7 @@
</div>
</details>
<button type="submit" class="rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-700">
<button type="submit" class="btn-primary">
Save settings
</button>
</form>
+1 -1
View File
@@ -22,7 +22,7 @@
<option value="admin">Admin</option>
</select>
</div>
<button class="rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700">Send invite</button>
<button class="btn-primary">Send invite</button>
</form>
<p class="mt-2 text-[11px] text-slate-400">Admins can manage QR codes and the team. Members can manage QR codes. Invitees join by signing in with that email.</p>
</div>