arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 6

UI

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

CSS

hashtag
css_overrides.css

Configure the css_overrides.css file in the assets/ folder of your overlay_dir

The file is empty by default. To override the css variables used in the applications see all the default values below. Note, if you wish to only override for example the button background color you do not need to include the rest of the variables.

hashtag
Default values/available variables

hashtag
Examples

Example: To update the button backgrounds define in your css_overrides.css:

Example: To change background image

Make sure image is available in the assets folder (using the overlay method preferably) and define in your css_overrides.css

UI Configuration Overrides

This is how overrides of ui_config should be done in all frontend apps/auth.

hashtag
Configure the ui_config_overrides.json

Use overlay to provide the custom file and place the file in <overlay_dir>/assets/ui_config_overrides.json.

The data in ui_config_overrides.json will be merged with the default values.

Overview

The UI can be adapted to the look and feel of the organisation style.

:root {
  --color-button-background: #ffe4c4;
  --color-button-background-hover: rgb(143 188 143);
  --color-button-text: #32cd32;
  --color-button-text-hover: #00fa9a;
}
:root {
  --color-primary: #024550; /* primary color */
  --color-accent: #00cc7e; /* accent color */

  --color-background: #181830; /* background color, used as fallback color if no background image is used. */
  --color-surface: #ffffff; /* surface color. used for cards and such typically where text appear */
  --color-backface: #f5f5f5; /* backface color, used behind cards and other surfaces */
  --color-on-primary: #ffffff; /* color that contrasts when used on color-primary, typically text on primary backgrounds */
  --color-on-surface: #024550; /* color that contrasts when used on color-surface, typically text on surface backgrounds */
  --color-on-accent: #ffffff; /* color that contrasts when used on color-accent, typically text on accent backgrounds */

  --color-link: #045e6c; /* link color */
  --color-link-hover: #058194; /* link color when hovered */
  --color-link-disabled: #bcbcbc; /* link color when disabled */

  --color-button-background: #181830; /* button background color */
  --color-button-background-hover: #c7f3aa; /* button background color when hovered */
  --color-button-background-disabled: #d4d4d4; /* button background color when disabled */
  --color-button-text: #ffffff; /* button text color */
  --color-button-text-hover: #181830; /* button text color when hovered */
  --color-button-text-disabled: #181830; /* button text color when disabled */

  --color-warning: #c24b1d; /* warning text/icon color */

  --button-radius: 0rem; /* button border radius, default no radius */
  --button-border: none; /* button border, default none, example: --button-border: 1px solid --color-primary; or --button-border: 1px solid #fa8072; */
  --button-border-hover: none; /* button border when hovered, default none. example: --button-border: 1px solid #8fbc8f; */

  --color-button-secondary-background: transparent; /* secondary button background color */
  --color-button-secondary-background-hover: transparent; /* secondary button background color when hovered */
  --color-button-secondary-text: var(--color-on-surface); /* secondary button text color, inherits from palette */
  --color-button-secondary-text-hover: var(--color-on-surface); /* secondary button text color when hovered, inherits from palette */
  --color-button-secondary-background-disabled: transparent; /* secondary button background color when disabled */
  --color-button-secondary-text-disabled: #9ca3af; /* secondary button text color when disabled, default gray-400 */
  --button-secondary-border: 1px solid #d1d5db; /* secondary button border, default gray-300 */
  --button-secondary-border-hover: 1px solid #9ca3af; /* secondary button border when hovered, default gray-400 */
  --button-secondary-border-disabled: 1px solid #e5e7eb; /* secondary button border when disabled, default gray-200 */

  --background-image: url('bg_login.svg') no-repeat center center/cover fixed; /* background image, used behind surface and backface. typically for authentication pages */
  /* image can be svg, png, jpg, jpeg, gif, webp, etc. The image will scale to fill the entire screen but maintain ratio if using the no-repeat center center/cover fixed */
  /* Image should be of size 1920x1080 and size optimized for web for best results  */
  /* apps such as Portal/Password Reset etc will have --background-image: none; as default and only use background color */
  --background-fallback-color: var(--color-background); /* background color, used as fallback color if no background image is used or if loading slowly */

  --color-header-background: var(--color-primary); /* header background color, mainly used in apps such as Portal/Password Reset etc. Default the --color-primary variable is used */
  --color-header-text: var(--color-on-primary); /* header text color, mainly used in apps such as Portal/Password Reset etc. Default the --color-on-primary variable is used */

  --color-progress-filled: var(--color-primary); /* progress bar filled color */
  --color-progress-background: #e2e8e9; /* progress bar background color/(not filled color) */

  --color-loader-indicator-bottom: var(--color-primary); /* loader indicator bottom color, mainly used in authentication pages */
  --color-loader-indicator-middle: var(--color-accent); /* loader indicator middle color, mainly used in authentication pages */
  --color-loader-indicator-top: rgb(from var(--color-surface) calc(r - 5) calc(g - 5) calc(b - 5) / 0.2); /* loader indicator middle color, mainly used in authentication pages */

  /* shadcn/ui Table component variables */
  --muted: 210 40% 96.1%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --border: 214.3 31.8% 91.4%;

  --destructive: oklch(0.577 0.245 27.325);
  --destructive-foreground: oklch(0.577 0.245 27.325);

  --input: oklch(0.922 0 0);
  --ring: oklch(0.708 0 0);

  /* Table-specific tokens for consistent styling across shadcn DataTable and MUI TableComponent */
  --table-header-bg: var(--color-primary);
  --table-header-text: var(--color-on-primary);
  --table-row-hover: rgb(229 231 235); /* neutral-200 */
  --table-row-selected: rgb(229 231 235); /* neutral-200 for selected state */
  --table-row-selected-text: inherit;
  --table-border: var(--border);

  --background: var(--color-backface);
  --foreground: var(--color-on-surface);
  --card: var(--color-surface);
  --card-foreground: var(--color-on-surface);
  --popover: var(--color-surface);
  --popover-foreground: var(--color-on-surface);
  --primary: var(--color-primary);
  --primary-foreground: var(--color-on-primary);
  --secondary: var(--color-accent);
  --secondary-foreground: var(--color-on-accent);
  /* --muted: var(--color-backface); */
  /* --muted-foreground: var(--color-on-surface); */
  --accent: var(--color-accent);
  --accent-foreground: var(--color-on-accent);
  /* --destructive: var(--color-destructive);
  --destructive-foreground: var(--color-on-destructive); */
  --border: var(--color-border);
  --input: var(--color-input);
  --ring: var(--color-ring);
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --color-chart-1: var(--chart-1);
  --color-chart-2: var(--chart-2);
  --color-chart-3: var(--chart-3);
  --color-chart-4: var(--chart-4);
  --color-chart-5: var(--chart-5);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --color-sidebar: var(--sidebar);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
}

