Skip to content

Commit

Permalink
Merge pull request #481 from UN-OCHA/CD-553-dropdown
Browse files Browse the repository at this point in the history
[CD-553] moving docs to this repo
  • Loading branch information
rupl authored May 10, 2024
2 parents 8c7b648 + 1635c1e commit 48a7c95
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 53 deletions.
72 changes: 38 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,40 @@ This theme provides a starting point for OCHA's Drupal websites. By installing t
* **Common Footer:** Navigation, social links, legal info.
* **Common SVG Icons:** a subset of [OCHA Humanitarian Icons][ocha-icons]

It provides the following theming tools that you should leverage in order to maintain the high standards for accessibility that our organization strives to meet:
[ocha-icons]: https://brand.unocha.org/d/xEPytAUjC3sH/icons

* JavaScript dropdowns which do not require jQuery or any framework.
* Common Design frontend components
## Getting started

[ocha-icons]: https://brand.unocha.org/d/xEPytAUjC3sH/icons
1. **Do not modify the base-theme.** Follow the setup guide in the [sub-theme README][subtheme-readme].
2. For Twig debug and local development see [Disable Drupal 8+ caching during development][drupal-caching].

[subtheme-readme]: https://github.com/UN-OCHA/common_design/blob/develop/common_design_subtheme/README.md
[drupal-caching]: https://www.drupal.org/node/2598914

## Drupal utilities

* normalize-css library is included in [Drupal core][normalize] and we depend on it.
* jQuery is [available in Drupal core][core], but the Common Design does not depend on it. It gets loaded only once it is needed.
* [hidden.module.css][hidden] is included in Drupal core to provide utility classes that hide content in an accessible manner.

[normalize]: https://git.drupalcode.org/project/drupal/-/blob/9.5.x/core/assets/vendor/normalize-css/normalize.css
[core]: https://git.drupalcode.org/project/drupal/-/blob/9.5.x/core/core.libraries.yml
[hidden]: https://git.drupalcode.org/project/drupal/-/blob/9.5.x/core/modules/system/css/components/hidden.module.css
[normalize]: https://git.drupalcode.org/project/drupal/-/blob/10.4.x/core/assets/vendor/normalize-css/normalize.css
[core]: https://git.drupalcode.org/project/drupal/-/blob/10.4.x/core/core.libraries.yml
[hidden]: https://git.drupalcode.org/project/drupal/-/blob/10.4.x/core/modules/system/css/components/hidden.module.css

## Additional components
## Additional tools

* Typography defaults
* Component library. See [Common Design demo][cd-demo] for live examples.
* Components that can be attached as Drupal libraries to twig templates.
* Component namespacing by way of [Components module][components-module].
* Docs available in [Components README][components-readme] and [each component][components-used] has some docs in the base theme.
* Components that can be attached as [Drupal Libraries][drupal-libraries] to Twig templates.
* Namespacing by way of [Components module][components-module].
* Docs available in [Libraries README][libraries-readme] and [each Drupal Library][libraries-list] has some docs in the base theme.
* Favicons and OCHA branded assets based on https://brand.unocha.org

[cd-demo]: https://web.brand.unocha.org/demo
[drupal-libraries]: https://www.drupal.org/docs/theming-drupal/adding-assets-css-js-to-a-drupal-theme-via-librariesyml
[components-module]: https://www.drupal.org/project/components
[components-readme]: https://github.com/UN-OCHA/common_design/blob/main/components/README.md
[components-used]: https://github.com/UN-OCHA/common_design/blob/main/components/

## Getting started

1. Follow the setup guide in the [sub-theme README][subtheme-readme].
2. For Twig debug and local development see [Disable Drupal 8+ caching during development][drupal-caching].

[subtheme-readme]: https://github.com/UN-OCHA/common_design/blob/main/common_design_subtheme/README.md
[drupal-caching]: https://www.drupal.org/node/2598914
[libraries-readme]: https://github.com/UN-OCHA/common_design/blob/develop/libraries/README.md
[libraries-list]: https://github.com/UN-OCHA/common_design/blob/develop/libraries/

## Single Directory Components

