Koala logo Design

Buttons

Use the koala-btn tag helper on <button> and <a> elements. Supports colours, variants, and composition with koala-loading.

Filled colours

The default variant is Filled. Each colour serves a specific purpose.

<button koala-btn="Primary">Save changes</button>
<button koala-btn="Secondary">New partner</button>
<button koala-btn="Neutral">Cancel</button>
<button koala-btn="Danger">Delete</button>

Outlined variant

Use koala-btn-variant="Outlined" for destructive triggers like "Cancel quote" or "Disable partner".

<!-- Filled (confirm action) -->
<button koala-btn="Danger">Yes, delete</button>

<!-- Outlined (trigger action) -->
<button koala-btn="Danger" koala-btn-variant="Outlined">Cancel quote</button>

Soft variant (Primary)

Use koala-btn="Primary" koala-btn-variant="Soft" for persistent global CTAs that need to read as branded but visually distinct from solid-green page-primary actions (Accept quote, Save). Currently used by the "Get a quote" button in the top nav so it doesn't compete with whatever page-primary the user is looking at.

<!-- Filled (page primary) -->
<button koala-btn="Primary">Accept quote</button>

<!-- Soft (persistent / global CTA) -->
<button koala-btn="Primary" koala-btn-variant="Soft">Get a quote</button>

Links as buttons

The tag helper works on <a> elements too. Use for navigation actions like "New quote" in page headers.

<a href="/partner/quotes/create" koala-btn="Primary">New quote</a>
<a href="/partner/partners/create" koala-btn="Secondary">New partner</a>
<a href="/partner/quotes" koala-btn="Neutral">Back</a>

Loading state

Add koala-loading to submit buttons. The tag helper auto-adds a spinner SVG, click guard, and disabled styling to prevent double-submits. On click, the button shows a spinner and becomes disabled until the form response completes.

Normal
Loading
<!-- Just add koala-loading — the tag helper handles everything -->
<button type="submit" koala-loading koala-btn="Primary">Save changes</button>
<button type="submit" koala-loading koala-btn="Danger">Confirm</button>

The koala-loading tag helper automatically injects Alpine.js x-data, a click guard to prevent double-submits, opacity and disabled styling while loading, and a spinner SVG that replaces the button text. It also disables every other <button> and <a> inside the same <form> (e.g. Back/Cancel) so users can't double-submit or navigate away mid-submit. State resets when the form response arrives. Exceptions: search buttons, sign out buttons, and instant-action buttons do not need spinners.

With icons

Place a <koala-icon> inside the button as child content. Add gap-2 to the button's class to space the icon from the text.

New quote
<a href="/partner/quotes/create" koala-btn="Primary" class="gap-2">
    <koala-icon name="Plus" size="Small" />
    New quote
</a>

<button koala-btn="Secondary" class="gap-2">
    <koala-icon name="Plus" size="Small" />
    New partner
</button>

<button koala-btn="Danger" koala-btn-variant="Outlined" class="gap-2">
    <koala-icon name="X" size="Small" />
    Cancel quote
</button>

Responsive sizing

Use w-full sm:w-auto for buttons that go full-width on mobile and auto-width on larger screens. Wrap in flex flex-col sm:flex-row gap-3.

Cancel
<div class="flex flex-col sm:flex-row gap-3">
    <button koala-btn="Primary" class="w-full sm:w-auto">Save</button>
    <a href="/cancel" koala-btn="Neutral" class="w-full sm:w-auto">Cancel</a>
</div>

Icon buttons

Use koala-icon-btn on <button> or <a> elements that contain only a single <koala-icon> (e.g. inline edit, delete, close). Muted icon with a subtle rounded background on hover (GitHub-style), giving visual separation between adjacent icons.

<button koala-icon-btn="Neutral" title="Edit">
    <koala-icon name="Pencil" />
</button>

<button koala-icon-btn="Danger" title="Delete">
    <koala-icon name="Trash" />
</button>

Use Neutral for edit/close, Danger for delete. The helper adds padding, a rounded hover background, and colour transitions — don't re-apply those yourself. Extra classes (e.g. absolute top-4 right-4, opacity-reveal) merge onto the output.

Colour reference

When to use each colour and variant combination.

Colour Variant Used for
Primary Filled Page-primary actions: Submit, Save, Invite, Accept; page-header CTAs (New partner, Add branch, Add team member, Invite team member)
Primary Soft Persistent global CTAs (top-nav "Get a quote") — branded but quieter than page-primary fills
Secondary Filled In-section CTAs (Add note inside the Notes section, New revision)
Neutral Filled Cancel, No, Back, Close
Danger Filled Destructive confirm (Yes in delete/disable modals)
Danger Outlined Destructive trigger (Cancel quote, Disable partner)

Copy link

A copy-to-clipboard button that flashes "Copied!" for 2 seconds after a successful copy. The value attribute is what gets copied.

<koala-copy-link value="@quote.PublicUrl" />
<koala-copy-link value="@partner.ReferralCode" label="Copy code" copied-label="Copied code!" />

Copy + open link

Pairs a visible URL (or label) with two icon affordances: a Copy button on the left and an Open-in-new-tab link on the right. The Copy icon briefly swaps to a Check tick (~1.5s) on success. Used on pages that surface a shareable URL alongside a QR code (referral codes, discount quick-create links).

https://app.koala.legal/r/ABC123
Open quote QUO-12345
https://app.koala.legal/d/SUMMER-DISCOUNT-CAMPAIGN-2026?utm_source=email&utm_medium=newsletter&utm_campaign=spring
<!-- Default: renders the URL as visible monospace text -->
<koala-copy-open-link href="@quickCreateUrl" />

<!-- With a custom label instead of the URL -->
<koala-copy-open-link href="@quote.PublicUrl" label="Open quote @quote.Reference" />

<!-- Long URL — wraps onto multiple lines -->
<koala-copy-open-link href="@discountUrl" />