@ewc-lib/ewc-menu
v1.2.2-alpha
Published
## TOC
Keywords
Readme
EWC Menu Component
TOC
Overview
The EWC Menu component provides a standardized dropdown menu for Eurostat web applications. It offers a consistent visual identity across Eurostat digital products while allowing for customization to meet specific application needs.
Features
- Supports usage in single page applications
- Highlighting of the currently selected item
- Responsive design that adapts to different screen sizes
- On wide screens, the menu is oriented horizontally, taking up all available space
- On narrow screens, the menu becomes a hamburger icon and opens up vertically along the right border of the viewport
- Automatic display of left/right scroll buttons
- Accessibility compliant
Screenshots
On wide enough screens, menu is displayed horizontally.

Given a narrow viewport, the menu is collapsed/hidden and a hamburger icon is displayed

Given a narrow viewport, the menu is displayed vertically when opened/expanded

Directory structure
ewc-menu
├── package.json the component's project
├── src/ plain JS files. Can be used as VanillaJS.
├── usage-example/ examples for usage in a project
│ ├── vanilla/
│ │ ├── index.html
│ │ └── ewc-menu/ a symlink to component root dir
│ └── webpack/
│ ├── package.json has dependency "@ewc-lib/ewc-menu": "latest"
│ └── webpack.config.js
└── tests/ for usage during development
├── package.json has dependency "@ewc-lib/ewc-menu": "file:../"
├── webpack.config.js similar to usage-exampe/webpack/
└── playwright.config.tsNote that this component contains 3 distinct NPM projects:
- The main package.json (the root of the containing project)
- including sources, usage-examples and tests.
- The examples in usage-example/
- They can be copy&pasted to start a project which uses this component.
- Note that usage-example/webpack is a project in it's own rights. It depends on the "latest" version in NPM.
- tests/
- depends on the local component (via "file:")
- is used during development
This component can also be used as VanillaJS. Note that this works without a bundler, yet the sources are made available through NPM.
API
Properties and Attributes
| Property | Attribute | Type | Default | Description |-----------------------|---------------|---------------------|---------|------------ | data | | MenuItem | | set contents of the menu. expects array of objects of type MainMenuItem. Please see "types" and "example of data" below. | select | | String | | sets currently selected item. expects an id. | onSelect | | Function | | a callback which is called when a menu/submenu item was selected. | | | | | callback signature: myCallback(subMenuId, menuId, isMainMenuItem) | | | | | isMainMenuItem === true means, a main-menu item was selected. Note: subMenuId === menuId in that case | | transparentBackground | Bool | | if set to "true", the background gradient is not drawn and the background is left transparent. default is false. | | data-ewc-menu-max-lines | Number | | labels of menu items don't take up more lines than specified. This implies a minimal width for all or some menu items. default=2.
Methods
| Method | Description |---------------------|------------ | close() | close the menu | setLocked(isLocked) | isLocked (boolean) true prohibits selecting elements
types
type MenuItem = {
id: string
label: string
}
type MainMenuItem = {
item: MenuItem
numberOfCols: number
subMenuItems: MenuItem[]
}example of data
const mainMenuItems =
[
{
item: {
id: 'MyMainMenuItemId',
label: 'Displayed Label',
},
numberOfCols: 2, // optional, default = 1
subMenuItems: [ // can be omitted or empty array
{
id: 'MySubMenuItemId'
label: 'Label for a submenu item'
}
]
}
]- numberOfCols - In the top-menu only (not when in side menu on narrow widths), up to 4 columns are supported.
Usage
Installation
npm install @ewc-lib/ewc-dialogImport the component in your application:
// Using ES modules
import "@ewc-lib/ewc-css-common/custom-props.css"
import "@ewc-lib/ewc-dialog"Note about ewc-css-common
- "ewc-css-common/custom-props.css" is necessary and downloaded along with ewc-dialog.
- It needs to be imported by the host project because it's not imported by ewc-dialog itself.
Usage examples
There are two examples (actually working sourcecode) on how to use the component.
One is pure vanillaJS, the other using WebPack.
Please see directory usage-example/
Usage scenarios
Embedded menu
By default - out of the box - the menu assumes to have the entire given width available.
Content on the right side of the menu
In order to allow for content on the right side of the menu, CSS similar to this has to be used:
ewc-menu {
width: calc(100% - 200px);
}The above code assumes that the lateral content has a width of 200px.
This assures, that the menu displays correctly and behaves as expected. See also detailed explanation below.
Note: A good a11y practice is to put the buttons into an ul which itself is put into a nav which has an aria-label. See usage examples.
Example Screenshots
This is what it looks like on wide screens to display 3 buttons on the right side of the menu.

