How to easily copy a built in theme?

I have been trying to create a copy of a built-in theme to use as a starting point since an empty theme also causes all make up, colors, text sizes etc to fall back to the browser default.

So far I have found it be frustrating. The files do not seem to be exposed to the file system. reading file by file via the api is time consuming and prone to error

I think either the files should be exposed in the file system or a copy theme URL should be added to the API.

or is there a way to import a theme with a css file and then start overriding what I need ?

1 Like

You should import the light theme in your custom theme. Have a look at the dark theme as an example

Nick, the OP is complaining because in 8.3 now that themes have become a "system" resource, they don't exist on the filesystem, so there's nothing to take a look at :upside_down_face:

For the OP, it's a legitimately vexing complaint. I'll say this: we're not going to make 'system' resources exist on the filesystem and we're unlikely to move first party themes out of 'system' - because the entire point of the system resource collection is for us to put first party stuff that you're allowed to override.

At some point early in the 8.3 lifecycle we're planning to have "smarter" gateway backup and restore - I would hazard a guess that you would be able to do a "partial" gateway backup that only includes the system level theme(s) you're interested in - think of this as equivalent to a project export in the designer.

At some other point early in the 8.3 lifecycle we're planning to add web UI to manage resource files with multiple individual files, such as JDBC drivers. At some point after that we'll probably add a web UI to manage themes, because there's no reason for it not to have a web interface.

At some other point early in 8.3 we're planning to add a system.config scripting API that should make it easier to script any kind of export/import functionality you want.

In the meantime... unfortunately, somewhat tedious stuff is probably going to be the way to go.

In your custom theme, you should be able to start it with an import like in 8.1 to set a builtin theme as a sort of base (ie. @import "./light/index.css")
Then from there your custom theme can start overriding stuff. But yeah as Paul mentioned since these are system level resources they aren’t exposed to the file system.

For posterity, the easiest solution might be to either go to your filesystem or our downloads page and download the Perspective module:

.modl files are just zip files, so you can open them in any archive extraction tool. It'll contain, among other things, a perspective-themes .jar file.
.jar files are also just zip files, so you can open them in any archive extraction tool.
Inside the themes files there'll be a set of Perspective theme .zip files:

2 Likes

I will test all of these tomorrow, but the import method looks like the best way going forward to keep compatibility and upgrade-ability.

btw I fully expect some sort of theme editor in a perspective project to popup in the exchange soon after full release

I am unable to import css files from built in themes in the css from a custom theme.

as a test I copy pasted these from the dark theme:

@import "../light/app/index.css";
@import "../light/common/index.css";
@import "../light/designer/index.css";
@import "../light/palette/index.css";

I keep getting the error file not found, is it possible that custom themes cannot reach the css files from built in themes ?

We use the themeManager to get the base theme [ usually light ] into a String and then append our overrides on the end. It’s a little “low level” but it works for us.

Optional baseTheme = context.getThemeManager().getTheme(baseName);

We then write our theme into the system using a builder - along the lines of

try {
					themeManager.create(themeName, new ThemeConfig(themeResource), "Kanoa MES", builder -> {
						Optional<String> baseTheme = context.getThemeManager().getTheme(baseName);
						String ourTheme = getThemeString(themePath);
						String globals = getThemeString("themes/globals.css");

						if(baseTheme.isPresent())
						{
							String thisTheme = baseTheme.get() + globals + ourTheme;
							ImmutableBytes b = ImmutableBytes.ofString(thisTheme);					
							builder.putData(themeResource, b);
						}
					});
				} catch (PushException e) {
					logger.error("Error creating " + themeResource + " : " + e);
					retval = FAILURE;
				}

I may be doing it a long winded way and we may be able to make it simpler with the @import above so I may look into it again in the future.