All components Zyqor Components

Component · pricing-table

Pricing switcher

Zyqor Studio's real starting prices in one switcher: a pill that squishes as it slides, a price that rolls digit by digit, and real keyboard tabs.

Vanilla JS1.9 KBARIA tabsOdometerReduced motion

starting price, USD

Zyqor Studio's real starting prices, in Sujon's own words. The exact scope is agreed for each project before any work starts.

Three tiers are on Sujon's own list of things to avoid, but these are his real prices, so they are shown as one switcher rather than three cards in a row.

Use it

Copy the folder pricing-table/ (the .js and .css files) into your project. No build step and no framework.

Behaviour

  • Real ARIA tabs: arrow keys, Home and End move between plans; only the selected tab is in the tab order.
  • The price rolls digit by digit; screen readers hear the plain price once (aria-label + polite live region).
  • Feature rows use a short SVG dash, not checkmarks (Sujon's avoid list).
  • Phone: the switcher spans the width and the plan sits under the price; same animation.
  • prefers-reduced-motion: no slide, no roll, no squish.

Credits

  • Prices and plan descriptions: Sujon Hoque, Zyqor Studio (Oct 2026). Exact scope is agreed per project.
  • Spec from his Drive guide: liquid squish segmented toggle (MA 6.2 item 1) and rolling odometer numbers for real numbers only (MA 6.2 item 4). Written from scratch.
<link rel="stylesheet" href="pricing-table.css">
<div class="pr" data-pricing data-start="0">
  <div>
    <div class="pr-seg" role="tablist" aria-label="Plans">
      <span class="pr-pill" aria-hidden="true"></span>
      <button type="button" role="tab" id="t1" aria-controls="p1" data-price="300">Simple</button>
      <button type="button" role="tab" id="t2" aria-controls="p2" data-price="1000">Scroll 3D</button>
    </div>
    <p class="pr-price" aria-live="polite"></p><p class="pr-unit"></p>
  </div>
  <div>
    <section class="pr-plan" role="tabpanel" id="p1" aria-labelledby="t1" hidden>...</section>
    <section class="pr-plan" role="tabpanel" id="p2" aria-labelledby="t2" hidden>...</section>
  </div>
</div>
<script type="module" src="pricing-table.js"></script>
OptionDefaultWhat it does
data-pricePrice for that plan (a number); the odometer formats it as $1,000.
data-unit"starting price"Small label under the price for that plan.
data-start0Plan selected on load.