-
Notifications
You must be signed in to change notification settings - Fork 51
Support for Themes
We need to support accessibility in cordova-simulate
. Part of that is supporting high-contrast themes. Also, ideally,
cordova-simulate
should comply with the current visual style of its host. To enable both these scenarios, we will add
support for themes to cordova-simulate
.
In order to support different host environments, cordova-simulate
won't provide pre-packaged themes. Rather, it will
support the host providing a bundle of properties (colors and fonts) that it will apply. It should support providing
these properties at startup, and notifying of changes.
The host will provide a theme to cordova-simulate
as a property bundle stored in a JSON file. It will provide the path
to the JSON file as a startup option (themefile
), and cordova-simulate
will provide a method on the Simulation
object to change the theme on the fly.
The theme file is organized by element type, then element state (being the name of a state pseudo-class), then a collection of CSS properties that will be applied in that state.
The following element types are supported:
Element type | Description |
---|---|
default | Properties defined under default will be applied to any element that doesn't have that property specified. |
input | Applies to input element such as text, number and select input elements, and textarea elements. |
button | Applies to buttons. |
label | Applies to labels. |
value | Applies to read-only display of values. |
panel | Applies to the panel itself. Typically, only border and background properties are relevant. |
panel-caption | Applies to the panel caption. Typically, only font , color and background properties are relevant. |
Any state can be supplied for any element, though typically only interactive elements would have styling supplied for different states. States should be described using the appropriate pseudo-class. Multiple states may be combined with a colon (so the same properties can be applied to multiple states). An empty string is used for the default state. A simplistic theme file that only styles a button might look like this:
{
"button": {
"": {
"font": "16px normal 'Segoe UI'",
"color": "black",
"background": "white",
"border": "1px solid gray"
},
"hover:active": {
"border": "1px solid dark-gray"
},
"active": {
"background": "gray"
}
}
}
Whenever cordova-simulate
needs to apply a theme file (at startup, or when notified of a change), it will dynamically
generate a CSS file file from the theme file. The CSS file will contain the following:
- Properties defined in theme file linked to appropriate selectors
- Additional properties that may be determined by values defined in the theme file, such as layout (panel width, margins etc) which might be based on font size.
For performance reasons, the generated CSS file will be cached. The cached CSS files will be saved in the cordova-simulate
app data directory (jsUtils.getAppDataPath()
). The files will be named to make tracking easy:
<sim-host UI renderer ID>-<hash of theme file name>-<hash of theme contents>.css
Where:
-
sim-host UI renderer ID is a unique, 8 character hex id provided by the
sim-host
UI renderer. This ensures the same CSS file name is never used for different renderers, since they will be incompatible. While it is unlikely the same theme file will be provided to different renderers, this ensures no clash if that does happen. - hash of theme file name is the first 8 characters of an MD5 hash of the fully qualified theme file name.
- hash of theme contents is the first 8 characters of an MD5 hash of the contents of that file.
Look up will work as follows:
- Generate the target CSS file name using a hash of the theme file name and contents. If an existing file is found, use that and skip the following steps.
- If no existing file is found, generate the CSS file and save it.
- See if there are other CSS files with the same file theme file hash and delete them (with the assumption that they have been superseded by the new file)
Performance note: Node has hashing functions implemented in native code that are extremely fast. Hashing the file contents is not expected to have any performance impact.
A sim-host
UI renderer is responsible for the following tasks:
-
Providing information necessary to generate theme CSS file:
The
sim-host
UI renderer is responsible for renderingcordova-simulate
custom elements, and applying its own CSS. So the theme CSS we generate will be specific for a particular UI renderer. While most of the work can be done in sharedcordova-simulate
code, the renderer must provide a way to generate suitable CSS, either by:- Providing a template that core
cordova-simulate
will populate, or - Providing a dictionary that maps "element types" to selectors.
Option 1 provides more flexibility, but option 2 means more of the work is done in shared code. Option 2 is probably preferable (the added flexibility of option 1 is likely unnecessary).
- Providing a template that core
-
Referencing the theme CSS file:
The
sim-host
should refer tosim-host-theme.css
in itssim-host.html
file, after any other CSS file. -
Responding to dynamic theme changes:
The
sim-host
may by notified that the theme has changed, at which point it needs to ensure it reloads the theme CSS file.
Core cordova-simulate
code is responsible for the following tasks:
-
Generating the theme CSS file:
All the logic described above regarding generating and caching the CSS file.
-
Serving the theme CSS file:
The server will track the current theme. When the
sim-host
requestssim-host-theme.css
, it will provide the appropriate generated CSS file. -
Responding to theme changes:
When the host requests a new theme, the server will generate the new CSS file (if necessary) and notify the sim-host of the change (via a websocket message).