Dark Light
System
Default LBBW Jira Confluence Source Code
Share
Playground

Themes #

Themes allow you to customize the look and feel of aFP Design System. They provide a centralized way to control colors, typography, spacing, and other design elements, enabling a consistent and flexible visual experience across your application.

Select a theme below to preview the design system in a different style:

Default
Default theme
default
LBBW
Corporate design theme
lbbw

Installation #

All themes, including the default theme, are provided by the npm package @afp-design-system/themes.
Install it in your project with:

npm install @afp-design-system/themes

Import #

After installing the package, import the desired minified CSS file into your project.
For example, in the index.html file:

<link rel="stylesheet" href="/path/to/@afp-design-system/themes/dist/themes/<theme-name>.css">

In an NX workspace you can also add the theme in the project.json file:

"styles": [
  "node_modules/@afp-design-system/themes/dist/themes/<theme-name>.css"
]

Usage #

Themes can be applied and customized in several ways.
Each theme is provided inside a dedicated CSS layer named afp-theme, which allows for easy overrides and controlled specificity.

Apply via Class #

Add a theme by applying a theme-specific class to a parent element (for example the <body> or <html>).
You can use either of the following naming conventions:

  • theme-<theme-name>
  • afp-theme-<theme-name>

Example:

<body class="theme-default">

Apply via Data Attribute #

Alternatively, you can set the theme using a data-theme attribute on any container element
(such as <html>, <body>, or a specific section of your page):

  • data-theme="<theme-name>"
  • data-theme="afp-<theme-name>"

Example:

<html data-theme="default">

Automatic Application #

If only one theme is loaded in your project, that theme is automatically applied even without a class or data-theme attribute.


Overriding Variables #

All theme variables can be overridden if needed.
Since the theme styles are wrapped in the afp-theme layer, you have two options to ensure your overrides take effect:

  • Adjust the CSS layer order, so your custom layer has higher priority than afp-theme.

Example override with a custom layer:

@layer my-overrides {
  :root {
    --afp-color-brand-hue: 111;
  }
}

/* Ensure that my-overrides layer is declared after the afp-theme layer */
@layer my-overrides, afp-theme;

By following these approaches, you can fine-tune colors, spacing, or other CSS custom properties
while still leveraging the base theme styles.


Schemes #

Each theme provides two visual schemes: light and dark.
The scheme defines the overall brightness and color tone of the interface, allowing you to adapt your application to different environments or user preferences.

By default, the light scheme is applied automatically.
You can explicitly set the desired scheme using the data-scheme attribute on any container element (such as <html>, <body>, or even specific components).

Example usage on the <html> element:

<html data-scheme="dark">

You can also apply the scheme to individual elements to style them differently from the global setting:

Dark Button
<afp-button data-scheme="dark">Dark Button</afp-button>
<afp-button [data-scheme]="'dark'">Dark Button</afp-button>
<AfpButton data-scheme="dark">Dark Button</AfpButton>
<AfpButton :data-scheme="'dark'">Dark Button</AfpButton>

This flexibility allows you to mix light and dark appearances within the same page if needed.


CSS Parts #

The CSS shadow parts module defines the ::part() pseudo-element that can be set on a shadow host. Using this pseudo-element, you can enable shadow hosts to expose the selected element in the shadow tree to the outside page for styling purposes.

Custom style
<style>
  afp-button.custom-button::part(button) {
    background-color: deeppink;
    color: white;
  }
</style>

<afp-button class="custom-button">Custom style</afp-button>
<style>
  afp-button.custom-button::part(button) {
    background-color: deeppink;
    color: white;
  }
</style>

<afp-button [class]="'custom-button'">Custom style</afp-button>
<style>
  afp-button.custom-button::part(button) {
    background-color: deeppink;
    color: white;
  }
</style>

<AfpButton class="custom-button">Custom style</AfpButton>
<style>
  afp-button.custom-button::part(button) {
    background-color: deeppink;
    color: white;
  }
</style>

<AfpButton :class="'custom-button'">Custom style</AfpButton>

CSS Attributes #

Components may expose (dynamic) attributes and properties that reflect their current state, such as disabled, loading, or icon. These attributes can be combined with ::part() to apply styles conditionally from outside the component.

Style icon-only buttons:
This color isn’t red
<style>
  afp-button.custom-btn[icon]::part(button) {
    color: var(--afp-color-red-500);
  }
</style>

<div class="afp-stack">
  <small>Style icon-only buttons:</small>
  <div class="afp-cluster afp-gap-xs">
    <afp-button class="custom-btn" appearance="filled">
      <afp-icon name="balloon-heart-fill"></afp-icon>
    </afp-button>
    <afp-button class="custom-btn" appearance="filled">
      This color isn’t red
    </afp-button>
  </div>
</div>
<style>
  afp-button.custom-btn[icon]::part(button) {
    color: var(--afp-color-red-500);
  }
</style>

<div class="afp-stack">
  <small>Style icon-only buttons:</small>
  <div class="afp-cluster afp-gap-xs">
    <afp-button [class]="'custom-btn'" [appearance]="'filled'">
      <afp-icon [name]="'balloon-heart-fill'"></afp-icon>
    </afp-button>
    <afp-button [class]="'custom-btn'" [appearance]="'filled'">
      This color isn’t red
    </afp-button>
  </div>
</div>
<style>
  afp-button.custom-btn[icon]::part(button) {
    color: var(--afp-color-red-500);
  }
</style>

<div class="afp-stack">
  <small>Style icon-only buttons:</small>
  <div class="afp-cluster afp-gap-xs">
    <AfpButton class="custom-btn" appearance="filled">
      <AfpIcon name="balloon-heart-fill"></AfpIcon>
    </AfpButton>
    <AfpButton class="custom-btn" appearance="filled">
      This color isn’t red
    </AfpButton>
  </div>
</div>
<style>
  afp-button.custom-btn[icon]::part(button) {
    color: var(--afp-color-red-500);
  }
</style>

<div class="afp-stack">
  <small>Style icon-only buttons:</small>
  <div class="afp-cluster afp-gap-xs">
    <AfpButton :class="'custom-btn'" :appearance="'filled'">
      <AfpIcon :name="'balloon-heart-fill'"></AfpIcon>
    </AfpButton>
    <AfpButton :class="'custom-btn'" :appearance="'filled'">
      This color isn’t red
    </AfpButton>
  </div>
</div>

Using attributes on the host together with CSS Parts provides a stable and state-aware styling API without relying on internal class names.


Adding Your Own Theme #

You can also create and add your own custom theme.
For more details and instructions, see the README in the themes repository.

Share
Create a link with a predefined theme that is automatically applied when the generated link is opened. Default LBBW Presentation Mode
Abort Copy Link