Skip to content

Support multiple selectable theme variants from one package #1609

Description

@asiloisad

Have you checked for existing feature requests?

  • Completed

Summary

AI supported feature request.

Add support for a single theme package to register multiple selectable theme variants, such as light and dark variants, while preserving the current one-package-per-theme behavior.

Today Pulsar themes are effectively modeled as one package equals one theme entry. This works well for existing packages, but it makes paired or multi-variant themes awkward: maintainers need to publish separate packages for each color variant even when most of the code, styles, settings, commands, and documentation are shared.

The feature request is to let a package expose multiple UI and/or syntax theme entries in the theme picker.

Existing theme packages could continue using the current format:

{
  "name": "one-day-ui",
  "theme": "ui"
}

A new optional format could allow one package to provide several variants:

{
  "name": "one-theme",
  "themes": [
    { "name": "one-day-ui",       "theme": "ui",     "stylesheetsPath": "styles/day-ui" },
    { "name": "one-night-ui",     "theme": "ui",     "stylesheetsPath": "styles/night-ui" },
    { "name": "one-day-syntax",   "theme": "syntax", "stylesheetsPath": "styles/day-syntax" },
    { "name": "one-night-syntax", "theme": "syntax", "stylesheetsPath": "styles/night-syntax" }
  ]
}

Each entry needs a name, a theme of ui or syntax, and a stylesheetsPath pointing to a folder that contains the variant's index.less (the same layout a classic theme uses). stylesheetsPath may also be an array of folders when a variant shares Less files, and the package's own styles folder is always available as a fallback import path.

The Settings theme dropdowns would show the individual theme variant names, for example:

  • one-day-ui
  • one-night-ui
  • one-day-syntax
  • one-night-syntax

The existing core.themes config could continue to store selected theme names:

[
  "one-day-syntax",
  "one-day-ui"
]

For a variant theme, Pulsar would resolve the selected theme name to the owning package, activate that package, and load the selected variant stylesheet.

The key design point is that a variant is not a separate package, but it should behave like a selectable theme entry.

What benefits does this feature provide?

Many themes are really families of color variants rather than unrelated packages. For example:

  • a light UI theme and a dark UI theme with the same layout and behavior
  • matching light and dark syntax themes
  • several color palettes sharing the same structural Less files
  • high-contrast, dim, OLED, sepia, or seasonal variants

Supporting theme variants from one package would make these themes easier to maintain. It would avoid forcing maintainers to duplicate package structure just to provide different color palettes.

Operating systems have mature light/dark appearance switching now, and many users already expect applications to follow the system color mode. Pulsar currently does not provide a first-class path toward this behavior. Multi-variant theme packages would create a cleaner foundation for future Pulsar behavior such as:

  • automatically switching theme variants based on the operating system light/dark mode
  • switching themes by time of day
  • exposing a built-in "follow system theme" setting
  • switching UI and syntax themes together as a coordinated pair
  • reducing duplicated packages that only differ by color variables

This would also help package authors expose consistent classes like .light-theme and .dark-theme, so other packages can adapt their UI to the active color mode without needing to know every specific theme name.

A useful part of this feature is that it could act as a compatibility bridge between the current many-package structure and a future one-package theme-family structure. Existing separate packages could continue to work, while newer packages could expose several variants from one package. A future automatic theme switcher could then target the same theme-variant abstraction in both cases instead of needing separate logic for every package layout.

Any alternatives?

The current workaround is to publish separate packages for every variant, for example:

  • one-day-ui
  • one-day-syntax
  • one-night-ui
  • one-night-syntax

This works today and should remain fully supported. It is also the best short-term path for package authors who need compatibility with existing Pulsar versions.

However, separate packages duplicate a lot of structure when variants share the same layout, behavior, settings, commands, documentation, and tests. The only meaningful difference may be color variables. Over time, this makes paired themes harder to keep in sync.

Another workaround is to create one normal package with a custom setting or command that switches internal light/dark styles. Theme packages can already expose settings, and those settings can be used to change palette colors or switch between visual modes inside the package. That can work for manual customization, but it does not integrate cleanly with Pulsar's existing Settings > Themes dropdowns. The user would see only one selectable theme entry, not separate light and dark variants.

This also makes it harder to build future automatic switching behavior. An automatic switcher needs stable theme identities to switch between, such as a light variant and a dark variant. Package settings can change colors, but they do not describe those modes as first-class selectable themes that Pulsar can reason about consistently.

There are already community packages that provide automatic theme switching based on the operating system color mode by selecting themes from a configured list. This shows that there is existing demand for automatic light/dark switching in Pulsar. However, those packages can only work with the current model: separate theme package names in core.themes. They cannot select multiple variants from one theme package because Pulsar does not expose multi-theme packages as first-class selectable themes.

A community package could continue providing automatic switching between existing separate themes by changing core.themes. That would be useful, but it would not solve the underlying theme model. Pulsar would still have no first-class way for one package to describe several theme variants or for the theme picker to list them as selectable entries.

For these reasons, this seems better as an additive core capability. It would remain compatible with separate packages, while allowing new packages to opt in to multi-variant theme registration.

Other examples:

Operating systems already provide mature light/dark appearance switching:

  • macOS: system Appearance can be Light, Dark, or Auto
  • Windows: system/app color mode can be Light or Dark
  • GNOME/KDE and other Linux desktops increasingly expose light/dark preference APIs or settings

Many applications can follow the OS color mode or switch between light and dark themes automatically. Examples include browsers, code editors, terminals, and productivity applications.

In editor/theme ecosystems, it is also common for one theme family to provide multiple variants. For example, many themes are distributed as a family with light, dark, high-contrast, or dim variants. Pulsar can support those today as separate packages, but not as multiple first-class selectable variants from one package.

Update: reference implementation

A working proof of concept exists that implements this additively, with no change to the existing one-package-per-theme behavior:

  • A package with a themes array is treated as a theme package, but its stylesheets are not auto-loaded on activation. Instead Pulsar resolves the selected variant name in core.themes to the owning package, activates it once, and loads only the active variant's stylesheets.
  • Settings > Themes lists each variant as its own selectable UI or syntax entry.
  • Selecting a variant across two packages, or one variant plus a classic theme, works in either combination, and dev live reload tracks each variant.

A sample package is available for testing: https://github.com/asiloisad/pulsar-one-more

Not yet included, left as follow-ups this abstraction unlocks: per-variant className hooks (.light-theme / .dark-theme) and automatic switching based on the operating system color mode.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions