Koala logo Design

Buttons

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

Colours

Four colours, each tied to a clear role. Primary is filled --color-primary (sage green) — the page-level CTA (Submit, Save, Invite). Secondary is filled --color-secondary (dark navy) — branded but lower-emphasis than Primary, for actions that aren't the main page CTA but still want brand weight. Outline is white surface + neutral border — Cancel, Back, Close, in-section CTAs, persistent global CTAs. Danger is filled red — destructive confirmation.

<button koala-btn="Primary">Primary</button>
<button koala-btn="Secondary">Secondary</button>
<button koala-btn="Outline">Outline</button>
<button koala-btn="Danger">Danger</button>

Outlined variant

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

<button koala-btn="Danger" koala-btn-variant="Outlined">Outlined</button>

Example — destructive flow

Pairing in practice: an outlined trigger that opens a confirmation, with a filled variant inside the modal as the final commit.

<!-- Trigger (on the page) -->
<button koala-btn="Danger" koala-btn-variant="Outlined">Cancel quote</button>

<!-- Confirm (inside the modal) -->
<button koala-btn="Danger">Yes, delete</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">Primary</a>
<a href="/partner/partners/create" koala-btn="Outline">Outline</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.

Click a button to see the loading state. The button enters the loading state until the form response arrives; here there's no form, so click again to reset by reloading the page.

<!-- Add koala-loading on a submit button. The tag helper auto-injects
     x-data, a click guard, disabled styling, and a spinner SVG that
     replaces the label on click. Loading state lasts until the form
     response arrives. -->
<form method="post">
    <button type="submit" koala-loading koala-btn="Primary">Primary</button>
</form>

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="Outline" 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="Outline" 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)
Secondary Filled Branded actions a step below Primary in emphasis: Save draft alongside Publish, branded confirms that aren't a page CTA. Filled --color-secondary (dark navy) with white text.
Outline Filled (white surface, neutral border) Cancel, No, Back, Close; in-section CTAs (Add note, New revision); persistent global CTAs (top-nav "Get a quote")
Danger Filled Destructive confirm (Yes in delete/disable modals)
Danger Outlined Destructive trigger (Cancel quote, Disable partner)

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
<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" />