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.
<!-- 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.
<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.
<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).
<!-- 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" />