CwButton

Every variant, size and state. Buttons share the same height scale as inputs and dropdowns, so controls of the same size line up in a toolbar. Buttons default to type="button"; pass type="submit" to submit a form.

Variants

Sizes

Alignment with form controls

Each row uses one size value; every control in the row is the same height.

States

Click it: the button keeps its width while the spinner shows.

Last event: none yet

CwButton example Copy code
<CwButton variant="primary">Save changes</CwButton>

<!-- Buttons default to type="button"; opt in to form submission explicitly -->
<CwButton type="submit" variant="primary">Submit</CwButton>

Icons

CwButton icon examples Copy code
<script lang="ts">
	import moreVertIcon from '$lib/icons/more_vert.svg';
</script>

<CwButton variant="secondary" aria-label="Refresh data">
	<svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
		<path
			d="M12.8 7.9A4.8 4.8 0 118 3.2c1.3 0 2.5.5 3.4 1.4"
			stroke="currentColor"
			stroke-width="1.4"
			stroke-linecap="round"
		/>
		<path
			d="M11.7 3.2h2.4v2.4"
			stroke="currentColor"
			stroke-width="1.4"
			stroke-linecap="round"
			stroke-linejoin="round"
		/>
	</svg>
</CwButton>

<CwButton variant="primary" aria-label="More actions" icon={moreVertIcon} />
<CwButton variant="primary" icon={moreVertIcon}>More</CwButton>
API

Usage and API reference

CwButton is the standard action component. Use it for labeled actions, icon-and-text buttons, and icon-only controls that still need a proper accessible name.

How to think about it

  1. Choose the role first Use `primary` for the main action on the page, `secondary` or `ghost` for supporting actions, and `danger` for destructive work.
  2. Size for layout, not emphasis `sm`, `md`, and `lg` only change spacing and font size. They do not change the semantic priority of the action.
  3. Prefer `loading` over manual spinners The component automatically disables itself and swaps in the shared spinner while async work is running.
  4. Label icon-only buttons accessibly If the button has no visible text, provide `aria-label`. You can render the icon inline as children or pass it through the `icon` prop.

Props and callbacks

The docs table lists the CWUI-specific API. Native button attributes still pass through.

APITypeDetails
variant

Default: primary

'primary' | 'secondary' | 'ghost' | 'danger' | 'info'Visual treatment for the action.
size

Default: md

'sm' | 'md' | 'lg'Padding and font scale.
loading

Default: false

booleanShows the built-in spinner and disables the button.
disabled

Default: false

booleanPrevents interaction without showing a loading spinner.
fullWidth

Default: false

booleanExpands the button to the width of its container.
icon
string | { src: string } | { default: string } | SnippetOptional leading icon asset or snippet. For icon-only buttons, pair it with `aria-label`.
children
SnippetButton content. This can be text, icon-only markup, or mixed inline content.
...native button attrs
HTMLButtonAttributesPass `type`, `name`, `value`, `aria-*`, `onclick`, and standard button attributes directly to the underlying `<button>`.
type

Default: 'button'

'button' | 'submit' | 'reset'Native button type. Defaults to `button`, so buttons inside forms never submit by accident.

Copy-paste examples

Each snippet is a complete, working example you can paste into a Svelte 5 component.

Primary and supporting actions

This is the default pattern for forms, drawers, and dialogs.

Primary and supporting actions Copy code
<CwButton variant="primary">Save changes</CwButton>
<CwButton variant="secondary">Preview</CwButton>
<CwButton variant="ghost">Cancel</CwButton>
Loading submit button

Use `loading` instead of manually wiring your own spinner.

Loading submit button Copy code
<script lang="ts">
	let saving = $state(false);

	async function submitForm() {
		saving = true;
		await new Promise((resolve) => setTimeout(resolve, 900));
		saving = false;
	}
</script>

<CwButton
	variant="primary"
	size="lg"
	fullWidth
	type="submit"
	loading={saving}
	onclick={submitForm}
>
	Save irrigation plan
</CwButton>
Icon-only and icon-prop buttons

Use inline markup when you want full control, or `icon={...}` when you already have an asset import.

Icon-only and icon-prop buttons Copy code
<script lang="ts">
	import moreVertIcon from '$lib/icons/more_vert.svg';
</script>

<CwButton variant="secondary" aria-label="Refresh data">
	<svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
		<path
			d="M12.8 7.9A4.8 4.8 0 118 3.2c1.3 0 2.5.5 3.4 1.4"
			stroke="currentColor"
			stroke-width="1.4"
			stroke-linecap="round"
		/>
		<path
			d="M11.7 3.2h2.4v2.4"
			stroke="currentColor"
			stroke-width="1.4"
			stroke-linecap="round"
			stroke-linejoin="round"
		/>
	</svg>
</CwButton>

<CwButton variant="primary" aria-label="More actions" icon={moreVertIcon} />