Skip to main content
Neural UIv2.0.0Documentation
View v1 GitHub

Theming

Use Core defaults, select light or dark, register a preset and choose density.

Start with the default styles

Loading @neural-ui/core/styles supplies the default Core tokens. No preset or provider is required. The default mode is light unless your application selects dark. Application CSS may override those defaults; the current theme is the result of that cascade.

styles.scss
@use '@neural-ui/core/styles' as *;

Choose light or dark

Set data-theme="dark" on the document element to select dark Core tokens. The application owns this choice. This complete mode control writes the attribute when the user changes it; keep the same initial mode on server and browser. A preset does not select it for you.

example.ts
import { DOCUMENT } from '@angular/common';
import { Component, inject, signal } from '@angular/core';
import { NeuSwitchComponent } from '@neural-ui/core/switch';

@Component({
  selector: 'app-theme-mode',
  imports: [NeuSwitchComponent],
  template:
    '<neu-switch label="Dark mode" [checked]="dark()" (checkedChange)="selectMode($event)" />',
})
export class ThemeMode {
  private readonly document = inject(DOCUMENT);
  readonly dark = signal(false);
  selectMode(dark: boolean): void {
    this.dark.set(dark);
    this.document.documentElement.setAttribute(
      'data-theme',
      dark ? 'dark' : 'light',
    );
  }
}

See both modes

Edit either Input: both surfaces share the same value. The dark surface uses data-theme="dark". The light surface explicitly restores its own light colors so this comparison also works inside a dark application; that scoped restoration is visible in Source.

See both modes

Light

Dark

Define a reusable preset

Save this as src/app/product-preset.ts. defineNeuPreset checks public token names and groups independent light/dark overrides. Change related background, foreground and hover values together, then check contrast in both modes.

product-preset.ts
import { defineNeuPreset } from '@neural-ui/core';

export const productPreset = defineNeuPreset({
  name: 'product',
  light: {
    '--neu-primary': '#175d95',
    '--neu-primary-dark': '#124c7d',
    '--neu-primary-solid': '#175d95',
    '--neu-primary-solid-fg': '#ffffff',
    '--neu-primary-solid-hover': '#124c7d',
  },
  dark: {
    '--neu-primary': '#86c8ff',
    '--neu-primary-dark': '#124c7d',
    '--neu-primary-light': '#86c8ff',
    '--neu-primary-solid': '#175d95',
    '--neu-primary-solid-fg': '#ffffff',
    '--neu-primary-solid-hover': '#124c7d',
  },
});

Register the preset

Import productPreset in app.config.ts and add provideNeuralUI alongside your existing providers. It activates the named preset; data-theme still selects the mode. A global preset is for component tokens, not for your application layout.

app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideNeuralUI } from '@neural-ui/core';
import { productPreset } from './product-preset';

export const appConfig: ApplicationConfig = {
  providers: [provideNeuralUI({ theme: { preset: productPreset } })],
};

Choose a control density

Set data-neu-density on a container to choose compact, comfortable or spacious control density. The default-size Input fields below use heights of 2.5rem, 2.75rem and 3rem, respectively (40, 44 and 48px with a 16px root font size). For Button, use the size input to choose its size; density adjusts the gap between its elements.

Choose a control density