How to make Seelen UI Themes

Basic Info

Theme code is done via CSS/SCSS.

Theme metadata is done via YAML.

We have a built-in debug mode for devs to aid in the creation of your themes. With it, you can:

➙ Inspect elements just like a web page
➙ See live HTML/CSS changes
➙ Test theme modifications instantly
➙ Debug styling issues easily

To bring it up, click either the toolbar or dock to focus on either and then send: Ctrl + Shift + I or Ctrl + Shift + Alt + I

 


 

Theme Formats

  1. Modular Theme Folder

    • Development & personal use only - NOT accepted for submission to the site.
    • Easy to organize, translate, and maintain.
  2. Bundled Theme File

    • Created by using CLI commands to bundle your Modular Theme Folder into a single file (covered later in this guide).
    • Required format for submission to the site.

 


 

Theme Scopes

  1. Components

    • @seelen/fancy-toolbar - Topbar

      └─ fancy-toolbar.scss

    • @seelen/weg - Dock / Taskbar

      └─ weg.css

    • @seelen/launcher - App Launcher

      └─ launcher.css

    • @seelen/window-manager - Window Manager

      └─ window-manager.css

    • @seelen/wallpaper-manager - Wallpaper Manager

      └─ wallpaper-manager.css

    • @seelen/task-switcher - Alt + Tab Menu

      └─ task-switcher.scss

  2. Module Menus

    • @seelen/system-tray - System Tray

      └─ tray-menu.scss

    • @seelen/power-menu - Power Options (Restart, Suspend, etc.)

      └─ power-menu.scss

    • @seelen/quick-settings - Quick Settings

      └─ quick-settings.scss

    • @seelen/bluetooth-popup - Bluetooth

      └─ bluetooth-popup.scss

Note that the file names you use DO NOT need to be the same as those above. These are just the default names noted for convenience for the next part.

 


 

Theme Preperation

Navigate to C:\Users\USER\AppData\Roaming\com.seelen.seelen-ui\themes.

In here, create a folder for your theme (the name does not matter).

And in your created folder, create the necessary files by following the below example structure.

Modular Theme Folder

├── YourThemeFolder/
│   ├── metadata.yml
│   ├── meta-split/            # (Optional) Split up metadata for translation purposes or for organization (included via !extend)
│   │   ├── display_name.yml
│   │   └── description.yml
│   │   └── settings.yml
│   ├── styles/                # Scopes that your modifying (included via !include)
│   │   ├── weg.css
│   │   ├── fancy-toolbar.scss
│   │   ├── window-manager.css
│   │   └── launcher.css
│   └── shared/                # (Optional) Splitting of styles shared across scopes (included via !include)
│       ├── index.scss
│       ├── buttons.scss
│       └── inputs.scss

 


 

Metadata - Base

Once you've structured your Modular Theme Folder, open up the metadata.yml.

Fill it as shown:

id: "@yourname/theme-id"
metadata:
  displayName: "Theme Name"
  description: "Theme Description"
  appTargetVersion:
    - 2
    - 4
    - 11

OR

id: "@yourname/theme-id"
metadata:
  displayName: !extend meta-split/display_name.yml
  description: !extend meta-split/description.yml
  appTargetVersion:
    - 2
    - 4
    - 11

ID is your theme's Friendly Identifier. It must be at least three valid characters long. Letters and numbers are valid.

Displayname / Description are self-explanatory. But if you split them as shown in the second, you would update those files like so to provide translations (a simple list):

en: Default Seelen Theme
uk: Тема за замовчуванням
hi: डिफ़ॉल्ट सेलेन थीम
tr: Varsayılan Seelen Teması
zh-CN: 默认 Seelen 主题
hr: Zadana tema Seelen
zh-TW: 默認 Seelen 主題
pt-PT: Tema Seelen padrão
...

Note that Seelen UI has a built-in CLI command to give MTL translations to your resource. It will be covered later in the guide.

AppTargetVersion should be set to the latest Seelen UI version at the time of creating and be updated as required/wanted to remove the version warning.

 


 

Metadata - Theme Settings

After you've set the base metadata, you can set a settings section.

This allows your theme to be customizable directly from the Seelen Settings menu. You’ve likely seen this in many themes uploaded to the site.

How does it work?

Instead of hardcoding values in your code (next section), you set variables in there place. You or other users can then change the values of those variables, and your theme will use them the way you've set it up.

This is something you have to build up as you are writing the code so note it.

...
  appTargetVersion:
    - 2
    - 4
    - 11
settings:
  - syntax: <>
    name: '--example-length-var'
    label: "Example Setting Name"
    initialValue: ~
    initialValueUnit: ~
...

OR

...
  appTargetVersion:
    - 2
    - 4
    - 11
settings: !extend meta-split/settings.yml

Also, you can add additional information with the setting. It will show in the theme settings page.