/* @layer base {
  * {
    @apply border-border outline-ring/50;
  }
  body {
    @apply bg-background text-foreground;
  }
} */

html {
  color: var(--color-on-surface); /* default text color */
  background-color: var(--background-fallback-color); /* default background color (used as fallback before image loads). */
  background: var(--background-image), var(--background-fallback-color); /* Background defaults to use background image, mainly used in authentication pages, and color otherwise while image loads. If only the color will be used you can just use fallback-color or define the color directly. example: background: #ffdab9; */
  font-family:
    'Inter',
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    Helvetica,
    Arial,
    sans-serif,
    'Apple Color Emoji',
    'Segoe UI Emoji',
    'Segoe UI Symbol';
}

@supports (font-variation-settings: normal) {
  html {
    font-family:
      'Inter var',
      -apple-system,
      BlinkMacSystemFont,
      'Segoe UI',
      Roboto,
      Helvetica,
      Arial,
      sans-serif,
      'Apple Color Emoji',
      'Segoe UI Emoji',
      'Segoe UI Symbol';
  }
}
:root {
  --background-image: url('new_background_image.png') no-repeat center center fixed;
}

Name
Description
Default value

logos

An object containing logos for app_logo (top bar of apps like forms and portal), and access_header and access_footer for Access authentication apps

"assets/fortified_logo_green.svg"

