Button

A tappable button with five styles, four sizes, and disabled and loading states.

Installation

npx @blotch/dolan add button
import { UiButton } from '../components/ui/button';

This also adds Spinner, which shows while the button is loading. Button imports class-variance-authority (see Installation).

Usage

src/app/app.ts
import { Component, signal } from '@angular/core';
import { UiButton } from '../components/ui/button';

@Component({
  selector: 'app-root',
  imports: [UiButton],
  template: `
    <ui-button [loading]="saving()" (pressed)="save()">Save changes</ui-button>
  `,
})
export class App {
  protected readonly saving = signal(false);

  protected save(): void {
    this.saving.set(true);
  }
}
  • pressed fires on tap. It doesn't fire while the button is disabled or loading.
  • Put plain text inside. The button wraps it in a <text> element for you.
  • The button shrinks slightly while a finger is down, on every platform.

Variants

<ui-button variant="default">Default</ui-button>
<ui-button variant="destructive">Delete</ui-button>
<ui-button variant="outline">Outline</ui-button>
<ui-button variant="secondary">Secondary</ui-button>
<ui-button variant="ghost">Ghost</ui-button>

Sizes

<ui-button size="sm">Small</ui-button>
<ui-button size="default">Default</ui-button>
<ui-button size="lg">Large</ui-button>
<ui-button size="icon">+</ui-button>

icon makes a square button for a single character.

Disabled and loading

<ui-button [disabled]="true">Disabled</ui-button>
<ui-button [loading]="true">Saving</ui-button>

Both dim the button to 50% and ignore taps. loading also replaces the label with a spinner.

Custom classes

<ui-button class="w-full">Continue</ui-button>

Your classes are merged onto the button's container and replace any default they conflict with.

Button styles on your own view

buttonVariants() returns the container classes for a variant and size. Use it to style a view that isn't a <ui-button>, and color its text yourself.

src/app/settings-link.ts
import { Component } from '@angular/core';
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
import { buttonVariants } from '../components/ui/button';

@Component({
  selector: 'app-settings-link',
  imports: [LYNX_ELEMENTS],
  template: `
    <view [class]="linkClass">
      <text class="text-sm font-medium text-foreground">Settings</text>
    </view>
  `,
})
export class SettingsLink {
  protected readonly linkClass = buttonVariants({
    variant: 'outline',
    size: 'sm',
  });
}

API

UiButton

InputTypeDefaultDescription
variant'default' | 'destructive' | 'outline' | 'secondary' | 'ghost''default'Visual style.
size'default' | 'sm' | 'lg' | 'icon''default'Height and padding. icon is a square.
disabledbooleanfalseDims the button and ignores taps.
loadingbooleanfalseShows a spinner, dims the button, ignores taps.
classstring''Extra Tailwind classes for the container.
OutputTypeDescription
pressedvoidEmits on tap, unless disabled or loading.

The file also exports buttonVariants and the ButtonVariant and ButtonSize types.