-
-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Load a theme via a theme
key in volto.config.js
or in package.json
#4625
Merged
Merged
Changes from 7 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
e6389a4
Use an entrypoint in volto.config.js or in package.json to load a theme
sneridagh 49026ff
Pining of `pydata-sphinx-theme` and `sphinx-book-theme`, CI is compla…
sneridagh e47b488
Preliminar docs
sneridagh 2ff4edb
Normalize name coming from getAddonDependencies
sneridagh 31ffe81
Changelog
sneridagh ce82d87
Add as temp files
sneridagh 3803033
Better docs
sneridagh da34018
Apply suggestions from code review
sneridagh dee896b
Update news/4625.feature
sneridagh f828984
Update docs/source/addons/theme.md
sneridagh bdd00fc
Merge branch 'master' into themeEntrypoints
sneridagh a446595
Add environment variable option to define the theme. Add documentatio…
sneridagh 3b9783e
Link new doc theme file
sneridagh 88e4176
Merge branch 'master' into themeEntrypoints
sneridagh a723965
Apply suggestions from code review
sneridagh c2876fe
Update docs/source/addons/theme.md
sneridagh dbb5735
More docs
sneridagh 074132d
Update docs/source/addons/theme.md
sneridagh 14de867
A bit more of re-wording
sneridagh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const tmp = require('tmp'); | ||
const cryptoRandomString = require('crypto-random-string'); | ||
|
||
const titleCase = (w) => w.slice(0, 1).toUpperCase() + w.slice(1, w.length); | ||
|
||
/* | ||
* Transforms a package name to javascript variable name | ||
*/ | ||
function nameFromPackage(name) { | ||
name = | ||
name.replace(/[@~./\\:\s]/gi, '') || | ||
cryptoRandomString({ length: 10, characters: 'abcdefghijk' }); | ||
return name | ||
.split('-') | ||
.map((w, i) => (i > 0 ? titleCase(w) : w)) | ||
.join(''); | ||
} | ||
|
||
/* | ||
* Creates a static file with code necessary to load the addons configuration | ||
* | ||
*/ | ||
function getAddonsLoaderCode(name, customThemeAddons = []) { | ||
let buf = `/* | ||
This file is autogenerated. Don't change it directly. | ||
Add a ./theme/_${name}.scss in your add-on to load your theme customizations in the current theme. | ||
*/ | ||
|
||
`; | ||
customThemeAddons.forEach((addon) => { | ||
const customization = `${addon}/theme/${name}`; | ||
const line = `@import '${customization}';\n`; | ||
buf += line; | ||
}); | ||
|
||
return buf; | ||
} | ||
|
||
module.exports = ({ main, variables }) => { | ||
// const addonsThemeLoaderVariablesPath = path.join( | ||
// process.cwd(), | ||
// 'src', | ||
// '_variables.scss', | ||
// ); | ||
// const addonsThemeLoaderMainPath = path.join( | ||
// process.cwd(), | ||
// 'src', | ||
// '_main.scss', | ||
// ); | ||
|
||
// const addonsThemeLoaderVariablesPath = path.join( | ||
// process.cwd(), | ||
// 'src', | ||
// '_variables.scss', | ||
// ); | ||
// const addonsThemeLoaderMainPath = path.join( | ||
// process.cwd(), | ||
// 'src', | ||
// '_main.scss', | ||
// ); | ||
|
||
const addonsThemeLoaderVariablesPath = tmp.tmpNameSync({ postfix: '.scss' }); | ||
const addonsThemeLoaderMainPath = tmp.tmpNameSync({ postfix: '.scss' }); | ||
fs.writeFileSync( | ||
addonsThemeLoaderVariablesPath, | ||
new Buffer.from(getAddonsLoaderCode('variables', variables)), | ||
); | ||
fs.writeFileSync( | ||
addonsThemeLoaderMainPath, | ||
new Buffer.from(getAddonsLoaderCode('main', main)), | ||
); | ||
|
||
return [addonsThemeLoaderVariablesPath, addonsThemeLoaderMainPath]; | ||
}; | ||
|
||
module.exports.getAddonsLoaderCode = getAddonsLoaderCode; | ||
module.exports.nameFromPackage = nameFromPackage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
--- | ||
myst: | ||
html_meta: | ||
"description": "Create a theme add-on" | ||
"property=og:description": "Create a theme add-on" | ||
"property=og:title": "Create a theme add-on" | ||
"keywords": "Volto, Plone, Semantic UI, CSS, Volto theme" | ||
--- | ||
|
||
# Create a theme add-on | ||
|
||
We can create a Volto Add-on that acts as a theme Add-on, so we can detach it from the project. | ||
The advantage is that you can deploy the same theme in different projects, or have themes depending on conditions that you could inject on build time. | ||
|
||
1. Add a `theme` key in your `volto.config.js` file in the root of your project: | ||
ksuess marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```js | ||
module.exports = { | ||
addons: [], | ||
theme: 'volto-my-theme' | ||
}; | ||
``` | ||
or add a key in your `package.json` project: | ||
|
||
```json | ||
"theme": "volto-my-theme" | ||
``` | ||
|
||
2. Create a directory `src/theme` in your add-on, then add this file `theme.config`, replacing `<name_of_your_theme>` with your add-on name: | ||
|
||
```less | ||
/******************************* | ||
Theme Selection | ||
*******************************/ | ||
|
||
/* To override a theme for an individual element specify theme name below */ | ||
|
||
/* Global */ | ||
@site : 'pastanaga'; | ||
@reset : 'pastanaga'; | ||
|
||
/* Elements */ | ||
@button : 'pastanaga'; | ||
@container : 'pastanaga'; | ||
@divider : 'pastanaga'; | ||
@flag : 'pastanaga'; | ||
@header : 'pastanaga'; | ||
@icon : 'pastanaga'; | ||
@image : 'pastanaga'; | ||
@input : 'pastanaga'; | ||
@label : 'pastanaga'; | ||
@list : 'pastanaga'; | ||
@loader : 'pastanaga'; | ||
@placeholder : 'pastanaga'; | ||
@rail : 'pastanaga'; | ||
@reveal : 'pastanaga'; | ||
@segment : 'pastanaga'; | ||
@step : 'pastanaga'; | ||
|
||
/* Collections */ | ||
@breadcrumb : 'pastanaga'; | ||
@form : 'pastanaga'; | ||
@grid : 'pastanaga'; | ||
@menu : 'pastanaga'; | ||
@message : 'pastanaga'; | ||
@table : 'pastanaga'; | ||
|
||
/* Modules */ | ||
@accordion : 'pastanaga'; | ||
@checkbox : 'pastanaga'; | ||
@dimmer : 'pastanaga'; | ||
@dropdown : 'pastanaga'; | ||
@embed : 'pastanaga'; | ||
@modal : 'pastanaga'; | ||
@nag : 'pastanaga'; | ||
@popup : 'pastanaga'; | ||
@progress : 'pastanaga'; | ||
@rating : 'pastanaga'; | ||
@search : 'pastanaga'; | ||
@shape : 'pastanaga'; | ||
@sidebar : 'pastanaga'; | ||
@sticky : 'pastanaga'; | ||
@tab : 'pastanaga'; | ||
@transition : 'pastanaga'; | ||
|
||
/* Views */ | ||
@ad : 'pastanaga'; | ||
@card : 'pastanaga'; | ||
@comment : 'pastanaga'; | ||
@feed : 'pastanaga'; | ||
@item : 'pastanaga'; | ||
@statistic : 'pastanaga'; | ||
|
||
/* Extras */ | ||
@main : 'pastanaga'; | ||
@custom : 'pastanaga'; | ||
|
||
/******************************* | ||
Folders | ||
*******************************/ | ||
|
||
/* Path to theme packages */ | ||
@themesFolder : '~volto-themes'; | ||
|
||
/* Path to site override folder */ | ||
@siteFolder : "~<name_of_your_theme>/theme"; | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/******************************* | ||
Import Theme | ||
*******************************/ | ||
|
||
@import (multiple) "~semantic-ui-less/theme.less"; | ||
@fontPath : "~volto-themes/@{theme}/assets/fonts"; | ||
|
||
.loadAddonOverrides() { | ||
@import (optional) "@{siteFolder}/@{addon}/@{addontype}s/@{addonelement}.overrides"; | ||
} | ||
|
||
/* End Config */ | ||
``` | ||
|
||
3. You also have to declare it as an add-on, so don't forget to add it in the `addons` key in `volto.config.js` or in `package.json`. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
4. After starting Volto, the theme should be active and you can add now overrides to the default theme in `src/theme` as you would do it in a project. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
5. You can safely delete now your project's `theme` folder, since the one in the add-on will take precedence. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Using your own scape hatch | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Volto theming uses SemanticUI theming capabilities to define and extend a theme for your site. However, while maintaining and playing well with the Semantic UI Volto base, using a traditional CSS approach can be done using the less-based `extras` scape hatch. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
At the same time, one can entirely bail off the extras scape hatch and add your own, by customizing the `theme.js` module in Volto. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```js | ||
import 'semantic-ui-less/semantic.less'; | ||
import '@plone/volto/../theme/themes/pastanaga/extras/extras.less'; | ||
|
||
// You can add more entry points for theming | ||
import '@kitconcept/volto-light-theme/theme/main.scss'; | ||
``` | ||
|
||
While building your own scape hatch for theming, you can use the preprocessor of your choice (in the example, scss) while maintaining the "base" Volto theme, but customizing it using the resultant CSS. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
You can see an example of such a theme in: https://github.com/kitconcept/volto-light-theme | ||
|
||
## Modify a custom theme using from another add-on | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Sometimes you have a custom theme that you want to reuse through all your projects, but with some differences, maintaining the base. | ||
Usually, the only option would be to use an addon that adds more CSS to the base theme, using imports that will load after the theme. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
However, there is a problem with this approach. | ||
You cannot use existing theme variables (like breakpoints, etc) on these new CSS. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
The same way, it gets somewhat detached from the normal flow of the loaded theme. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Same applies for add-ons, they are detached from the current theme. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
One could use a SemanticUI approach for making this work, but it's SemanticUI bound. | ||
|
||
```{warning} | ||
This is only possible when using your own scape hatch, and works only with scss-based themes, and not with SemanticUI themes, since it enables a couple of entry points that only support scss files. For an example of how it could be used, see: https://github.com/kitconcept/volto-light-theme | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
If your custom scape hatch defines a custom theme using scss, you can take advantage of this feature. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Although not limited to this, it would be possible to extend this feature to add more entry points, use another preprocessor or theming approach. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
This feature enables two entry points: variables and main. | ||
From your add-on code, you can extend an existing theme in use by creating a file corresponding to each entry point: | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* `./src/theme/_variables.scss` | ||
* `./src/theme/_main.scss` | ||
|
||
### Variables (`addonsThemeCustomizationsVariables`) | ||
|
||
Use this entrypoint file to modify the original variables of the current loaded theme (by adding the entrypoint after your own variable definitions in the theme). In the theme, it should be imported like this: | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```scss hl_lines="2" | ||
@import 'variables'; | ||
@import 'addonsThemeCustomizationsVariables'; | ||
pnicolli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@import 'typography'; | ||
@import 'utils'; | ||
@import 'layout'; | ||
``` | ||
|
||
Volto will not only load your add-on entrypoints files but it will also detect all the add-ons that have these entrypoint files and import them grouped under a single file, and will add automatically an `addonsThemeCustomizationsVariables` alias that can be referenced from the theme as shown above. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Main (`addonsThemeCustomizationsMain`) | ||
|
||
This entrypoint is intended to add your own styling definitions, complementing the theme ones. You should add it after all the CSS of your theme: | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```scss hl_lines="6" | ||
@import 'blocks/search'; | ||
@import 'blocks/listing'; | ||
|
||
@import 'temp'; | ||
|
||
@import 'addonsThemeCustomizationsMain'; | ||
|
||
/* No CSS beyond this point */ | ||
``` | ||
|
||
Volto will also detect all the add-ons that have this entrypoint files and import them grouped under a single file, and will add automatically an `addonsThemeCustomizationsMain` alias that can be referenced from the theme as shown above. | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```{note} | ||
It will only work in combination with the theme declaration in `volto.config.js` or in `package.json`. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Support for declaring a theme in `volto.config.js` or in `package.json` | ||
Add two entrypoints for allowing extending a theme from other add-ons. @sneridagh | ||
sneridagh marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might want an addon to provide the theme.
The volto.config.js implies that the project is no longer throw-away, or at least there's a standard "distribution-like" volto.config.js that I use in all my projects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that would be desirable, but the current state is that you need to define the enabled
addons
list involto.config.js
or inpackage.json
anyways, so adding thetheme
is nothing that we "loose"...In fact, these (addons and theme) are the only things that you need to "save" in order of a project to be expendable. Same applies for the dockerized approach... as long as you have a
volto.config.js
that you can forward to your expendable project, you are safe.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add an option to define a theme name from an environment var. We have it already for addons iirc, so it would be a nice complement, and a very very nice addition for docker users :)