Add example solution for Tip Calculator App (#325)#347
Add example solution for Tip Calculator App (#325)#347suryaprakash0010 wants to merge 1 commit intosumn2u:mainfrom
Conversation
|
@suryaprakash0010 is attempting to deploy a commit to the Suman Kunwar's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull Request Overview
Adds a complete Tip Calculator example app demonstrating DOM manipulation, event handling, validation, and styling. Key changes:
- Introduces HTML structure for inputs, tip selection, results, and a calculate button.
- Adds CSS for responsive layout, animations, and visual states.
- Implements JavaScript for validation, tip/total calculations, split-bill logic, and UI interactions.
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 11 comments.
| File | Description |
|---|---|
| examples/tip-calculator/index.html | Adds semantic markup for the calculator UI and results display. |
| examples/tip-calculator/style.css | Provides styling, transitions, and layout for the calculator. |
| examples/tip-calculator/script.js | Implements input validation, tip calculations, and UI updates. |
| examples/tip-calculator/README.md | Documents features, usage, and implementation details of the example. |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| - **Bill Amount Input**: Enter the total bill amount | ||
| - **Tip Percentage Selection**: Choose from preset percentages (10%, 15%, 20%, 25%) or enter a custom percentage | ||
| - **Split Bill**: Divide the total among multiple people | ||
| - **Real-time Calculations**: Automatically calculates tip amount and total |
There was a problem hiding this comment.
README claims real-time calculations, but the app only updates results on 'Calculate' click; either update the doc to reflect click-to-calculate or call calculateTip() on input changes and tip button clicks to truly make it real-time.
| - **Real-time Calculations**: Automatically calculates tip amount and total | |
| - **Click-to-Calculate**: Calculates tip amount and total when you click "Calculate" |
| <div class="tip-selection"> | ||
| <label>Tip Percentage:</label> | ||
| <div class="tip-buttons"> | ||
| <button class="tip-btn" data-tip="10">10%</button> | ||
| <button class="tip-btn" data-tip="15">15%</button> | ||
| <button class="tip-btn" data-tip="20">20%</button> | ||
| <button class="tip-btn" data-tip="25">25%</button> | ||
| </div> | ||
| <div class="custom-tip"> | ||
| <input type="number" id="custom-tip" placeholder="Custom %" min="0" max="100"> | ||
| </div> |
There was a problem hiding this comment.
The custom tip input lacks an associated label and the tip controls aren’t grouped; wrap the percentage controls in a fieldset/legend and add a label or aria-label for the custom tip input to improve screen-reader accessibility.
|
|
||
| <button id="calculate-btn">Calculate</button> | ||
|
|
||
| <div class="results" id="results"> |
There was a problem hiding this comment.
Dynamic result updates aren’t announced to assistive technologies; add aria-live="polite" (and optionally role="status") to the results container so changes to amounts are announced.
| <div class="results" id="results"> | |
| <div class="results" id="results" aria-live="polite" role="status"> |
| // Update active button | ||
| tipButtons.forEach(btn => { | ||
| btn.classList.remove('active'); | ||
| if (parseInt(btn.dataset.tip) === percentage) { |
There was a problem hiding this comment.
Use a radix with parseInt or use Number() for clarity: parseInt(btn.dataset.tip, 10) or Number(btn.dataset.tip).
| if (parseInt(btn.dataset.tip) === percentage) { | |
| if (parseInt(btn.dataset.tip, 10) === percentage) { |
| // Event listeners for tip buttons | ||
| tipButtons.forEach(button => { | ||
| button.addEventListener('click', () => { | ||
| updateTipPercentage(parseInt(button.dataset.tip)); |
There was a problem hiding this comment.
Specify a radix with parseInt or use Number(): updateTipPercentage(parseInt(button.dataset.tip, 10)) or updateTipPercentage(Number(button.dataset.tip)).
| updateTipPercentage(parseInt(button.dataset.tip)); | |
| updateTipPercentage(parseInt(button.dataset.tip, 10)); |
| tipButtons.forEach(btn => btn.classList.remove('active')); | ||
| } | ||
|
|
||
| numPeople = parseInt(numPeopleInput.value) || 1; |
There was a problem hiding this comment.
This allows 0 or negative values (they’re truthy/falsey but not clamped); enforce the min by clamping: numPeople = Math.max(1, parseInt(numPeopleInput.value, 10) || 1).
| numPeople = parseInt(numPeopleInput.value) || 1; | |
| numPeople = Math.max(1, parseInt(numPeopleInput.value, 10) || 1); |
| color: white; | ||
| transform: translateY(-2px); | ||
| } | ||
|
|
There was a problem hiding this comment.
Buttons have hover styles but no visible focus style for keyboard users; add a :focus-visible style (e.g., outline or box-shadow) to ensure clear focus indication.
| .tip-btn:focus-visible { | |
| outline: 3px solid #764ba2; | |
| outline-offset: 2px; | |
| box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.2); | |
| } |
| } | ||
|
|
||
| .custom-tip input { | ||
| width: calc(100% - 24px); |
There was a problem hiding this comment.
With box-sizing: border-box set on number inputs, subtracting 24px is unnecessary and makes the input narrower than its container; prefer width: 100% here.
| width: calc(100% - 24px); | |
| width: 100%; |
|
|
||
| // Function to animate result updates | ||
| function animateResult(element, newValue) { | ||
| element.textContent = '$' + newValue; |
There was a problem hiding this comment.
[nitpick] String-concatenating '$' assumes USD and locale; consider Intl.NumberFormat for currency formatting (e.g., new Intl.NumberFormat(navigator.language, { style: 'currency', currency: 'USD' }).format(value)).
| element.textContent = '$' + newValue; | |
| element.textContent = new Intl.NumberFormat(navigator.language, { style: 'currency', currency: 'USD' }).format(Number(newValue)); |
| tipButtons.forEach(btn => { | ||
| btn.classList.remove('active'); | ||
| if (parseInt(btn.dataset.tip) === percentage) { | ||
| btn.classList.add('active'); | ||
| } | ||
| }); |
There was a problem hiding this comment.
In addition to the visual .active class, set aria-pressed to reflect selection state for assistive technologies (e.g., btn.setAttribute('aria-pressed', String(parseInt(btn.dataset.tip, 10) === percentage))); also set aria-pressed="false" when clearing active states in the custom tip handler.
|
Closing this since there hasn’t been any activity for over a month. You’re welcome to reopen the PR anytime. |
Description #325
This PR adds a complete Tip Calculator example solution for issue #325. The application demonstrates fundamental JavaScript concepts including DOM manipulation, event handling, and input validation.
Features Implemented
Technical Implementation