logos.app_logo/logos.access_header/logos.access_footer

Logo objects. All logos are configured in the same way. Properties below are for all logos (app_logo, access_header and access_footer). Can be configured as false to disable the logo. Example: { "logos": { "access_header": false } [...]} See next section for more information about logos.

{
  "variables": {},
  "

hashtag
Logo Configuration

All logos are configured as follows:

All logos can be made into links.

For example, BankID has the following default configuration, where it has BankID's logo at the top (with some negative margins because it has so much whitespace in it and we have our own margins otherwise):

hashtag
Advanced Configuration

If you want or need to have the same overrides file for several apps, you can also configure more advanced for all apps (password_reset, forms, portal, enrollment), all access (bidomd selector etc) and all infoendpoint by scoping as below. You can also make configuration for a specific app/auth/infoendpoint.

hashtag
Variables in Config

If variables are defined in the variables object, all instances of the variable will be replaced in the output to the browser. Note: since search and replace are used for variables, use caution when naming the variables. Use for example __VARIABLE_NAME__ as naming convention to avoid unexpected bugs.

Overlay

All applications providing UI implement the same pattern regarding styling.

hashtag
Configure the overlay folders

In order to make the application read the custom files instead of the default files the configuration parameter overlay_dirs must be used.

Add parameter "overlay_dirs":

{
  "logos": {
    "app_logo": {
      "src": "assets/fortified_logo_green-white.svg",
      "height": "40px"
    },
    "access_header": {
      "src": "assets/fortified_logo_green-teal.svg",
    },
    "access_footer": {
      "src": "assets/fortified_logo_green-teal.svg",
      "height": "40px",
      "link": {
        "url": "https://fortifiedid.se",
        "text": "FortifiedID"
      }
    }
  }
}
{
  "logos": {
    "access_header": {
      "src": "assets/svg/logo_bankid.svg",
      "link": false, //or omit 
      "width": "14rem",
      "margin": "-2.5rem auto -0.5rem auto"
    },
    "access_footer": {
      "src": "assets/fortified_logo_green-teal.svg",
      "size": "40px",
      "link": {
        "text": "",
        "url": "https://fortifiedid.se"
      }
    }
  },
  // ... remaining configuration with title etc.
}
{
  "logos": {
    "access_header": { ... },
    "access_footer": { ... }
  },
  "title": "Acme", // all get this title, even pwd_reset for example
  "access": {
    "title": "Acme IdP", // all Access get this
    "logos": {
      "access_header": { ... } // more specific. all Access auth apps will get a designated header logo
    }
  },
  "bidomd": {
    "logos": {
        "access_header": "default" // most specific, will become the Bankid logo which is default 
    },
    "title": "Acme BankID" // bidomd gets this title
  },
  "selector": {
     "logos": {
         "access_header": false // most specific, turn off the upper logo only on the selector
     }
  }
  // ... remaining configuration with title etc.
}
{
  "variables": {
    "__NAME__": "Acme"
  },
  "title": "__NAME__ title" // becomes "Acme title" in the browser
}

Accessibility/A11y

Fortified ID aims to make applications that are usable for all.

Fortified ID uses the guidelines of WCAG 2.1 to make content more accessible to a wider range of people with disabilities.

WCAG defines four principles that provides the foundation of making a website/application accessible: that it is Perceivable, Operable, Understandable, Robust.

Examples of how Fortified user interfaces are designed according with accessibility/a11y in mind:

1. Perceivable – Information and user interface components must be presented in ways that users can perceive. For example, providing alternative text for images and ensuring clear color contrasts.

2. Operable – The user interface and navigation must be usable by all, regardless of physical or cognitive ability. This includes keyboard navigation support and avoiding content that may trigger seizures or other health issues.

3. Understandable – Content and interface must be understandable for users, which means clear language, predictable navigation, and explanations where necessary.

4. Robust – Content must be robust enough to work with a variety of assistive technologies and future user agents.

logos
"
:
{
"app_logo": {
"src": "assets/fortified_logo_green-white.svg",
"size": "40px"
},
"access_header": {
"src": "assets/logo.svg",
"link": false
},
"access_footer": {
"src": "assets/fortified_logo_green-white.svg",
"size": "80px",
"link": {
"url": "https://fortifiedid.se"
}
}
},
"supportedLanguages": [
{
"code": "en",
"name": "English"
},
{
"code": "sv",
"name": "Svenska"
}
],
"title": "Fortified ID",
"localesMergePath": "",
"fallbackLanguage": "sv"
}

