@magic-spells/cart-progress-bar
v2.0.0
Published
Cart progress bar web component for free shipping thresholds.
Maintainers
Readme
Cart Progress Bar
A beautiful, accessible cart progress bar web component for free shipping thresholds and e-commerce sites.
Features
- 🎯 Smart Messaging - Template-based messages with an
[amount]placeholder - 🎨 Simplified Theming - Just 6 CSS variables to control all colors and appearance
- 📱 Responsive - Mobile-optimized with responsive breakpoints
- ⚡ Smooth Animations - Buttery smooth transitions and completion effects
- 🔧 Easy Integration - Drop-in web component that works with any framework
Installation
npm install @magic-spells/cart-progress-barThe package is ESM only — there is no CommonJS build and exports declares no
require condition. Import it once, anywhere in your module graph; it registers
<cart-progress-bar> and <progress-bar> as a side effect.
import '@magic-spells/cart-progress-bar';
// or, if you need the classes:
import { CartProgressBar, ProgressBar } from '@magic-spells/cart-progress-bar';The stylesheet is extracted into its own file rather than injected by the JS, so load it yourself:
@import '@magic-spells/cart-progress-bar/css'; /* unminified */
@import '@magic-spells/cart-progress-bar/css/min'; /* minified */For a plain <script> tag with no build step, use the minified UMD bundle, which
exposes the global CartProgressBar:
<link rel="stylesheet" href="node_modules/@magic-spells/cart-progress-bar/dist/cart-progress-bar.min.css" />
<script src="node_modules/@magic-spells/cart-progress-bar/dist/cart-progress-bar.min.js"></script>Basic Usage
<cart-progress-bar
threshold="75.00"
current="25.50"
message-above="🎉 Congratulations! You've qualified for FREE shipping!"
message-below="Add $[amount] more for FREE shipping!">
<p data-content-cart-progress-message>Add $[amount] more for FREE shipping!</p>
<progress-bar></progress-bar>
</cart-progress-bar>JavaScript API
const progressBar = document.querySelector('cart-progress-bar');
// Set progress percentage directly
progressBar.setPercent(67);
// Update cart amount
progressBar.setCurrentAmount(45.5);
// Change threshold
progressBar.setThresholdAmount(100.0);
// Get current progress info
const info = progressBar.getProgress();
console.log(info.percent, info.isComplete, info.thresholdAmount);
// Update message templates
progressBar.setMessages('Almost there!', 'Only $[amount] more to go!');Cart Integration
The component automatically listens for cart data changes when placed inside a <cart-panel> component from the @magic-spells/cart-panel package:
<cart-panel>
<cart-progress-bar threshold="75.00" message-below="Add $[amount] more for FREE shipping!">
</cart-progress-bar>
</cart-panel>When the cart-panel emits a cart-panel:data-changed event (typically from Shopify cart API updates), the progress bar will automatically update with the calculated cart subtotal. Point it at a different ancestor with listen-selector and listen-event.
Smart Pricing Logic
The progress bar uses intelligent pricing calculation:
- Preferred: Uses
calculated_subtotalfrom cart-panel (respects_ignore_price_in_subtotalproperty) - Fallback: Uses
total_pricefor backwards compatibility - Includes: Bundle items that are hidden in cart but should count toward shipping threshold
- Excludes: Gift items or promotions marked with
_ignore_price_in_subtotalproperty
Attributes
| Attribute | Description | Example |
| --------------- | ----------------------------------------- | ------------------------------ |
| threshold | Threshold amount for free shipping | "75.00" |
| current | Current cart amount | "25.50" |
| message-above | Success message when threshold is reached | "🎉 FREE shipping unlocked!" |
| message-below | Message template shown below the bar | "Add $[amount] more!" |
| money-format | Shopify money format string; uses {{amount}} placeholders and formats the amount that fills [amount] in the messages | "${{amount}}" |
| listen-selector | closest() selector for the element to listen on | "cart-panel" (default) |
| listen-event | Event name to listen for on that element | "cart-panel:data-changed" (default) |
Customization
Use CSS custom properties to customize the appearance:
cart-progress-bar {
/* Core color customization */
--cart-progress-bar-bg: #e9ecef;
--cart-progress-bar-fill-before: #ff6b6b;
--cart-progress-bar-fill-after: #28a745;
/* Structure (optional) */
--cart-progress-bar-height: 16px;
--cart-progress-bar-border-radius: 8px;
--cart-progress-bar-transition-duration: 0.3s;
}Available CSS Custom Properties
Core Color Variables
| Property | Description | Default |
| --------------------------------- | ------------------------------------ | ------------- |
| --cart-progress-bar-bg | Background of progress bar track | #e9ecef |
| --cart-progress-bar-fill-before | Fill color before reaching threshold | #28a745 |
| --cart-progress-bar-fill-after | Fill color after reaching threshold | #007bff |
Structure Variables (Optional)
| Property | Description | Default |
| --------------------------------------- | --------------------------------- | ------- |
| --cart-progress-bar-height | Height of the progress bar | 12px |
| --cart-progress-bar-border-radius | Border radius | 6px |
| --cart-progress-bar-transition-duration | Animation transition duration | 0.3s |
Two more are set for you and are not meant to be overridden:
--cart-progress-percent (the fill width, written by JavaScript) and
--cart-progress-bar-fill-current (switched between the before/after colors by the
complete attribute).
Message Templates
Use the [amount] placeholder in your message templates and include the currency symbol:
<cart-progress-bar
message-above="🎉 FREE shipping unlocked!"
message-below="You need $[amount] more for free shipping!">
<p data-content-cart-progress-message>You need $[amount] more for free shipping!</p>
</cart-progress-bar>Supported Placeholder Format
[amount] — square brackets, with or without spaces inside ([amount], [ amount ]). Square
brackets avoid clashing with Liquid's {{ }} and JavaScript template literals, so curly-brace
forms are not substituted in messages. (money-format is the one place {{amount}} is used,
and it formats the number that fills [amount].)
Examples
<!-- Dollar amounts -->
<cart-progress-bar message-below="Add $[amount] more for free shipping!">
<!-- Euro amounts -->
<cart-progress-bar message-below="Only €[amount] left to unlock free delivery!">
<!-- Spaces inside the brackets work too -->
<cart-progress-bar message-below="Just £[ amount ] more to go!">The component automatically:
- Shows
message-belowwhen incomplete (with placeholder replaced with remaining amount) - Shows
message-abovewhen threshold is reached (success message) - Formats amounts as minimal decimal numbers (removes .00 for whole amounts)
- Updates messages when amounts change
- Switches between before/after progress bar colors based on completion status
States and Attributes
The component automatically sets attributes based on completion status:
complete="true"- When threshold is reachedcomplete="false"- When threshold is not reached
These attributes are used internally to switch between the "before" and "after" progress bar colors.
Browser Support
- Chrome/Edge 88+
- Firefox 85+
- Safari 14+
- All modern browsers with Custom Elements support
Development
npm run build— production build todist/viascripts/build.mjs(Vite + Rolldown, Lightning CSS, Terser). Emits exactly four files: the unminified ESM bundle, the minified UMD bundle, and the plain and minified stylesheets.npm run dev— watch build intodemo/dist/, plus a Vite dev server fordemo/at http://localhost:3001 with live reload.host: true, so the demo also answers on the LAN address Vite prints.npm run lint/npm run format— ESLint / Prettier.
scripts/build.mjs is the whole build configuration (configFile: false) —
there is no vite.config.js. Sourcemaps are emitted for the demo only; the
published dist/ carries none, because Rolldown inlines sourcesContent and
would ship src/ a second time inside them.
Build output
| File | Format |
| ----------------------------- | ----------------------------------------- |
| cart-progress-bar.esm.js | Unminified ESM |
| cart-progress-bar.min.js | Minified UMD, global CartProgressBar |
| cart-progress-bar.css | Plain stylesheet |
| cart-progress-bar.min.css | Minified stylesheet |
License
MIT License - see LICENSE file for details.
