UI Components

UI components are ready-made buttons, form controls, dialogs, charts and more for AngularLynx apps. A CLI copies their source into your project, so you own the code and can change anything. It's the same idea as shadcn/ui.

Two package names are involved:

  • @blotch/ui is the component source. You never install it.
  • @blotch/dolan is the CLI. It carries a copy of that source and writes it into src/components/ui/.

Before you start

The components are styled with Tailwind CSS. If you said yes to Tailwind when you created the app, you're ready. Otherwise, set it up first: see Tailwind CSS.

Installation

1. Install the CLI as a dependency.

npm install @blotch/dolan class-variance-authority
  • Copied components import cn() and animation helpers from @blotch/dolan, so your app needs it to build, not only to run commands.
  • Button, Button Group, Toggle, Typography, Badge and Alert also import class-variance-authority, which dolan add doesn't install for you.

2. Set up dolan.

npx @blotch/dolan init

Press Enter to accept both default folders. It writes dolan.config.json and copies three theme files into src/styles/:

  • default.css: the light theme's colors and corner radius
  • dark.css: the dark theme's colors
  • tailwind-plugin.ts: maps those colors to Tailwind classes such as bg-primary

3. Add the Tailwind plugin.

tailwind.config.ts
import type { Config } from 'tailwindcss';
import preset from '@lynx-js/tailwind-preset';
import { blotchPlugin } from './src/styles/tailwind-plugin'; 

const config: Config = {
  content: ['./src/**/*.ts'],
  presets: [preset],
  plugins: [blotchPlugin],
};

export default config;

4. Import the theme. Put the @import lines first, because CSS ignores an @import that comes after other rules.

src/styles.css
@import './styles/default.css';
@import './styles/dark.css';

@tailwind base;
@tailwind utilities;

dark.css changes nothing until you turn dark mode on. See Theming.

5. Add components.

npx @blotch/dolan add button card

Each one lands in src/components/ui/<name>/. Components it depends on come too: button brings spinner.

6. Use them.

src/app/app.ts
import { Component, signal } from '@angular/core';
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
import { UiButton } from '../components/ui/button';
import {
  UiCard,
  UiCardContent,
  UiCardHeader,
  UiCardTitle,
} from '../components/ui/card';

@Component({
  selector: 'app-root',
  imports: [
    LYNX_ELEMENTS,
    UiButton,
    UiCard,
    UiCardHeader,
    UiCardTitle,
    UiCardContent,
  ],
  template: `
    <view class="h-full bg-background p-6">
      <ui-card>
        <ui-card-header>
          <ui-card-title>Welcome</ui-card-title>
        </ui-card-header>
        <ui-card-content>
          <ui-button (pressed)="increment()">
            Tapped {{ count() }} times
          </ui-button>
        </ui-card-content>
      </ui-card>
    </view>
  `,
})
export class App {
  protected readonly count = signal(0);

  protected increment(): void {
    this.count.update((n) => n + 1);
  }
}
  • The component pages import from ../components/ui/<name>, a path relative to src/app/.
  • Templates use Lynx elements such as <view> and <text> instead of HTML (see Glossary). Import LYNX_ELEMENTS whenever you use them (see Elements).

Good to know

  • Text color doesn't inherit. CSS inheritance is off by default on Lynx, so put a color class such as text-foreground on each of your own <text> elements. The components color their own text.
  • Tests come with the code. dolan add copies each component's <name>.test.ts. Most use @blotch/angular-lynx-testing-library, so set up testing or delete those files.
  • Updates are merged, not forced. Run dolan update after upgrading @blotch/dolan. It keeps your edits and asks when both sides changed.

Components

General

  • Button: a tappable button with variants, sizes and a loading state
  • Button Group: connected buttons that act as one toolbar
  • Icon: 195 vector icons
  • Typography: text styles for headings, body and captions

Layout

  • Card: a bordered surface with header, content and footer
  • Separator: a thin horizontal or vertical line
  • Accordion: stacked sections that expand one or many at a time
  • Collapsible: one section that shows and hides its content
  • Tabs: panels switched by a row of tab buttons
  • Aspect Ratio: a box that keeps a width-to-height ratio
  • Scroll Area: a scrolling container with edge events

Navigation

Data Display

Forms

  • Input: a single-line text field with label, helper text and error
  • Textarea: a multi-line text field that grows with its content
  • Label: a caption for a form control
  • Checkbox: an on/off box with a check mark
  • Radio Group: pick one option from a list
  • Select: pick one option from a bottom sheet
  • Switch: an on/off toggle switch
  • Toggle: a button that stays pressed, alone or in a group

Feedback

  • Alert: an inline message
  • Alert Dialog: a dialog that asks for confirmation
  • Dialog: a centered modal window
  • Bottom Sheet: a panel that slides up from the bottom
  • Sheet: a bottom sheet with header and footer slots
  • Action Sheet: a list of actions that slides up
  • Toast: short messages that appear and go away

Design principles

  • You own the code. Components are plain files in your repo. Edit them like your own.
  • Signals throughout. Inputs use input(), events use output(), and two-way values use model(), so [(value)] and [(checked)] work.
  • Theme tokens, not colors. Components use classes such as bg-primary and text-muted-foreground, defined once in your theme. See Theming.
  • Variants with cva. Variant classes come from class-variance-authority. Components export them, for example buttonVariants.
  • Your classes win. Most components take a class input. It's merged with cn(), so a conflicting class you pass replaces the default.
  • Lynx elements only. Components are built from <view>, <text>, <svg>, <overlay> and other Lynx elements, never HTML.
  • CLI: every @blotch/dolan command
  • Theming: change colors, radius and dark mode
  • Tailwind CSS: set up Tailwind for Lynx