Note that in the depicted situation, not all menu items fit the given width, thus automatically displaying an additional button to scroll the menu items.
On narrow screens, by default, the hamburger icon is displayed to the left side of the additional content:
![]()
Hamburger icon right side of additional content
![]()
To achieve this, additionally to what's described above (content on the right side of menu), the following CSS is necessary:
@media (max-width:996px) {
#menu-container-row {
flex-direction: row-reverse;
reading-flow: flex-visual;
}
ewc-menu {
width:auto;
}
}Note:
- the above sourcecode is demonstrated with working node-project in the directory "usage-example/".
- "flex-direction" does not account for a correct tab order.
- This is a recognised issue. Quote: "the tabbing order... can be cognitively confusing"
- This quoted source puts the burdon on the developer (basically by stating, they should keep their DOM nodes in order and not use flex-direction).
- Whereas reading-flow is a solution in CSS - see here.
- However that's available in chrome based browsers only atm.
Detailed explanation
Here is a visual example of the HTML elements involved to achieve this.
┌── menu-container-row ────────────────────────────────────────────────────────────────────┐
│ ┌── ewc-menu ────────────────────────────────────────────────┐┌─── btn-container ──────┐ │
│ │ ┌─────────────────┐ ┌────────────┐ ┌────────────────────┐ ││┌──────┐┌──────┐┌──────┐│ │
│ │ │ │ │ │ │ │ │││ ││ ││ ││ │
│ │ │ menu item │ │ menu item │ │ menu item │ │││ Btn ││ Btn ││ Btn ││ │
│ │ │ │ │ │ │ │ │││ ││ ││ ││ │
│ │ └─────────────────┘ └────────────┘ └────────────────────┘ ││└──────┘└──────┘└──────┘│ │
│ └────────────────────────────────────────────────────────────┘└────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────────────┘ Assumptions:
- buttons are set to an explicit width by the developer (let's say 56px)
- menu-container-row and btn-container are calculated by the browser
- ewc-menu does not have a width set by the developer
Below a certain width, some or all menu items are set to an explicit width, calculated by some dedicated JS. This is done in order to mainain a certain maximal number of rows for menu items and/or to display the buttons for scrolling the menu left/right.
So, ewc-menu grows as wide as it needs to, pushing the btn-container out of the right side of the screen.
To avoid that, the ewc-menu has to be assigned a width by the devloper, similar to this example:
width: calc(100% - calc(3 * 56px));Note that the above is demonstrated with working sourcecode in the directory "usage-example/".
Notes
Accessibility
The component is designed with accessibility in mind:
- Keyboard navigable elements
- Sufficient color contrast
- Screen reader friendly with appropriate ARIA attributes
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
License
European Union Public License (EUPL)
Changelog
1.2.2-alpha
- fix: submenu taking full width when more than 12 submenu items
1.2.1-alpha
- avoid aria-expanded on main menupoints without submenu
- add test for this
1.2.0-alpha
- indent submenu items of narrow-screen menu
1.1.4-alpha
- a11y (arrow key nav)
- hamburger button accessible name
- menu line buttons
1.1.3-alpha
- a11y (role, arias) WIP
- adapting testcases and specific screenshots
1.1.2-alpha
- bugfix: wrong selection in narrow view
- introduce playwright test cases
1.1.1-alpha
- improve docu
1.1.0-alpha
- respect given total width when calculating menu item width to support content on the side of the menu
- update docu
1.0.9-alpha
- option for transparent background
1.0.8-alpha
- fix for: Menu labels don't use available width after narrowing the window and then widening it again. The labels stay in 2 lines even though there is enough width available for them to be in just 1 line.
1.0.7-alpha
- allow for main menu items without a submenu
