Kando allows you to create custom themes for the menus. A theme defines several layers which will be painted on top of each other for each menu item. Depending on the menu item’s state (e.g. active, child, parent, hovered, etc.), the layers can be styled differently using CSS.
Creating Menu Themes
Menu Theme Locations
If you want to create a new menu theme, you should put a new subdirectory into the menu-themes
directory.
The location of this directory depends on your operating system:
If you are running Kando from the source code via npm start
, it will also look for themes in the assets/menu-themes/
directory.
Anatomy of a Menu Theme
This section will give you an overview of the files you need to create a new menu theme. Thereafter we will have a look at the individual parts in more detail.
Directorykando
Directorymenu-themes
Directorymy-theme
- theme.json5
- theme.css
- preview.jpg
- REUSE.toml
Directoryassets/ You can put any fonts or images your theme uses into a subdirectory.
- …
theme.json5
contains metadata about the theme and a list of layers which will be created for each menu item.
Each layer gets a specific class name which can be used in the CSS file to style the layer.
theme.css
can contain any CSS code you like. With CSS selectors, you can choose which layers to style in which way.
The CSS file can reference assets like images or fonts. These can be placed in the same directory as the JSON and CSS files or in a subdirectory.
preview.jpg
is a square-shaped image which will be shown in the menu editor to preview the theme.
REUSE.toml
is not strictly necessary, but it is recommended to include it in your theme directory. It contains information about the license of your theme.
Metadata and Layer Description
Below you can have a look at the theme.json5
file of the default theme.
The keys are explained with inline comments.
Most of it will be clear, but some keys might need a bit more explanation.
We will have a look at the colors
and layers
keys in the following sections.
colors: {}
The colors
object lists colors which can be configured by the user in the menu editor.
Each entry maps a CSS color to a given color name.
In your CSS file, you can use the colors with var(--<key>)
.
In the menu editor, the user can change the value of these colors.
layers: []
This is maybe the most important part of the metadata file. It describes the div elements which will be created for each menu item. The layer will be drawn top-to-bottom in the order they are defined in the JSON file. So the first layer will be the topmost layer, and the last layer will be the bottommost layer.
Each layer has a class
and a content
key.
The class
key is used in the CSS file to style the corresponding div element.
The value for the content
key is a string.
For now, these content strings are limited to the following values:
Content Type | Description |
---|---|
"none" | The layer will not contain any additional content. This is for instance useful for simple background layers. You can also assign a background-image to the layer in the CSS file. |
"icon" | The layer will contain a nested .icon-container element for this menu item. For a simple theme, a single layer of this type is usually enough, as you can style the layer to have a background color, border, drop shadow, etc. |
"name" | The text content of the layer element will be the name of the menu item. |
However, keep in mind that the menu rendering performance will generally be better if you use fewer layers.
Styling of the Layers
The theme.css
file is where you define how the layers are styled.
Using CSS selectors, you can style the layers differently depending on the menu item’s state.
Each menu item has the class .menu-node
and will have child elements for each layer you defined in the JSON file.
So for instance the following will style the .icon-layer
of the currently active menu item:
CSS Classes of the Menu Items
Kando assigns a lot of CSS classes to each menu-item element based on the current state of the menu item (child, center, parent, hovered, etc). This allows you to style the menu items differently depending on their state. The overall tree structure of the menu may look like this:
In this example, the menu container contains two elements: The center text and the root item of the menu.
The center text shows the name of the currently selected item.
It is automatically moved to the currently active menu item.
In the above case, the root item contains three submenus.
The third child is a submenu which is currently open (.active
).
Therefore the root item is a .parent
and the other two children are drawn as .grandchild
.
The .active
child has four children itself, two of which have grandchildren.
The second child is currently .dragged
in marking mode.
It also is .hovered
by the mouse cursor.
In addition, each menu node has a class for the current level (.level-0
, .level-1
, .level-2
, etc).
This can be used to style the menu items differently depending on their depth in the menu tree.
Only the root item has the class .level-0
.
Furthermore, the menu node classes contain the type of the item (.type-submenu
, .type-uri
, .type-command
, etc).
This can be used to style different item types differently.
Last but not least, each menu node has a class for its approximate direction relative to the center of the menu (.top
, .right
, .bottom
, .left
). Escept for the root node, which is always in the center.
Not depicted in the tree structure above are the connector lines between the menu items and the layers added by the theme.
The connector lines are long divs which are appended to each submenu menu node.
They have the class .connector
and can be styled as well.
CSS Properties of the Menu Items
In addition to the colors specified in the theme’s JSON file, Kando sets some custom CSS properties on some .menu-node
and layer div elements.
Menu Node Properties
The following properties are available on some .menu-node
elements.
See the details for each property to find out on which elements they are available.
Available on all elements with the --dir-x
and --dir-y
.menu-node
class except for the root node.
The normalized x and y direction of the menu item relative to the parent menu item.
If the item is on the right side, the x-direction will be 1
, if it’s on the left, it will be -1
.
The same applies to the y-direction, but with the top being -1
and the bottom being 1
.
This is usually used to position the item correctly around the parent.
Available on all elements with the --angle
.menu-node
class except for the root node.
The angle of the item in degrees, starting at the top with 0° and going clockwise. This is useful if you want to rotate a layer with respect to the item’s position.
Available on all elements with the --siblings-count
.menu-node
class except for the root node.
The number of child items the item’s parent has. This can be used to increase the child item distance if there are many children.
Available on all elements with the --parent-angle
.menu-node
class except for the root node and the direct children of the root node.
The angle of the parent item relative to its parent in degrees, starting at the top with 0° and going clockwise. This is useful for styling grandchildren as this will be the same as the --angle
property of the child.
Available on all elements with the --angle-diff
.menu-node.child
classes. That is, all children of the currently active menu item.
The angular difference between the item and the direction towards the mouse pointer. This is useful if you want to create some kind of fisheye effect when the mouse pointer is close to the item.
Center Layer Properties
These properties are available on all your layer divs attached to the current center menu item.
That is, all layers attached to the menu node with the .menu-node.active
classes.
The angle towards the mouse pointer in degrees, starting at the top with 0° and going clockwise.
You can use this to rotate a layer towards the mouse pointer.--pointer-angle
The angle towards the currently hovered item in degrees, starting at the top with 0° and going clockwise.
If the center is hovered, this will be the direction towards the parent item (if there is any).
You can use this to rotate a layer towards the hovered item.--hover-angle
The same as --hovered-child-angle
--hover-angle
, but if the center is hovered, this will not be updated.
Styling the Layers
You can now use CSS selectors to style each of these elements.
Usually, you will want to apply a transformation to the .menu-node
elements to position them correctly on their position around the center.
Appearance properties like background-color
, border
, box-shadow
, or filter
are usually applied to the layer elements.
Here’s how the theme.css
file of the default theme looks like:
You should have a look at this default theme to get an idea of how to style the menu. It is maybe a good idea to start with a copy of the default theme and modify it to your needs. You can also have a look at the other included themes for inspiration, most of them use more than one layer.
Another good theme to get started with is the very simple Minecraft Theme available in the Kando Menu Themes Repository.
Useful CSS Selectors
Here are some CSS selectors which you may find useful. Feel free to add more selectors to this list if you find something useful!
A Preview for your Theme
preview.jpg
should be a square screenshot of a menu with the theme applied.
You can use a custom background to suit your theme.
The menu should be shown in the center of the image, the default themes use a resolution of 700x700 pixels, but Kando will scale the image to fit the preview area in the menu editor.
Adding Proper Credits
A theme usually builds upon the work of others. Therefore, it is important to give proper credit to the original authors! All the assets you use in your theme may be subject to copyright and may be licensed under different terms.
If you choose to submit your theme to the Kando Menu Themes Repository, you should make sure that your theme follows the REUSE specification. As a theme author, it is your responsibility to make sure that there is proper license and copyright information for each file of your theme. You can follow the existing themes as examples.
Where should I put the license information?
For text files like .json
or .css
, you can simply add an SPDX license header at the top of the file. This can look like this:
For binary files like images or fonts, you should create a REUSE.toml
file in your theme directory.
You can have a look at this file for an example.
What is a valid SPDX-FileCopyrightText?
- For files you copied from others, you should use the original author’s copyright text.
- For files you created yourself, the copyright text should ideally be your name and email address. If you do not want to share this publicly, you can also use a pseudonym. It would be great if it was possible to contact you in case there are questions about your theme. So maybe using a Discord handle or a GitHub username is a good idea in this case.
- For files you modified, you should add your own copyright line above the original one. There can be multiple
SPDX-FileCopyrightText
in each file.
Which SPDX-License-Identifier should I choose?
If you copied a file from somewhere else, you usually have to use the same license as the original file. There exceptions to this rule, but it is usually a good idea to stick to the original license.
If you created a file yourself, you can use any license you like. For artwork like themes, the Creative Commons licenses are often a good choice. Here are some examples:
- If folks should be able to use your file however they like, you can use the
CC0-1.0
license. - If you want to be credited, you can use the
CC-BY-4.0
license. - If you want to force others to use the same license for their modifications, you can use the
CC-BY-SA-4.0
license.
As a rule of thumb, we would recommend using the CC0-1.0
license for simple configuration files like your theme.json5
file and another Creative Commons license like CC-BY-4.0
for your artwork.
Distributing your Theme
You are invited to show your themes in Kando’s Discord Server! You can also contribute your themes to the Kando Menu Themes Repository by creating a pull request.