Expand All @@ -59,7 +55,6 @@ If you can't or don't want to use SDC, read the [CSS](#css) and [JS](#js) sectio

For managing CSS, use [Drupal Libraries][drupal-libraries] to create components made of vanilla CSS/JS files, store them in a component-specific folder inside `libraries`, and attach them to the appropriate Twig template so that they only appear on pages where needed.

[drupal-libraries]: https://www.drupal.org/docs/theming-drupal/adding-assets-css-js-to-a-drupal-theme-via-librariesyml

## JS

Expand All @@ -75,37 +70,41 @@ this.methodName();
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).
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`. In order to easily use other methods defined in your Behavior, you'll need to bind `this` manually. [There are examples of the process in the CD Dropdown][bind-this].

If you don't manually bind `this`, then you have to use the full object as if you were in the global global scope. See code:

[bind-this]: https://github.com/UN-OCHA/common_design/blob/8c7b648a86c2f7293d96f3fefbd9345c83d843aa/libraries/cd-dropdown/cd-dropdown.js#L9-L14

```js
(function (Drupal) {
'use strict';

Drupal.behaviors.exampleBehavior = {
attach: function (context, settings) {
// ✅ Manually bind `this` before it gets used.
this.handleClick = this.handleClick.bind(this);

// 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) {
showAlert: 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:
// ✅ after binding `this`
//
// Uncaught TypeError: this.sendAlert is not a function
this.sendAlert(ev.target);
// Shorthand will work as long as the .bind(this) command was run inside
// the `attach` method.
this.showAlert(ev.target);

// ✅ CORRECT:
// ❌ without binding `this`
//
// Referencing the Behavior as defined in Drupal object will work.
Drupal.behaviors.exampleBehavior.sendAlert(ev.target);
// If we hadn't bound `this` inside `attach` then it would be long-winded:
Drupal.behaviors.exampleBehavior.showAlert(ev.target);
}
};
})(Drupal);
Expand All @@ -126,6 +125,11 @@ If you do create a new template, use one from the base-theme as a guide. They ha

[hide-content]: https://www.drupal.org/docs/accessibility/hide-content-properly

## Print

Using `@media print` should be sufficient in most cases, unless there is a specific reason to have a specific print.css stylesheet (e.g. used by [Snap Service][snap-classes]). Refer to `_print.scss` for basic rules.

[snap-classes]: https://github.com/UN-OCHA/tools-snap-service?tab=readme-ov-file#using-snap-service-on-your-website

## Fonts

Expand Down
11 changes: 5 additions & 6 deletions common_design_subtheme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Refer to [Drupal 9+ Theming documentation][theming-docs] for more information.
3. In the Drupal Admin, go to Appearance, find **OCHA Common Design sub theme** and select **Enable and set default**.
4. Customize the `name`/`description` fields of the sub-theme's info file if you wish.
5. Rebuild the cache.
6. Edit the sub-theme's `css/brand.css` to pick your site's palette. No other modifications are necessary.
6. Edit the sub-theme's `css/brand.css` to pick your site's palette. No other modifications are necessary. The header/footer plus all components will adopt your new colors.


### Customise the logo
Expand Down Expand Up @@ -48,7 +48,7 @@ Replace the favicon in the theme's root, and the homescreen icons in `img/` with

### Customise colours

Change the CSS Vars in `css/brand.css` and save the file. Sass is no longer available in CD v8.
Change the CSS Vars in `css/brand.css` and save the file. Sass is no longer available in CD v8 and newer.