logos.app_logo.src

The src of the bottom vendor logo. If undefined or empty string "" no logo will be shown

logos.app_logo.width

The width of the logo. Use css values like "40px"

"auto"

logos.app_logo.height

The height of the logo. Use css values like "40px"

"100%"

logos.app_logo.link

Link object. Can be configured as false to disable

logos.app_logo.link.url

logos.app_logo.link.text

If undefined or empty string "" no link text will be shown

""

supportedLanguages

List of supported languages. If a language is specified here it is assumed to be available under the folder assets/locales/<code>.json See more in section below

title

Browser tab title

"Fortified ID"

localesMergePath

Path for merging locale files. If omitted or empty string "" is used no locale merging will be done. Important: must end with /

""

fallbackLanguage

Default/fallback language if user has not saved a language in cookies

"sv"

<path_to_custom_directories
>
.

Simple example from a Forms config.

In the custom directory create a folder, "assets".

hashtag
Favicon

in the assets folder of your overlay_dir, place the favicon.ico.

{
  "name": "Forms",
  "config": {
    "http_context": "/forms",
    "logout_endpoint_url": "/forms/logout",
    "overlay_dirs": ["config/locale_overlay", "config/ui_overlay"],
    "flows": "@include:../flows/*/flow.json"
  }
}
[
    {
      "code": "en",
      "name": "English"
    },
    {
      "code": "sv",
      "name": "Svenska"
    }
]

Language translations

hashtag
Customizing translations

All text that is displayed can be customized. The default locale file contains standard translations and can be changed and extended by future updates. Use the overlay method to override the default locale file with a custom file. The default file will be merged with the custom file, with the keys in the custom file taking precedence.

hashtag
Add more languages

Default provided languages are English and Swedish. Language files must be present in <overlay_dir>/assets/locales/ E.g. assets/locales/en.json

To add more languages add to the array in supportedLanguages and place file (using overlay method) in locales folder. E.g. add the following to the supportedLanguages array {code: 'de', name: 'Deutsch'} and add a file called assets/locales/de.json

hashtag
Custom translation keys

To customise translations use localesMergePath to extend and merge with the provided default files.

hashtag
Example of a custom extension/merge:

Default language file contains the translations keys

The overlay_dir contains a ui_config_overrides.json with localesMergePath: "assets/custom_locales/" (See )

A file is placed in <overlay_dir>/assets/custom_locales/en.json containing the following:

The resulting merged language file used in the application will contain the following:

For each language that will be customised, add language files <overlay_dir>/assets/custom_locales/<lang>.json

hashtag
Scoped Translation Strings with Prefixing

You can scope your translation strings by prefixing them with the last segment of a path. This allows you to define translation strings that are specific to a particular page or context.

Example for Path-Based Prefixing

For example, given the path:

You can prefix your translation strings with the last part of the path, selector_root, to create translations specific to that page:

Add these translations to your translation file, and they will only apply to the specified path.

Forms Prefixing with Control IDs

For forms, you can also choose to scope translations by using a part of the path as described above or by prefixing with a control ID. This approach helps localize translations at a finer level of granularity for specific form elements.

Example of a control ID-based prefix:

This flexibility in prefixing allows you to maintain organized and context-aware translations across your application.

Overlay
{
    "selector.header": "Choose authentication method",
    "selector.error": "An error occured",
    "change_language": ""
}
{
    "selector.header": "A different header"
}
{
    "selector.header": "A different header",
    "selector.error": "An error occured",
    "change_language": ""
}
https://dev.fortifiedid.se/saml/authn/selector_root/
{
  "selector_root.selector.header": "A header specific to this page"
}
{
  "min_control.forms.multiselectwidget.removed_item": "Item removed from the multiselect widget"
}