- Full-width header and footer
- Full-width components
- Common Header
- Common Footer
- Common SVG Icons (a web-specific subset of OCHA humanitarian icons)
- Variables for breakpoints, colours, font sizes, fonts, and z-index
- Mixins for clearfix and media queries
- Custom javascript for dropdown behaviour
- See v3.0.0 Release notes and common_design implementation notes for v2 for more detailed documentation
There is a sub theme included in this repo.
- This can be used as a starting point for implementations. Add components,
override and extend the base theme as needed. Copy the common_design_subtheme
directory to
/themes/custom/
and refer to its README. All the implementation-specific work should happen in the sub theme.
Drupal components:
- normalize-css library is included in Drupal core
- jQuery is included in Drupal core but is not loaded globally. We include it as a library only when we need it.
- hidden.module.css is included in Drupal core for display-related utility classes
Additional components:
- Typography
- Component library
- HTML/CSS/JS components that can be attached as Drupal libraries to twig templates, or copied into sass partials.
- Requires Drupal Components module.
- See Common Design demo for Component examples.
- Refer to Components README and the components used in the theme.
- Favicons and OCHA branded assets based on https://brand.unocha.org
- Node workflow for frontend development
- SASS
- Sourcemaps (to show which specific Sass file contains styles during local development)
- Autoprefixer
- Sass and JS linting
- SVG sprite
- E2E tests
- Clone this repo to
/themes/contrib/
or install usingcomposer require unocha/common_design
. - Copy the
common_design_subtheme
directory to/themes/custom/
. - In the Drupal Admin, go to Appearance, find 'OCHA Common Design sub theme' and select Enable and set default.
To contribute to common_design
base theme or sub theme development and/or to customise the sub theme
- Run
nvm use
in theme folder to ensure the correct node version. - Install the dependencies:
npm install
- For development, run
npm run sass:watch
(this includes an initial linting and sourcemaps) or runnpm run sass:compile-dev
to compile. - Run
npm run sass:build
for final CSS generation. - For twig debug and local development see Disable Drupal 8/9 caching during development.
Drupal 8/9 core have helper classes for accessibility. Hide content properly using official drupal.org docs.
This project uses Sass. To make changes edit the .scss
files in the sass/
folder, do NOT edit the files in css/
directly.
npm run sass:build
— compile production-ready CSS.npm run sass:watch
— watch for changes and automatically rebuild the CSS during local development.npm run sass:lint
— linting report only.npm run sass:lint-fix
— linting report, plus automatically fix any errors that the tool can safely handle.
The stylelintrc.json
config file extends Drupal core stylelint config. Run npm install
in your site's html/core
directory to install the stylelint plugins if there are errors indicating missing packages.
When possible, use Jenkins to run the sass:build
task on build to generate the CSS within your website's deploy job.
Follow Drupal CSS coding standards and best practices
Javascript files should be added to js/
and defined as a library in common_design.ibraries.yml
Instead of grouping all JS in one file, each component has its own JS file associated with it. They have been built to be reused, allowing you to mix and match any combination of JS files and use each as a dependency without altering the original file. The general pattern to reference the method of a behavior is:
// Use a method called "methodName" inside the same Behavior file
this.methodName();
// Use a method called "methodName" defined in cd-dropdown.js
Drupal.behaviors.cdDropdown.methodName();
Using this
works for most functions except ones which are assigned to event listeners. For those, we have prefixed all of them with the word handle
— and despite being contained within the same Behavior, you'll need to reference internal functions using the full Behavior name (see second example above, as if it were outside your Behavior).
(function (Drupal) {
'use strict';
Drupal.behaviors.exampleBehavior = {
attach: function (context, settings) {
// Assign handleClick as an event listener. When assigning the handler
// it is correct to prefix the method name with `this`
document.addEventListener('click', this.handleClick);
},
sendAlert: function (message) {
window.alert(message);
},
handleClick: function (ev) {
// ❌ WRONG:
//
// Inside this event listener handler, we do not have access to the
// Behavior object as `this` so this.sendAlert() will not be defined
// and the following error will occur:
//
// Uncaught TypeError: this.sendAlert is not a function
this.sendAlert(ev.target);
// ✅ CORRECT:
//
// Referencing the Behavior as defined in Drupal object will work.
Drupal.behaviors.exampleBehavior.sendAlert(ev.target);
}
};
})(Drupal);
Follow Drupal JS coding standards and best practices
This projects defines a few CSS Vars for font-families that use Google Fonts. The actual fonts must be loaded by enabling them individually (see below). You can read official guidance on OCHA's visual identity website.
Here are the technical details relating to the theme itself:
- Roboto is included by default as a sass partial in
sass/base/_fonts.scss
and imported instyles.scss
. This means Roboto font is compiled as part ofstyles.css
- Additional fonts for advanced typography and other languages which don't use Latin character sets are available as Drupal Libraries. The list is defined in
common_design.libraries.yml
. For performance reasons, we do not include these by default. If your website must support character sets that are not included in the base-theme, refer to the sub-theme's Libraries filecommon_design_subtheme.libraries.yml
to see a commented-out example helping you create your own Drupal Library.
The fonts can be enabled one of two ways.
First, in the common_design_subtheme
by adding the relevant base-theme libraries as a dependency to the global styles in the common_design_subtheme.libraries.yml
:
global-styling:
css:
theme:
css/styles.css: {}
dependencies:
- common_design/fonts-advanced
- common_design/fonts-arabic
- common_design/fonts-chinese
- common_design/fonts-russian
Second, you can also enable them in the Drupal Admin UI under the sub-theme theme settings at /admin/appearance/settings/common_design_subtheme
.
This project uses some Node packages for Sass compilation, watching and linting, JS linting and SVG icon sprite generation. See scripts in package.json.
To get a list of commands, do npm run
and it will output all possible options.
The available icons can be found in img/icons
There are two techniques used, SVG symbol sprite with the <use>
element, and SVG as a background-image, depending on context. The sprite technique is preferred. We only use svg as a background image when using the sprite isn't possible.
SVG symbol sprite with the <use>
element. The SVG sprite is loaded as a single asset in the html.html.twig
before the closing body tag. Each icon within the sprite can be referenced by its ID eg.
<svg class="cd-icon cd-icon--arrow-down" width="16" height="16" aria-hidden="true" focusable="false">
<use xlink:href="#cd-icon--arrow-down"></use>
</svg>
Each icon should have the class cd-icon
and a BEM selector if needed e.g. cd-icon--arrow-down
. We can create associated CSS rules to control dimension and fill.
Each icon should have reasonable width and height attribute values. These control the SVG display when the CSS is slow or does not load. If the icon is decorative, add aria-hidden="true" focusable="false"
to remove the element from the accessibility tree.
We're using https://github.com/jkphl/svg-sprite node package. See https://una.im/svg-icons for more details.
SVG as a background-image value, usually on a pseudo element. The SVG fill colour is added as an attribute in the SVG file. The icons are black by default. If you need another color, it's best to copy the icon and manually adjust the fill/stroke to suit your needs. Rename the copy to include the color in the filename eg. arrow-down--white.svg
.
As defined in the node scripts, all new icons should be placed in the img/icons
directory. Run npm run svg:sprite
to generate a new sprite. This generates the sprite SVG img/icons/cd-icons-sprite.svg
and it creates an html page with all SVGs for reference img/icons/sprite.symbol.html
.
Progressive enhancement approach to layout, using Feature Queries to detect support for flexbox and grid.
OCHA default favicons are provided. Update these with your logo.
http://realfavicongenerator.net/ is a good tool for generating favicons.
See Browsers to test and Draft - Supporting a global audience.
We use browserstack for browser and device testing. We can test using our local development environments, select specific browsers for manual testing, and generate screenshots of many browsers at once. Join the Flowdock Developers channel for access.
There are e2e test using Jest and Puppeteer in the base and sub theme. There is a repo for Visual Regression testing using backstopjs and a Jenkins Job to run VRT on the server. Depending on the json configuration files, we can generate screenshots from lists of URLs (including authenticated user pages), of multiple viewport dimensions, and capture keypress, hover and click actions.
Depending on the project, we run tests via Travis CI. For the common-design-site repo we run PHP lint and Drupal coding standards checks, and compile the theme's sass files. These are common among most projects. Additionally, we install Drupal, import the config, import a database of sample data and run a web server so we can then run the e2e tests.
There is an open issue to integrate Lighthouse performance and accessibility testing OPS-7526
# Install dependencies for your host machine.
npm i
# Run all E2E tests in headless mode. The console will output the results.
npm run e2e
# See the tests run in a visible browser window with --debug
npm run e2e -- --debug
# If you want to run a limited number of tests, specify a string with the -t
# argument. It will parse all of the describe() blocks and only run tests when
# it matches the string you supply.
# All tests that include 'OCHAServicesDropdown'.
npm run e2e -- -t 'OCHAServicesDropdown'
# Only tests in 'Subtheme: OCHAServicesDropdown' block.
npm run e2e -- -t 'Subtheme: OCHAServicesDropdown'
# All 'OCHAServicesDropdown' test except blocks including 'Subtheme'.
npm run e2e -- -t '^(?!.*Subtheme).*$OCHAServicesDropdown'
# All tests except blocks including 'Subtheme'.
npm run e2e -- -t '^(?!.*Subtheme).*$'
web.brand.unocha.org website uses the Drupal PWA module
There is a site.webmanifest
file available in the sub theme as an alternative to the module, if all you want is the Web Manifest, and you don't want offline capability. The manifest file should be adjusted per implementation, and added using a <link>
element in the <head>
, with additional configuration needed. See the Manifest documentation for implementation details.
Arabic, French and Spanish string translation files are available for the Common Design Header and Footer user interface, for example the OCHA Services in the header and the OCHA mandate in the footer. Refer to the .po
files in the translations
directory and the README.