├── .gitignore ├── .npmignore ├── tsconfig.json ├── index.d.ts ├── .github ├── workflows │ ├── npm-schedule.yml │ ├── init-lint-test.yml │ ├── npm-publish.yml │ └── codeql-analysis.yml ├── dependabot.yml └── FUNDING.yml ├── webpack.config.js ├── index.test.js ├── src ├── index.js └── index.css ├── README.md ├── package.json └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | coverage 4 | dist -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | coverage 4 | 5 | .github 6 | src 7 | index.test.js 8 | tsconfig.json 9 | webpack.config.js -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "esModuleInterop": true, 5 | "allowJs": true 6 | }, 7 | "include": ["src/**/*", "index.d.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | declare module "react-hamburger-drawer" { 4 | export interface HamburgerDrawerProps { 5 | children: React.ReactNode; 6 | useFocusBounder: boolean; 7 | } 8 | 9 | const HamburgerDrawer: React.FunctionComponent; 10 | export default HamburgerDrawer; 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/npm-schedule.yml: -------------------------------------------------------------------------------- 1 | name: schedule 2 | 3 | on: 4 | schedule: 5 | - cron: '*/15 * * * *' 6 | 7 | jobs: 8 | init: 9 | runs-on: ubuntu-latest 10 | timeout-minutes: 2 11 | steps: 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: 16 15 | - run: npm init --force 16 | - run: npm install react-glize 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/init-lint-test.yml: -------------------------------------------------------------------------------- 1 | name: init-lint-test 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | if: github.repository == 'vpodk/react-hamburger-drawer' 9 | runs-on: ubuntu-latest 10 | timeout-minutes: 2 11 | 12 | strategy: 13 | matrix: 14 | node-version: [16, 17, 18, 19, 20] 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Use Node ${{ matrix.node-version }} 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm install 23 | - run: npm run lint 24 | - run: npm run test 25 | - run: npm run build 26 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [vpodk] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | buy_me_a_coffee: vpodk 5 | #patreon: # Replace with a single Patreon username 6 | #open_collective: # Replace with a single Open Collective username 7 | #ko_fi: # Replace with a single Ko-fi username 8 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 9 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 10 | #liberapay: # Replace with a single Liberapay username 11 | #issuehunt: # Replace with a single IssueHunt username 12 | #otechie: # Replace with a single Otechie username 13 | # custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | custom: www.paypal.me/vpodk 15 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const ESLintPlugin = require("eslint-webpack-plugin"); 3 | 4 | module.exports = { 5 | mode: "production", 6 | entry: "./src/index.js", 7 | output: { 8 | path: path.resolve(__dirname, "dist"), 9 | filename: "index.js", 10 | libraryTarget: "commonjs2", 11 | }, 12 | plugins: [ 13 | new ESLintPlugin({ 14 | extensions: ["js", "jsx"], 15 | exclude: ["/node_modules/", "/dist/"], 16 | }), 17 | ], 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.jsx?$/, 22 | include: path.resolve(__dirname, "src"), 23 | exclude: /(node_modules|dist)/, 24 | use: { 25 | loader: "babel-loader", 26 | options: { 27 | presets: ["@babel/preset-env", "@babel/preset-react"], 28 | }, 29 | }, 30 | }, 31 | { 32 | test: /\.css$/, 33 | include: path.resolve(__dirname, "src"), 34 | exclude: /(node_modules|dist)/, 35 | use: ["style-loader", "css-loader"], 36 | }, 37 | ], 38 | }, 39 | externals: { 40 | react: "commonjs react", 41 | "react-dom": "commonjs react-dom", 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /index.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {fireEvent, render, screen} from '@testing-library/react'; 3 | import HamburgerDrawer from './src/index'; 4 | 5 | describe('HamburgerDrawer Test Suite', () => { 6 | it('HamburgerDrawer Test Case', () => { 7 | render( 8 | 9 | 15 | , 16 | ); 17 | 18 | const checkbox = screen.getByRole('checkbox'); 19 | const classList = document.documentElement.classList; 20 | expect(classList.contains('HamburgerDrawer-open')).toBe(false); 21 | fireEvent.click(checkbox); 22 | expect(classList.contains('HamburgerDrawer-open')).toBe(true); 23 | 24 | expect(checkbox.checked).toBe(true); 25 | fireEvent.keyUp(document, {key: 'Escape', code: 27}); 26 | expect(checkbox.checked).toBe(false); 27 | 28 | fireEvent.keyUp(checkbox, {key: 'Enter', code: 13}); 29 | expect(checkbox.checked).toBe(true); 30 | fireEvent.keyUp(checkbox, {key: 'Enter', code: 13}); 31 | expect(checkbox.checked).toBe(false); 32 | }); 33 | }); -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: publish 5 | 6 | on: 7 | push: 8 | branches: [main] 9 | 10 | jobs: 11 | build: 12 | if: github.repository == 'vpodk/react-hamburger-drawer' 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 2 15 | 16 | strategy: 17 | matrix: 18 | node-version: [16, 17, 18] 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Use Node ${{ matrix.node-version }} 23 | uses: actions/setup-node@v3 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - run: npm install 27 | - run: npm run lint 28 | - run: npm run test 29 | 30 | publish-npm: 31 | needs: build 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/checkout@v3 35 | - uses: actions/setup-node@v3 36 | with: 37 | node-version: 16 38 | registry-url: https://registry.npmjs.org/ 39 | - run: npm install 40 | - run: npm run build 41 | - run: npm publish 42 | env: 43 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 44 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import FocusBounder from "react-focus-bounder"; 4 | import "./index.css"; 5 | 6 | export const HamburgerDrawer = ({ children, useFocusBounder = false }) => { 7 | const checkbox = React.useRef(null); 8 | const Wrapper = useFocusBounder ? FocusBounder : React.Fragment; 9 | 10 | const handleEscKey = (event) => { 11 | // Closes the navigation drawer by pressing Esc key. 12 | if ("Escape" === event.key) { 13 | checkbox.current.checked = false; 14 | } 15 | }; 16 | 17 | const handleKeyup = (event) => { 18 | if ("Enter" === event.key) { 19 | checkbox.current.checked = !checkbox.current.checked; 20 | } 21 | }; 22 | 23 | const handleClick = () => { 24 | document.documentElement.classList.toggle("HamburgerDrawer-open"); 25 | }; 26 | 27 | React.useEffect(() => { 28 | document.addEventListener("keyup", handleEscKey); 29 | return () => document.removeEventListener("keyup", handleEscKey); 30 | }, []); 31 | 32 | return ( 33 | 34 | 60 | 61 | ); 62 | }; 63 | 64 | HamburgerDrawer.propTypes = { 65 | children: PropTypes.node.isRequired, 66 | useFocusBounder: PropTypes.bool, 67 | }; 68 | 69 | export default HamburgerDrawer; 70 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '23 18 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript', 'typescript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v3 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v2 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v2 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v2 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Navigation drawer 2 | 3 | [![Build Status](https://github.com/vpodk/react-hamburger-drawer/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/vpodk/react-hamburger-drawer/actions/workflows/npm-publish.yml) [![License](https://img.shields.io/:license-apache-blue.svg?logo=apache)](https://www.apache.org/licenses/LICENSE-2.0.html) [![NPM version](https://img.shields.io/npm/v/react-hamburger-drawer.svg?logo=npm)](https://npmjs.org/package/react-hamburger-drawer) [![NPM downloads](https://img.shields.io/npm/dm/react-hamburger-drawer.svg?style=flat)](https://npmjs.org/package/react-hamburger-drawer) 4 | 5 | Simple lightweight react hamburger navigation drawer (based on [navigation-drawer](https://github.com/vpodk/navigation-drawer)). 6 | 7 | ### Key points 8 | 9 | - Hidden `` as a toggle; 10 | - Fullscreen `