UI Assets Overrides
All the assets served to the UI of Hanami can be overridden. For this, one would need to add to their customer.yml
file something like this:
local:
assets:
folder: /opt/hanami/ext/override
Like this, files in the /opt/hanami/ext/override
folder will be put in the folder serving UI assets. This could override any file in there even index.html
, but we recommend to not blindly override any random file. Instead, we procure here a list of usual overrides that serves dedicates purposes.
i18n files
By default, Hanami loads 2 files when rendering the application in a given language. For example when the application is in English, it loads assets/i18n/en.json
and assets/i18n/en.customer.json
. Those files are holding most of the labels used in the application, structured in deep string maps that serves as keywords to map to labels. For example part of en.json
looks like this:
{
"global": {
"cancel": "Cancel",
"close": "Close",
"collection": "Collection",
"copy_uri": "Copy URI",
"created": "Created",
"delete": "Delete"
},
"some_other_key": {
"that_can_go": {
"super_deep": "foo",
"something": "else"
}
}
}
Which means that, when the interface is trying to find a label for the key some_other_key.that_can_go.super_deep
, it will print the label foo
. And for some_other_key.that_can_go.something
, it will print else
.
Now considering en.customer.json
. By default, it is served as an empty json {}
and so will not have any impact. But let's say that we configured the override by using the opt/hanami/ext
folder, then one could add there /opt/hanami/ext/assets/i18n/en.customer.json
that would look like this:
{
"some_other_key": {
"that_can_go": {
"super_deep": "bar"
}
}
}
With this, when the interface will try and display a label for some_other_key.that_can_go.super_deep
, it will print the label bar
. And since we are doing a deep merge of the 2 maps, some_other_key.that_can_go.something
will still be printed as else
.
Customer specific keywords
If you need to add new keywords to the translation map, we advise to put them under a dedicated customer
to be sure to not accidentally override keywords used elsewhere in the application. Then a typical en.customer.json
file would look like this:
{
"customer": {
"my_custom_key": "Hello World"
}
}
This is especially useful when configuring other Hanami features that make use of translation labels, like workflow actions or footer links labels (see below).
UI Config file
An other file that is loaded on start is assets/config.json
, and by default it is an empty json {}
. Put properties can be added to it to configure some features.
Header
When overriding assets/config.json
, one could set some properties as below:
{
"header": {
"app_title": "customer.header.app_title",
"app_subtitle": "customer.header.app_subtitle",
"navMode": "bar",
"logo": {
"src": "assets/img/logo.png",
"alt": "customer.header.logo_alt",
"width": 81,
"height": 45
},
"links": [
{
"labelKey": "customer.footer.data_catalogue",
"url": "http://ep-catalog-dev-app.sysadmin.garden:8080"
}
]
}
}
The header can have a few properties set:
app_title
: The title od the application, if you desire to override the default "Hanami". Please note that we are using keywords here, and so related translations should be provided in the i18n files as explained above.app_subtitle
adding a second line to the title, styled differentlynavMode
: specify the way the navigation bar behaves in the header. There are multiple possible values:bar
: display the navigation items directly in the headerburger
: display the navigation items in a "burger menu" that can be opened from the left of the application logohybrid
: An in-between solution wherebar
is used on the home page, andburger
on most others. This configuration is not considered a11y friendly at the moment, so we advise against it for now.
logo
: specify which logo to use instead of the default one. All properties here are needed:src
: url to the image to be loadedalt
: descriptive text to add to the image, especially useful for users making use of screen readers.width
: width the image should take, in pixelsheight
: height the image should take, in pixels
links
: list of link to be added to the header, giving them alabelKey
and aurl
to reach.
Footer
Similarly to the header, the footer can be configured in a similar fashion, having also links
and a logo
parameters:
{
"footer": {
"logo": {
"src": "assets/img/footer-logo.png",
"alt": "customer.footer.logo_alt",
"width": 236,
"height": 35
},
"links": [
{
"labelKey": "customer.footer.google",
"url": "https://google.com"
},
{
"labelKey": "customer.footer.send_feedback",
"url": "mailto:feedback@domain.com"
}
]
}
}
Styles
Finally, one can configure the injection of custom css files, like so:
{
"styles": {
"files": ["assets/styles/customer.css"]
}
}
You can then put any styling that you want there and customize Hanami to your heart's content. For now, we advise to limit this customization only through overriding css variables, for example like so:
:root {
--font-family-main: "Helvetica", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--color-primary: #0d6efd;
--color-primary-dark: #0d5286;
--color-primary-intense: #0d5286;
--color-secondary: #6b31a5;
--color-secondary-intense: #360c50;
}
Here is the list of variables that we advise to first override if the need arises:
:root {
/* Primary colors, used in most places */
--color-primary: var(--color-blue-intense);
--color-primary-dark: var(--color-blue-dark);
--color-primary-light: var(--color-blue-light);
--color-primary-bg: var(--color-blue-bg);
--color-primary-hover: var(--color-blue-hover);
--color-primary-disabled: var(--color-blue-disabled);
/* border colors, depending on the desired intensity */
--color-border-soft: var(--color-gray-10);
--color-border-hard: var(--color-gray-50);
/* A secondary palette of colors, used as an accent color to draw attention to some parts of the page */
--color-secondary: var(--color-violet);
--color-secondary-bg: var(--color-violet-bg);
--color-secondary-intense: var(--color-violet-intense);
--color-secondary-light: var(--color-violet-light);
--color-link: var(--color-primary);
/* color of fonts used, high is usually for titles, medium is for more discreet texts. Light is really rarely used */
--color-font-high: var(--color-dark);
--color-font-medium: var(--color-gray-70);
--color-font-light: #686868;
/* Color used for error state, like inlined errors in forms, or error prompts */
--color-error: var(--color-red);
/* Color used for warning state, mostly ever used in rare warning prompts prompts */
--color-warning: var(--color-orange-intense);
/* Colors used for success state, mostly for success toasts after an async operation succeeds (like a creation/save) */
--color-success: var(--color-green);
--color-success-bg: var(--color-green-bg);
/* Fonts to be used in the application */
--font-family-main: "Inter", sans-serif;
--font-family-secondary: "Inter", sans-serif;
}
Other styling could be added fo course, but then we advise to use components tag names to somewhat limit the scope of the customization. For example one could add something like this:
hanami-page-title .hanami-page-title-content {
color: var(--color-primary) !important;
font-weight: 400 !important;
font-family: var(--font-family-secondary) !important;
}
It is to be noted that styling outside of css variables could break on new Hanami releases, so custom styling should ideally be kept to a minimal set of change.