...
  - syntax: <>
    name: '--example-length-var'
    label: "Example Setting Name"
    description: "This shows below the label with a lighter color - for explanations"
    tip: "Info button gets added next to label and any text here is shown in a tooltip when it is hovered"
    initialValue: ~
    initialValueUnit: ~
...

Translations:

- syntax: <>
  name: '--example-length-var'
  label:
    en: "Example Setting Name"
  description:
    en: "This shows below the label with a lighter color - for explanations"
  tip:
    en: "Info button gets added next to label and any text here is shown in a tooltip when it is hovered"
  initialValue: ~
  initialValueUnit: ~
...

 


 

Theme Settings - Overview

Available Syntax Types:

  ...
  appTargetVersion:
    - 2
    - 4
    - 11
settings:
  - syntax: <color>
    name: '--example-color-var'
    label:
      en: "Example Color"
    initialValue: '#def8ffdc'

  - syntax: <length>
    name: '--example-length-var'
    label:
      en: "Example Length"
    initialValue: 2
    initialValueUnit: 'px'

  - syntax: <number>
    name: '--example-number-var'
    label:
      en: "Example Number"
    initialValue: 600

  - syntax: <string>
    name: '--example-string-var'
    label:
      en: "Example String"
    initialValue: 'grayscale(0%) opacity(1.0) saturate(1.0)'

  - syntax: <url>
    name: '--example-url'
    label:
      en: "Example Url"
    initialValue: ''

Usage in Code:

.taskbar {
  ...
  .taskbar-bg-layer-2 {
    background-color: var(--example-color-var); /* Dock's main BG */
    border: var(--example-length-var) solid var(--example-secondary-color-var); /* Adds border around dock */
  }
}
...
.ft-bar-item {
  font-weight: var(--example-number-var); /* Font line thickness */
}
...
.weg-item {
  .weg-item-icon {
    filter: var(--example-string-var, grayscale(0%) opacity(1.0) saturate(1.0));
  }
}

Note: For "string" variables, adding a fallback as shown above is good. Everything after the "," is considered part of the fallback, so just put the code snippet like so. This way, if when changing the value in Seelen Settings, the code snippet becomes invalid, it doesn't break and instead uses this fallback.

 


 

Metadata - Styles

After the settings section (if you choose to use it), is the styles section where you define the scopes your editing and point to the related files.

  ...
  appTargetVersion:
    - 2
    - 4
    - 11
settings: !extend meta-split/settings.yml
styles:
  "@seelen/fancy-toolbar": !include styles/fancy-toolbar.scss
  "@seelen/launcher": !include styles/launcher.css
  "@seelen/power-menu": !include styles/power-menu.scss
  "@seelen/task-switcher": !include styles/task-switcher.scss
  "@seelen/wallpaper-manager": !include styles/wallpaper-manager.css
  "@seelen/weg": !include styles/weg.css
  "@seelen/window-manager": !include styles/window-manager.css
  "@seelen/system-tray": !include styles/tray-menu.scss
  "@seelen/quick-settings": !include styles/quick-settings.scss
  "@seelen/bluetooth-popup": !include styles/bluetooth-popup.scss

 


 

Styles - Overview

There isn't much to add about the coding part of this. Follow standard CSS/SCSS practices.

And you just need to remember to use the debug tool effectively to get variable names and any other information of interest.

You can also view Seelen UI's default themes for the base variables and as a self-guide.

You can find those on the github page or go you can go to your Seelen UI install folder and navigate: static > themes.

Still, here is a quick preview:

weg.css :

.taskbar {
  .taskbar-bg-layer-1 {
    display: none;
  }

  .taskbar-bg-layer-2 {
    background-color: #def8ffdc;
    border: 2px solid #acdae6;
    border-radius: 15px;
  }
}

.weg-item {
  .bg-layer-1 {
    display: none;
  }
  
  .bg-layer-2 {
    background-color: rgba(132, 161, 187, 0.438);
    border-radius: 10px;
  }

  &:has(.weg-item-open-sign-focused) .bg-layer-2,
  &:hover .bg-layer-2 {
    background-color: rgb(198, 211, 236);
  }

  .weg-item-icon {
    filter: grayscale(0%) opacity(1.0) saturate(1.0);
  }
}

 


 

Metadata - Shared Styles

This is if you want to create reusable styles across multiple scopes.

...
styles:
  "@seelen/weg": !include styles/weg.css
  "@seelen/fancy-toolbar": !include styles/toolbar.css
sharedStyles: !include shared/index.scss

 


 

Shared Styles - Overview

...

 


 

Bundling your Theme

Open CMD and run: seelen-ui resource bundle theme "C:\path\to\your\theme\folder"

For full info: seelen-ui resource bundle --help

 


 

Adding MTL Translations to your Theme

Open CMD and run: seelen-ui resource translate "C:\path\to\export_12345.yml"

Specify source language: seelen-ui resource translate "C:\path\to\export_12345.yml" en

For full info: seelen-ui resource translate --help

  • By: K. Ivy
  • Published at: Sun Dec 28 2025
  • Last revision: Sun Dec 28 2025