{"id":18263146,"url":"https://github.com/vanillawc/wc-menu-wrapper","last_synced_at":"2026-05-04T07:39:01.958Z","repository":{"id":57151762,"uuid":"274991826","full_name":"vanillawc/wc-menu-wrapper","owner":"vanillawc","description":"A web component that wraps HTML elements and forms a drop-down menu out of them.","archived":false,"fork":false,"pushed_at":"2021-05-16T17:59:41.000Z","size":29,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-21T12:26:30.605Z","etag":null,"topics":["custom-elements","drop-down","dropdown","dropdown-menus","html","javascript","menu","vanilla-web-component","web-components"],"latest_commit_sha":null,"homepage":"http://135.181.40.67/wcmenuwrapper/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vanillawc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-25T18:50:49.000Z","updated_at":"2025-04-28T04:52:33.000Z","dependencies_parsed_at":"2022-09-03T16:50:42.092Z","dependency_job_id":null,"html_url":"https://github.com/vanillawc/wc-menu-wrapper","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/vanillawc/wc-menu-wrapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanillawc%2Fwc-menu-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanillawc%2Fwc-menu-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanillawc%2Fwc-menu-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanillawc%2Fwc-menu-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vanillawc","download_url":"https://codeload.github.com/vanillawc/wc-menu-wrapper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanillawc%2Fwc-menu-wrapper/sbom","scorecard":{"id":915990,"data":{"date":"2025-08-18","repo":{"name":"github.com/vanillawc/wc-menu-wrapper","commit":"6d2c7ccf0a679b786358f26f4df54698bc34d746"},"scorecard":{"version":"v5.2.1-41-g40576783","commit":"40576783fda6698350fcbbeaea760ff827433034"},"score":3.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/latest.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/latest.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/latest.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/latest.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/latest.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/latest.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/vanillawc/wc-menu-wrapper/release.yml/main?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/latest.yml:25","Warn: npmCommand not pinned by hash: .github/workflows/release.yml:27","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/latest.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T21:00:17.345Z","repository_id":57151762,"created_at":"2025-08-24T21:00:17.345Z","updated_at":"2025-08-24T21:00:17.345Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32599408,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["custom-elements","drop-down","dropdown","dropdown-menus","html","javascript","menu","vanilla-web-component","web-components"],"created_at":"2024-11-05T11:09:58.115Z","updated_at":"2026-05-04T07:39:01.936Z","avatar_url":"https://github.com/vanillawc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/vanillawc/wc-menu-wrapper/releases\"\u003e\u003cimg src=\"https://badgen.net/github/tag/vanillawc/wc-menu-wrapper\" alt=\"GitHub Releases\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@vanillawc/wc-menu-wrapper\"\u003e\u003cimg src=\"https://badgen.net/npm/v/@vanillawc/wc-menu-wrapper\" alt=\"NPM Releases\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=@vanillawc/wc-menu-wrapper\"\u003e\u003cimg src=\"https://badgen.net/bundlephobia/minzip/@vanillawc/wc-menu-wrapper\" alt=\"Bundlephobia\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vanillawc/wc-menu-wrapper/actions\"\u003e\u003cimg src=\"https://github.com/vanillawc/wc-menu-wrapper/workflows/Latest/badge.svg\" alt=\"Latest Status\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vanillawc/wc-menu-wrapper/actions\"\u003e\u003cimg src=\"https://github.com/vanillawc/wc-menu-wrapper/workflows/Release/badge.svg\" alt=\"Release Status\"\u003e\u003c/a\u003e\n\n  \u003ca href=\"https://discord.gg/aSWYgtybzV\"\u003e\u003cimg alt=\"Discord\" src=\"https://img.shields.io/discord/723296249121603604?color=%23738ADB\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n# wc-menu-wrapper\nA web component that wraps HTML elements and forms a drop-down menu out of them.\n\nLive demo available [here.](http://135.181.40.67/wcmenuwrapper/)\n\n## Features\nWc-menu-wrapper is a standalone vanilla JS web component that does not use shadow DOM.\n\nComponent features include:\n- content agnostic: menu items should be able to contain any HTML\n- nestable: allows creating of versatile menu-submenu structures\n- menu \"drop\" directions: down or right\n- initial menu item positions: bottom or right\n- menu toggling methods: click or hover\n\n## Usage\n- create a menu heading container by assigning a heading class to it\n- create menu item containers by assigning item classes to them\n- add style to classes\n- add content inside the containers\n- wrap the containers inside a custom menu component\n- dispatch menuClose events from within the menu items if necessary\n\nHTML example:\n\n ```html\n     \u003cwc-menu-wrapper\u003e\n        \u003cdiv class='heading'\u003e Menu \u003c/div\u003e\n        \u003cdiv class='item'\u003e 1st item \u003c/div\u003e\n        \u003cdiv class='item'\u003e 2nd item \u003c/div\u003e\n        \u003cdiv class='item'\u003e 3rd item \u003c/div\u003e\n     \u003c/wc-menu-wrapper\u003e    \n ```\n\n Style example:\n\n ```css\n   .item, .heading {\n    background-color: lightblue;\n    display: none;\n    width: 150px;\n    height: 60px;\n    align-items: center;\n    justify-content: center;\n  }\n\n  .item:hover {\n    background: white;\n    cursor: default;\n  }\n\n  .heading {\n    background-color: #63b4cf;\n  }\n ```\nValue *none* should be assigned as an initial display style for the containers.\n\nComponent will change the container display style to *flex* during component initialization.\n\nContainer contents should be considered as flex items when styling them.\n\nIn the example above, the content is centered as flex items with *align-items* and *justify-content* directives.\n\n## Including the component to an HTML file\n\n1. Import polyfill, this is not needed for modern browsers:\n\n    ```html\n    \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/custom-elements/1.4.1/custom-elements.min.js\"\u003e\u003c/script\u003e\n    ```\n\n2. Import custom element:\n\n    ```html\n    \u003cscript defer src='wc-menu-wrapper.min.js'\u003e\u003c/script\u003e\n    ```\n\n3. Start using it!\n\n    ```html\n     \u003cwc-menu-wrapper\u003e\n        \u003cdiv class='heading'\u003e Menu \u003c/div\u003e\n        \u003cdiv class='item'\u003e 1st item \u003c/div\u003e\n     \u003c/wc-menu-wrapper\u003e    \n    ```\n## Including the component from NPM\n\n1. Install and import polyfill, this is not needed for modern browsers:\n\n   See https://www.npmjs.com/package/@webcomponents/custom-elements\n\n2. Install wc-menu-wrapper NPM package:\n\n    ```console\n    npm i @vanillawc/wc-menu-wrapper\n    ```\n\n3. Import custom element:\n\n    ```javascript\n    import '@vanillawc/wc-menu-wrapper'\n    ```\n\n4. Start using it:\n\n   ```javascript\n   var menu = document.createElement('wc-menu-wrapper')\n   var heading = document.createElement('div')\n   var item = document.createElement('div')\n   heading.innerHTML = 'Menu'\n   item.innerHTML = 'Item 1'\n   heading.classList.add('heading')\n   item.classList.add('item')\n   menu.appendChild(heading)\n   menu.appendChild(item)   \n   document.body.appendChild(menu)\n   ```\n\n\n## Attributes\n\n### mode\n\nDefines how the menu can be toggled.\n\nMenu can be toggled by clicking or hovering on it.\n\nAttribute value must be either 'click' or 'hover'.\n\nDefault mode is 'click'.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper mode='hover'\u003e\n```\n\n### position\n\nDefines initial menu item position in relation to menu heading.\n\nAttribute value must be either 'bottom' or 'right'.\n\nDefault position is 'bottom'.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper position='right'\u003e\n```\n\n### direction\n\nDefines menu opening direction.\n\nAttribute value must be either 'down' or 'right'.\n\nDefault direction is 'down'.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper direction='right'\u003e\n```\n\n### init-state-open\n\nIf defined, the menu will initially be displayed in open state.\n\nThis attribute is a boolean attribute, also known as a valueless attribute.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper init-state-open\u003e\n```\n\n### closing-delay\n\nDefines how many milliseconds the menu will be open after the pointer is not above the menu anymore.\n\nThis attribute applies only when the menu is in hover mode.\n\nDefault delay is 500 ms.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper mode='hover' closing-delay='1000'\u003e\n```\n\n### close-submenus-on-closing\n\nDefines whether the submenus will be closed when the menu is closed by custom event or by losing focus.\n\nThis attribute is a boolean attribute, also known as a valueless attribute.\n\nThis attribute applies only when the menu is in click mode.\n\nBy default, the component will not close submenus on closing.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper close-submenus-on-closing\u003e\n```\n\n### close-submenus-on-heading-click\n\nDefines whether the submenus will be closed when the menu is closed by heading click.\n\nThis attribute is a boolean attribute, also known as a valueless attribute.\n\nThis attribute applies only when the menu is in click mode.\n\nBy default, the component will not close submenus on heading click.\n\nHTML example:\n\n```html\n\u003cwc-menu-wrapper close-submenus-on-heading-click\u003e\n```\n\n### heading-class\n\nDefines the name of the class that will be assigned to heading when the menu is opened.\n\nThe class will be removed from heading when the menu is closed.\n\nThis attribute can be used to change the heading style when the menu is toggled.\n\nThis attribute does not have a default value.\n\nCSS example:\n\n ```css\n  .menu-open-heading {\n    background-color: #black;\n    color:white;\n  }\n ```\nHTML example:\n\n```html\n\u003cwc-menu-wrapper heading-class='menu-open-heading'\u003e\n```\n\n### item\n\nDefines new item class name, if the default class name 'item' can not be used.\n\n### heading\n\nDefines new heading class name, if the default class name 'heading' can not be used.\n\n## Closing the menu\n\nFollowing events cause menu closing:\n\n * item or its descentant loses focus due to click outside menu area\n * heading loses focus due to click outside menu area (on click mode only)\n * click on the heading (on click mode only)\n * hover outside menu area for longer than closing-delay time (on hover mode only)\n * menuClose or rootMenuClose event is dispatched from menu item or its descentant\n\n#### Dispatching menuClose event\n\n  menuClose event closes the menu that contains the item from within the event originated from.\n\n  Example:\n\n```javascript\n  var element = getElementById(\"elemId\")\n  element.dispatchEvent(new CustomEvent('menuClose', {bubbles: true}))\n```\n\n  In the example above, the element must be a menu item or its descentant.\n  Remember to set the 'bubbles:true' object parameter on CustomEvent.\n\n#### Dispatching rootMenuClose event\n\n  rootMenuClose event closes the root menu that contains the submenu that contains the item from within the event originated from.\n\n  rootMenuClose event closes the menu also if it there are no submenus at all.\n\nExample:\n\n```javascript\n  var element = getElementById(\"elemId\")\n  element.dispatchEvent(new CustomEvent('rootMenuClose'))\n```\n\n  In the example above, the element must be a descendant of menu item element. Unlike in the case of menuClose event, there is no need for second parameter on CustomEvent.\n\n## Adding and removing menu items\n\nIf component has not been added to DOM, new items can be added with HTML DOM appendChild() method.\n\nIf component has been added to DOM, new items must be added with component's addItem() method, see documentation below.\n\nItems can be removed from the component by using HTML DOM ChildNode.remove() method.\n\nYou can use document.getElementById() or document.querySelector() methods to get the item element and then remove it with its own remove() method.\n\nIf component has been added to DOM, items can be removed also with components deleteItem() method, see documentation below.\n\n## Methods\n\n### addItem( element, index )\n\nAdds new menu item container. The element parameter must be a div element that contains the actual item content. The index parameter defines the place of the new item to be added. Index 0 adds item as first. If index parameter is omitted, item is added as last. Index parameter must be integer.\n\nThis method can be used only when the component has been added to DOM.\n\n### deleteItem( param )\n\nRemoves menu item container from menu. If param type is string, param is considered to be the id of the item container to be removed. If param type is number, param is considered to be the ordinal index of the item container to be removed.\n\nIf param is omitted, the last item container shall be removed.\n\nThis method can be used only when the component has been added to DOM.\n\n## Importing menu content as component\n\nMenu content can be imported from a file as a custom element.\n\nExample:\n\n ```html\n     \u003cscript src=\"my-menu-content.js\"\u003e\u003c/script\u003e\n\n     \u003cwc-menu-wrapper\u003e\n        \u003cmy-menu-content /\u003e\n     \u003c/wc-menu-wrapper\u003e    \n ```\n\nElement name can be freely chosen as long as it adheres to custom element naming rules.\n\nThe element must have *menuContent* attribute that shall contain the menu content HTML definition.\n\nSee example file *my-menu-content.js* in *menu-content-component* folder.\n\n## Building\n\nUnminified scripts in the dist folder can be used and modified as such, there are no build scripts available for them.\n\nBuilding is done by executing the minifier script minify.cmd, which is a Linux bash shell script.\n\nMinify.cmd can be found from dist folder.\n\nBuilding (minifying) requires [terser](https://github.com/terser/terser) command line tool to be installed. It can be installed with following command:\n```console\n npm install terser -g\n   ```\n## Contributing\n\nQuestions, suggestions and bug reports are welcome. Safari testing would be nice.\n\n## License\n\nCopyright (c) 2020 Jussi Utunen\n\nLicensed under the MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvanillawc%2Fwc-menu-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvanillawc%2Fwc-menu-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvanillawc%2Fwc-menu-wrapper/lists"}