https://github.com/chrisnajman/meal-item-selector
A checkbox-driven meal item manager that enforces selection limits for precise user input control.
https://github.com/chrisnajman/meal-item-selector
accessibility aria-attributes css-flexbox css-grid css-nesting cssnano es6-modules esbuild html-css-javascript html-minifier-terser loading-spinner postcss theme-switcher
Last synced: 11 months ago
JSON representation
A checkbox-driven meal item manager that enforces selection limits for precise user input control.
- Host: GitHub
- URL: https://github.com/chrisnajman/meal-item-selector
- Owner: chrisnajman
- License: mit
- Created: 2025-07-18T06:09:06.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-07-18T09:32:58.000Z (11 months ago)
- Last Synced: 2025-07-18T10:29:04.605Z (11 months ago)
- Topics: accessibility, aria-attributes, css-flexbox, css-grid, css-nesting, cssnano, es6-modules, esbuild, html-css-javascript, html-minifier-terser, loading-spinner, postcss, theme-switcher
- Language: HTML
- Homepage: https://chrisnajman.github.io/meal-item-selector/
- Size: 359 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Meal Item Selector
A checkbox-driven meal item manager that enforces selection limits for precise user input control.
[View on GitPage](https://chrisnajman.github.io/meal-item-selector)
---
## How it works
Users select items from five food categories — Starters, Mains, Vegetables, Desserts, and Drinks — with selection limits enforced per category. Selections are visually displayed with corresponding icons and prices, and a running total is calculated. The interface is fully keyboard-accessible and includes accessibility features such as live region announcements and focus management.
---
## Features
- Checkbox-based selection grouped by food categories
- Custom limits per group (e.g., max 2 starters, 1 main)
- Dynamic feedback when limits are exceeded
- Lazy-loaded images for performance (after first image)
- Total price calculation on form submission
- ARIA live region support for screen reader announcements
- "Skip to submit" keyboard links per group
- Responsive and accessible interface
- Modular JavaScript and CSS structure
- Light/dark theme toggle with local storage support
---
## JavaScript
Built with **vanilla ES6 JavaScript**, focusing on modern syntax and browser APIs, then bundled, transpiled to ES2015, and minified for broad browser compatibility.
The JavaScript has been split into separate modules, improving code modularity:
### Main
- `meal-item-selector/`
- `meal-item-selector.js`: Initializes the form logic, binds event handlers, and controls flow from input to output on submission.
- `components/`
- `checkbox-groups.js`: Defines the five checkbox groups and their individual limits using data attributes.
- `enforce-checkbox-limits.js`: Dynamically prevents users from exceeding the selection limits for each group, providing inline warnings.
- `output-checkbox-values.js`: Builds and appends a DOM structure showing the selected items, their icons, and prices.
- `output-prices.js`: Totals all selected checkbox prices and displays the result in the output container.
- `remove-no-checkbox-selected-warning.js`: Removes the "no selection" warning once a checkbox is selected after an empty submission.
- `image-credits.js`: Applies lazy-loading to icons used on the image credits page, skipping the first image for eager loading.
- `helpers/`
- `lazy-load-images.js`: Tracks image count to apply `loading="lazy"` to all but the first image.
- `set-multiple-attributes.js`: Utility function to assign multiple attributes to a single DOM element efficiently.
### Other
- `loader.js`: Displays a loader animation until the page is fully rendered, then removes the loader and announces readiness for screen readers.
- `theme.js`: Handles theme toggling (light/dark mode) and local storage management.
---
## CSS
Built with modern CSS features such as nesting, custom properties, and the `:has()` pseudo-class, this project emphasizes modular, accessible, and maintainable styling.
The main `style.css` file serves as an entry point and imports individual CSS modules using `@import`. These are then processed by PostCSS (with `postcss-import`, `postcss-nesting`, and `cssnano`) during the build.
---
## Theme Toggling
The application includes a dark mode and light mode toggle:
- The current theme state is stored in **local storage** and applied automatically on page reload.
- Accessible buttons with appropriate ARIA attributes are used to improve usability.
> [!IMPORTANT]
> Remember to change `const LOCAL_STORAGE_PREFIX` in `js-modules/theme.js` to a unique identifier.
---
## Accessibility
The site is fully navigable using tab keys and arrow keys. Key accessibility features include:
- ARIA `role="alert"` used to announce output content changes to screen readers.
- `tabindex="-1"` and `.focus()` used to direct keyboard focus after form submission.
- Skip links (`a.skip-link`) placed after each food group to quickly jump to the submit button.
- Warnings (e.g., for over-selection or missing selections) are announced and clearly styled.
- Lazy-loading excludes the first image to ensure immediate content visibility for screen reader users on slower connections.
---
## Testing and Compatibility
The application has been tested on the following platforms and browsers:
- **Operating System**: Windows 10
- **Browsers**:
- Google Chrome
- Mozilla Firefox
- Microsoft Edge
### Device View Testing
The layout and functionality have been verified in both browser and device simulation views to ensure responsiveness and usability.
---
## How to Run
1. Clone or download the repository to your local machine.
2. Open the project folder and start a simple HTTP server (e.g., using `Live Server` in VS Code or Python's `http.server` module).
3. Open the project in a modern browser (e.g., Chrome, Firefox, or Edge).
---
## Build & Deployment Setup for `/docs` Folder
If you want to deploy a minified version of this project to **GitHub Pages**, read on.
### 1. Install Required Packages
Run this once in your project root to install dev dependencies:
```bash
npm install
```
### 2. Run the full build process
In the terminal, run:
```bash
npm run build
```
### 3. Deploy to GitHub Pages
Once you've created a repository and pushed the files,
- go to `https://github.com/[your-name]/[your-project-name]/settings/pages`.
- Under "Build and deployment > Branch" make sure you set the branch to `main` and folder to `/docs`.
- Click "Save".
> [!NOTE]
> For a detailed description of the build process, configuration files and npm packages see my [GitHub Pages Optimised Build](https://github.com/chrisnajman/github-pages-optimised-build).