### Customise icons
Expand Down Expand Up @@ -94,8 +94,7 @@ Core and CD base-theme libraries [can be extended with small customizations][lib
Override theme preprocess functions by copying from `common_design.theme` and editing as needed. hen copying, the **function name will always need to be modified** from `common_design_` to `common_design_subtheme_`.
Refer to [common_design README][cd-readme] for
general details about base-theme and instructions for compilation. There should be no need to use Sass in the sub-theme anymore.
Refer to [common_design README][cd-readme] for general details about base-theme and instructions for compilation. There should be no need to use Sass in the sub-theme anymore.
[cd-readme]: https://github.com/UN-OCHA/common_design/blob/main/README.md#ocha-common-design-for-drupal-9
Expand All @@ -119,7 +118,7 @@ npm run e2e -- --debug
# 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'
# All tests that include 'OCHAServices'.
npm run e2e -- -t 'OCHAServices'
```
4 changes: 4 additions & 0 deletions libraries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Eg. Layout markup
```

### CSS

- A component will likely have its own CSS stylesheet. Some components might be CSS only.
- There should be no hexidecimal colour values. We should use CSS custom properties for colour management, defaulting to `--brand-*` whenever possible.
- If variants exist, multiple stylesheets can be used to distinguish and organise.
Expand All @@ -112,18 +113,21 @@ Eg. For cd-hero component
- Adopt a mobile-first approach by starting with generic rules and adding media queries with min-width values down the cascade.

### JS

- Each component should be tested and have applicable cross-browser and device fixes or polyfills where required.
- Adopt a content-first approach by ensuring all content is accessible and the site remains usable when JS is disabled.
*There may be exceptions.
- Add code comments to explain intent where relevant.


### Twig

- Include the markup without the wrapper divs. The main purpose of the twig file is to include the component on the demo page.
- Define and attach the relevant Drupal libraries instead of linking to the CSS files.
As this will display on the demo page (a Drupal site), the cd-base.css is replaced with styles.css (already loaded)

### Add the component to the Demo page

- Include the component in the list of Table of contents.
- Include the twig template on the demo page with a back-to-toc link.

Expand Down
31 changes: 18 additions & 13 deletions libraries/cd-dropdown/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
# CD Dropdown

There are two elements: the button (referred to in code as “toggler”) and the
dropdown (referred to as “element”). The dropdown element needs to be included in the markup and requires the attribute of data-cd-toggable. We use javascript to create and remove the toggle button as needed and the attribute data-cd-hidden to apply the display rules.
There are two elements: the button (referred to in JS code as “toggler”) and the
dropdown (referred to as “element”). The dropdown element needs to be included in the markup and requires the attribute of `data-cd-toggable`. The markup is designed to be declarative: you can specify the data attributes listed below and the JS does the rest.

@TODO refine this based on
https://docs.google.com/document/d/1GpTtCWNQvGiPDfZmhFvaKGvU9hbOG0HedFTYgo3nvd4/edit#heading=h.w6466tbgvgf1
**Progressive enhancement:** This component expects all content to exist in the HTML response which it will convert to a dropdown. There's no mode where data gets fetched from the client-side. We use JavaScript to create and remove the toggle button as needed. We use the attribute `data-cd-hidden` to apply the display rules.

## Purpose and Usage

**Minimum requirements**

The following attributes should be added to the dropdown element’s markup:
- `data-cd-toggable` - the value is used for the Button label
- `id` - this is also used to set the aria-controls attribute on the toggler
- `aria-labelledby` - component-toggle (eg. cd-filters-toggle)
- `data-cd-component` - the component name, for BEM selectors (eg. cd-filters)
The following attributes should be added to the dropdown element’s markup in order to construct a widget that meets our accessibility requirements:

- `id`: used to set the `aria-controls` attribute on the toggler
- `data-cd-toggable`: the value of this attribute is used as the Button label
- `data-cd-component`: the component name, for BEM selectors (eg. cd-filters)
- `aria-labelledby`: component-toggle (eg. cd-filters-toggle)

**Optional**
- `data-cd-logo` and/or `data-cd-icon` if either are required for the button

- `data-cd-logo` and/or `data-cd-icon` if either are desired for the button
- `data-cd-logo-only` adds a class `visually-hidden` to the button label
- `data-cd-label-switch` for different labels depending on open/closed state
- `data-cd-focus-target` for adding focus to a specific element when dropdown is toggled (this works well with the Search component. Add the ID of the search input field and it will have focus when the dropdown is expanded)
- `data-cd-replace=”ID”` will replace the element with the given ID with a toggler. The element (ex: a link) serves as a fallback element for progressive enhancement when the cd-dropdown script cannot run.

## Caveats

Implementation for Drupal required using Drupal behaviours so we use the file
in `common_design/js` for the base theme. The JS in this component folder is for testing outside of Drupal.
- The dropdown element must be wrapped in a container element, so that the button can be generated as a sibling to the content.
- This script works best when JS is detected in the `<head>` of your document and injects a `js` class onto the `<html>` element. In Drupal this happens too late to prevent a Flash of Unstyled Content (FOUC) which manifests in dropdowns quickly appearing then disappearing on page load. [See our theme file][drupal-js-head] for how this works, or to copy code to another platform if implementing outside Drupal.
- If you have multiple dropdowns on a page, they are "aware" of each other in a sense: expanding a dropdown will simultaneously close any others that are open. Additionally, if using keyboard navigation, the dropdown will automatically close once it loses focus (e.g. when you tab away from the final link in the dropdown).
- The layout of a dropdown can be configured to expand automatically at a certain breakpoint. There is a CSS Custom Prop `--dropdown` which can be set to `false` at any media query you wish. [More info on this technique][dropdown-custom-prop].

[drupal-js-head]: https://github.com/UN-OCHA/common_design/blob/1ff0a03bf5df76071ece76e82105b952c4cf32e1/common_design.theme#L487-L496
[dropdown-custom-prop]: https://justmarkup.com/articles/2017-01-24-handling-states-on-resize-using-css-custom-properties/

The dropdown element must be wrapped in a parent element.

### Variants

Expand Down

0 comments on commit 48a7c95

Please sign in to comment.