Commerce

Order summary

Subtotal, discounts, shipping, tax and total for a cart or checkout, collapsible on a phone.

Built on
<dl><details>::details-contentContainer queriesIntl.NumberFormat<data>
Client JavaScript
None
Works without React
Yes, as HTML and CSS
Source, gzipped
3.2 kB
Built from
Icon
Subtotal
$124.00
Code SPRING10
Discount, minus $12.40
Shipping
Free
Total
$111.60
Code
import { OrderSummary } from "@/components/equip/order-summary";

export default function Demo() {
  return (
    <OrderSummary
      style={{ width: 224 }}
      subtotal={124}
      discounts={[{ label: "Code SPRING10", amount: 12.4 }]}
      shipping="free"
    />
  );
}
HTMLworks in any framework, with the part's CSS
<div style="width:224px" class="eq-order-summary">
  <div class="eq-order-summary-body">
    <dl class="eq-order-summary-list">
      <div class="eq-order-summary-row" data-kind="subtotal">
        <dt class="eq-order-summary-label">Subtotal</dt>
        <dd class="eq-order-summary-value">
          <data value="124">$124.00</data>
        </dd>
      </div>
      <div class="eq-order-summary-row" data-kind="discount">
        <dt class="eq-order-summary-label"><svg aria-hidden="true" focusable="false" class="eq-icon eq-order-summary-tag" data-size="s" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h7.5l8.5 8.5-7.5 7.5L4 11.5z" /><path d="M7.5 9a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0 -3 0" /></svg>Code SPRING10</dt>
        <dd class="eq-order-summary-value">
          <data value="-12.4"><span aria-hidden="true">-$12.40</span><span class="eq-order-summary-hidden">Discount, minus $12.40</span></data>
        </dd>
      </div>
      <div class="eq-order-summary-row" data-kind="shipping">
        <dt class="eq-order-summary-label">Shipping</dt>
        <dd class="eq-order-summary-value">
          <span class="eq-order-summary-free">Free</span>
        </dd>
      </div>
    </dl>
    <dl class="eq-order-summary-totals">
      <div class="eq-order-summary-row" data-kind="total">
        <dt class="eq-order-summary-label">Total</dt>
        <dd class="eq-order-summary-value">
          <data value="111.6">$111.60</data>
        </dd>
      </div>
    </dl>
  </div>
</div>

Examples

Checkout sidebar

Discounts read as "Discount, minus $18.40", and the total is worked out from the rows unless you pass one.

Order summary

Subtotal (3 items)
$184.00
Code SPRING10
Discount, minus $18.40
Member price
Discount, minus $5.00
Shipping
$6.95
Estimated tax
$13.71
Total
$181.26
Code
import { OrderSummary } from "@/components/equip/order-summary";
import { Button } from "@/components/equip/button";

export default function Example() {
  return (
    <div
      style={{
        width: "100%",
        maxWidth: 340,
        boxSizing: "border-box",
        padding: 20,
        border: "1px solid var(--eq-line)",
        borderRadius: "var(--eq-radius-l)",
        background: "var(--eq-surface)",
        display: "grid",
        gap: 16,
      }}
    >
      <OrderSummary
        title="Order summary"
        itemCount={3}
        subtotal={184}
        discounts={[
          { label: "Code SPRING10", amount: 18.4 },
          { label: "Member price", amount: 5 },
        ]}
        shipping={6.95}
        tax={13.71}
        taxLabel="Estimated tax"
      />
      <Button variant="accent" size="l" style={{ width: "100%" }}>
        Place order
      </Button>
    </div>
  );
}
HTMLworks in any framework, with the part's CSS
<div style="width:100%;max-width:340px;box-sizing:border-box;padding:20px;border:1px solid var(--eq-line);border-radius:var(--eq-radius-l);background:var(--eq-surface);display:grid;gap:16px">
  <div class="eq-order-summary">
    <h2 class="eq-order-summary-title">Order summary</h2>
    <div class="eq-order-summary-body">
      <dl class="eq-order-summary-list">
        <div class="eq-order-summary-row" data-kind="subtotal">
          <dt class="eq-order-summary-label">Subtotal<span class="eq-order-summary-count"> (3 items)</span></dt>
          <dd class="eq-order-summary-value">
            <data value="184">$184.00</data>
          </dd>
        </div>
        <div class="eq-order-summary-row" data-kind="discount">
          <dt class="eq-order-summary-label"><svg aria-hidden="true" focusable="false" class="eq-icon eq-order-summary-tag" data-size="s" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h7.5l8.5 8.5-7.5 7.5L4 11.5z" /><path d="M7.5 9a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0 -3 0" /></svg>Code SPRING10</dt>
          <dd class="eq-order-summary-value">
            <data value="-18.4"><span aria-hidden="true">-$18.40</span><span class="eq-order-summary-hidden">Discount, minus $18.40</span></data>
          </dd>
        </div>
        <div class="eq-order-summary-row" data-kind="discount">
          <dt class="eq-order-summary-label"><svg aria-hidden="true" focusable="false" class="eq-icon eq-order-summary-tag" data-size="s" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h7.5l8.5 8.5-7.5 7.5L4 11.5z" /><path d="M7.5 9a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0 -3 0" /></svg>Member price</dt>
          <dd class="eq-order-summary-value">
            <data value="-5"><span aria-hidden="true">-$5.00</span><span class="eq-order-summary-hidden">Discount, minus $5.00</span></data>
          </dd>
        </div>
        <div class="eq-order-summary-row" data-kind="shipping">
          <dt class="eq-order-summary-label">Shipping</dt>
          <dd class="eq-order-summary-value">
            <data value="6.95">$6.95</data>
          </dd>
        </div>
        <div class="eq-order-summary-row" data-kind="tax">
          <dt class="eq-order-summary-label">Estimated tax</dt>
          <dd class="eq-order-summary-value">
            <data value="13.71">$13.71</data>
          </dd>
        </div>
      </dl>
      <dl class="eq-order-summary-totals">
        <div class="eq-order-summary-row" data-kind="total">
          <dt class="eq-order-summary-label">Total</dt>
          <dd class="eq-order-summary-value">
            <data value="181.26">$181.26</data>
          </dd>
        </div>
      </dl>
    </div>
  </div>
  <button style="width:100%" type="button" class="eq-button" data-variant="accent" data-size="l">
    <span class="eq-button-label">Place order</span>
  </button>
</div>

Collapsible on a phone

Below 30rem the rows sit behind a native disclosure that shows the total; with "auto" a wider container shows them plainly.

Show order summaryHide order summary$90.38
Subtotal (2 items)
$98.00
Code WELCOME15
Discount, minus $14.70
Shipping
Calculated at the next step
Estimated tax
$7.08
Total
$90.38
Code
import { OrderSummary } from "@/components/equip/order-summary";

export default function Example() {
  return (
    <div style={{ width: "100%", maxWidth: 320, padding: 12, boxSizing: "border-box", border: "1px solid var(--eq-line)", borderRadius: "var(--eq-radius-m)" }}>
      <OrderSummary
        collapsible="auto"
        itemCount={2}
        subtotal={98}
        discounts={[{ label: "Code WELCOME15", amount: 14.7 }]}
        shipping={null}
        tax={7.08}
        taxLabel="Estimated tax"
      />
    </div>
  );
}
HTMLworks in any framework, with the part's CSS
<div style="width:100%;max-width:320px;padding:12px;box-sizing:border-box;border:1px solid var(--eq-line);border-radius:var(--eq-radius-m)">
  <div class="eq-order-summary" data-collapsible="auto">
    <details class="eq-order-summary-disclosure">
      <summary class="eq-order-summary-toggle"><span class="eq-order-summary-toggle-label"><span class="eq-order-summary-show">Show order summary</span><span class="eq-order-summary-hide">Hide order summary</span></span><svg aria-hidden="true" focusable="false" class="eq-icon eq-order-summary-chevron" data-size="s" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M5.5 9 12 15.5 18.5 9" /></svg><data class="eq-order-summary-toggle-total" value="90.38">$90.38</data></summary>
      <div class="eq-order-summary-body">
        <dl class="eq-order-summary-list">
          <div class="eq-order-summary-row" data-kind="subtotal">
            <dt class="eq-order-summary-label">Subtotal<span class="eq-order-summary-count"> (2 items)</span></dt>
            <dd class="eq-order-summary-value">
              <data value="98">$98.00</data>
            </dd>
          </div>
          <div class="eq-order-summary-row" data-kind="discount">
            <dt class="eq-order-summary-label"><svg aria-hidden="true" focusable="false" class="eq-icon eq-order-summary-tag" data-size="s" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h7.5l8.5 8.5-7.5 7.5L4 11.5z" /><path d="M7.5 9a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0 -3 0" /></svg>Code WELCOME15</dt>
            <dd class="eq-order-summary-value">
              <data value="-14.7"><span aria-hidden="true">-$14.70</span><span class="eq-order-summary-hidden">Discount, minus $14.70</span></data>
            </dd>
          </div>
          <div class="eq-order-summary-row" data-kind="shipping">
            <dt class="eq-order-summary-label">Shipping</dt>
            <dd class="eq-order-summary-value">
              <span class="eq-order-summary-pending">Calculated at the next step</span>
            </dd>
          </div>
          <div class="eq-order-summary-row" data-kind="tax">
            <dt class="eq-order-summary-label">Estimated tax</dt>
            <dd class="eq-order-summary-value">
              <data value="7.08">$7.08</data>
            </dd>
          </div>
        </dl>
        <dl class="eq-order-summary-totals">
          <div class="eq-order-summary-row" data-kind="total">
            <dt class="eq-order-summary-label">Total</dt>
            <dd class="eq-order-summary-value">
              <data value="90.38">$90.38</data>
            </dd>
          </div>
        </dl>
      </div>
    </details>
  </div>
</div>

Euros with VAT included

taxMode="included" keeps the VAT out of the sum and states it under the total, as European prices show it.

Subtotal (2 items)
149,90 €
Code HERBST20
Discount, minus 29,98 €
Shipping
4,90 €
Total
124,82 €
Includes 19% VAT
19,93 €
Code
import { OrderSummary } from "@/components/equip/order-summary";

export default function Example() {
  return (
    <OrderSummary
      style={{ maxWidth: 340 }}
      currency="EUR"
      locale="de-DE"
      itemCount={2}
      subtotal={149.9}
      discounts={[{ label: "Code HERBST20", amount: 29.98 }]}
      shipping={4.9}
      tax={19.93}
      taxMode="included"
      taxLabel="Includes 19% VAT"
    />
  );
}
HTMLworks in any framework, with the part's CSS
<div style="max-width:340px" class="eq-order-summary">
  <div class="eq-order-summary-body">
    <dl class="eq-order-summary-list">
      <div class="eq-order-summary-row" data-kind="subtotal">
        <dt class="eq-order-summary-label">Subtotal<span class="eq-order-summary-count"> (2 items)</span></dt>
        <dd class="eq-order-summary-value">
          <data value="149.9">149,90 €</data>
        </dd>
      </div>
      <div class="eq-order-summary-row" data-kind="discount">
        <dt class="eq-order-summary-label"><svg aria-hidden="true" focusable="false" class="eq-icon eq-order-summary-tag" data-size="s" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h7.5l8.5 8.5-7.5 7.5L4 11.5z" /><path d="M7.5 9a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0 -3 0" /></svg>Code HERBST20</dt>
        <dd class="eq-order-summary-value">
          <data value="-29.98"><span aria-hidden="true">-29,98 €</span><span class="eq-order-summary-hidden">Discount, minus 29,98 €</span></data>
        </dd>
      </div>
      <div class="eq-order-summary-row" data-kind="shipping">
        <dt class="eq-order-summary-label">Shipping</dt>
        <dd class="eq-order-summary-value">
          <data value="4.9">4,90 €</data>
        </dd>
      </div>
    </dl>
    <dl class="eq-order-summary-totals">
      <div class="eq-order-summary-row" data-kind="total">
        <dt class="eq-order-summary-label">Total</dt>
        <dd class="eq-order-summary-value">
          <data value="124.82000000000001">124,82 €</data>
        </dd>
      </div>
      <div class="eq-order-summary-row" data-kind="included">
        <dt class="eq-order-summary-label">Includes 19% VAT</dt>
        <dd class="eq-order-summary-value">
          <data value="19.93">19,93 €</data>
        </dd>
      </div>
    </dl>
  </div>
</div>

Props

PropTypeDefaultWhat it does
subtotalnumbernoneSum of the lines before discounts, in major units.
discounts{ label: string; amount: number }[][]Each a row such as "Code SPRING10", with a positive amount shown as a minus and read as "Discount, minus".
shippingnumber | "free" | nullnoneAn amount; "free" or 0 for Free; null for "Calculated at the next step". Leave out to hide the row.
taxnumbernoneTax amount. Leave out to hide the row.
taxLabelstring"Tax" or "Includes tax"Label of the tax row, such as "Estimated tax" or "Includes 19% VAT".
taxMode"added" | "included""added"added sums tax into the total; included states it under the total without adding it.
totalnumbernoneReplaces the total worked out from the rows.
itemCountnumbernoneAdds "(3 items)" to the subtotal label.
currencystring"USD"ISO 4217 currency code.
localestring"en-US"Sets the symbol position, separators and grouping.
titleReactNodenoneA heading above the rows, such as "Order summary".
headingLevel2 | 3 | 42The title's heading level.
collapsibleboolean | "auto"falsetrue puts the rows behind a "Show order summary" disclosure with the total; "auto" only below a 30rem container.
defaultOpenbooleanfalseWhether the disclosure starts open.
childrenReactNodenonePlaced above the total, such as a coupon field.
...restOmit<ComponentProps<"div">, "title">noneEvery native div attribute, applied to the root.

Anatomy

root.eq-order-summaryThe size container; data-collapsible is true or auto when set.
title.eq-order-summary-title
disclosure.eq-order-summary-disclosureA native <details>, only when collapsible.
toggle.eq-order-summary-toggleThe <summary>: label, chevron and total.
toggle label.eq-order-summary-toggle-label
show text.eq-order-summary-showShown while closed.
hide text.eq-order-summary-hideShown while open.
chevron.eq-order-summary-chevron
toggle total.eq-order-summary-toggle-total
body.eq-order-summary-body
list.eq-order-summary-listA <dl> of subtotal, discounts, shipping and tax.
row.eq-order-summary-rowA <div> holding one <dt> and <dd>; data-kind names the row.
label.eq-order-summary-label
value.eq-order-summary-valueEnd-aligned, tabular figures.
count.eq-order-summary-count
tag.eq-order-summary-tagThe tag icon before a discount label.
free.eq-order-summary-free
pending.eq-order-summary-pendingShipping not worked out yet.
extra.eq-order-summary-extraHolds children, above the total.
totals.eq-order-summary-totalsA second <dl> with the total and any included tax, under a rule.
hidden text.eq-order-summary-hiddenWords for screen readers only.

Keyboard

EnterSpaceOn the disclosure toggle, shows or hides the rows.

Notes

  • Renders on the server with no client JavaScript; the disclosure is a native <details>.
  • A <dl> rather than a table: each row is a name and a value, and screen readers read label then amount without table navigation.
  • Every amount uses the currency's own fraction digits, so $124.00 and $12.40 line up in the end-aligned column.
  • Discounts show the locale's minus sign and read as "Discount, minus $12.40"; the colour is never the only cue.
  • CSS cannot open a <details> by width, so "auto" keeps the disclosure in the DOM and, in a wide container, hides the toggle and shows the rows through ::details-content.
  • The toggle reads "Show order summary" or "Hide order summary" with the total, and the native element reports expanded or collapsed.
  • The total is the subtotal less discounts plus shipping and added tax, never below zero; pass total when your server has the final figure.
  • ::details-content is in Chrome 131, Safari 18.4 and Firefox 143. Elsewhere collapsible="auto" stays a disclosure at every width, so the rows are still one click away.

Source

Two files, and they are the whole part. Open either to read it, copy it straight from its bar, or add the part to your loadout and install it with everything else you picked.

components/equip/order-summary.tsx154 lines
import type { ComponentProps, ReactNode } from "react";
import { Icon } from "./icon";
import "./order-summary.css";

export type OrderSummaryDiscount = {
  /** Says where it comes from, such as "Code SPRING10" or "Member price". */
  label: string;
  /** The amount taken off, as a positive number in major units. */
  amount: number;
};

export type OrderSummaryProps = Omit<ComponentProps<"div">, "title"> & {
  subtotal: number;
  discounts?: OrderSummaryDiscount[];
  /** A number, "free" (or 0) for Free, null for "Calculated at the next step". Leave out to hide the row. */
  shipping?: number | "free" | null;
  /** Tax amount. Leave out to hide the row. */
  tax?: number;
  /** Label of the tax row, such as "Estimated tax" or "Includes 19% VAT". */
  taxLabel?: string;
  /** "added" puts tax on top of the total; "included" shows it as a note under the total. */
  taxMode?: "added" | "included";
  /** Replaces the total worked out from the lines above. */
  total?: number;
  /** Adds "(3 items)" to the subtotal label. */
  itemCount?: number;
  /** ISO 4217 code. */
  currency?: string;
  locale?: string;
  /** A heading above the rows, such as "Order summary". */
  title?: ReactNode;
  headingLevel?: 2 | 3 | 4;
  /** true wraps the rows in a disclosure; "auto" does so only in a narrow container, where supported. */
  collapsible?: boolean | "auto";
  /** Whether the disclosure starts open. */
  defaultOpen?: boolean;
  /** Placed above the total, such as a CouponField. */
  children?: ReactNode;
};

export function OrderSummary({
  subtotal,
  discounts = [],
  shipping,
  tax,
  taxLabel,
  taxMode = "added",
  total,
  itemCount,
  currency = "USD",
  locale = "en-US",
  title,
  headingLevel = 2,
  collapsible = false,
  defaultOpen = false,
  children,
  className,
  ...rest
}: OrderSummaryProps) {
  const money = new Intl.NumberFormat(locale, { style: "currency", currency });
  const off = discounts.reduce((sum, d) => sum + d.amount, 0);
  const shippingCost = typeof shipping === "number" ? shipping : 0;
  const taxAdded = taxMode === "added" && tax != null ? tax : 0;
  const grand = total ?? Math.max(0, subtotal - off + shippingCost + taxAdded);
  const Heading = `h${headingLevel}` as const;

  const row = (kind: string, label: ReactNode, value: ReactNode, key?: string) => (
    <div className="eq-order-summary-row" data-kind={kind} key={key}>
      <dt className="eq-order-summary-label">{label}</dt>
      <dd className="eq-order-summary-value">{value}</dd>
    </div>
  );

  const amount = (n: number) => <data value={n}>{money.format(n)}</data>;

  const rows = (
    <>
      <dl className="eq-order-summary-list">
        {row(
          "subtotal",
          <>
            Subtotal
            {itemCount != null && (
              <span className="eq-order-summary-count">
                {" "}
                ({itemCount} {itemCount === 1 ? "item" : "items"})
              </span>
            )}
          </>,
          amount(subtotal),
        )}
        {discounts.map((d, i) =>
          row(
            "discount",
            <>
              <Icon name="tag" size="s" className="eq-order-summary-tag" />
              {d.label}
            </>,
            <data value={-d.amount}>
              <span aria-hidden="true">{money.format(-d.amount)}</span>
              <span className="eq-order-summary-hidden">Discount, minus {money.format(d.amount)}</span>
            </data>,
            `${d.label}-${i}`,
          ),
        )}
        {shipping !== undefined &&
          row(
            "shipping",
            "Shipping",
            shipping === null ? (
              <span className="eq-order-summary-pending">Calculated at the next step</span>
            ) : shipping === "free" || shipping === 0 ? (
              <span className="eq-order-summary-free">Free</span>
            ) : (
              amount(shipping)
            ),
          )}
        {tax != null && taxMode === "added" && row("tax", taxLabel ?? "Tax", amount(tax))}
      </dl>
      {children != null && <div className="eq-order-summary-extra">{children}</div>}
      <dl className="eq-order-summary-totals">
        {row("total", "Total", amount(grand))}
        {tax != null && taxMode === "included" && row("included", taxLabel ?? "Includes tax", amount(tax))}
      </dl>
    </>
  );

  return (
    <div
      {...rest}
      className={["eq-order-summary", className].filter(Boolean).join(" ")}
      data-collapsible={collapsible === false ? undefined : String(collapsible)}
    >
      {title != null && <Heading className="eq-order-summary-title">{title}</Heading>}
      {collapsible === false ? (
        <div className="eq-order-summary-body">{rows}</div>
      ) : (
        <details className="eq-order-summary-disclosure" open={defaultOpen || undefined}>
          <summary className="eq-order-summary-toggle">
            <span className="eq-order-summary-toggle-label">
              <span className="eq-order-summary-show">Show order summary</span>
              <span className="eq-order-summary-hide">Hide order summary</span>
            </span>
            <Icon name="chevron-down" size="s" className="eq-order-summary-chevron" />
            <data className="eq-order-summary-toggle-total" value={grand}>
              {money.format(grand)}
            </data>
          </summary>
          <div className="eq-order-summary-body">{rows}</div>
        </details>
      )}
    </div>
  );
}
components/equip/order-summary.css221 lines
@layer equip {
  .eq-order-summary {
    container-type: inline-size;
    box-sizing: border-box;
    width: 100%;
    color: var(--eq-ink);
    font: var(--eq-weight) var(--eq-text-m) / 1.4 var(--eq-font);
  }

  .eq-order-summary-title {
    margin: 0 0 var(--eq-space-3);
    font-size: var(--eq-text-l);
    font-weight: var(--eq-weight-strong);
    line-height: 1.3;
  }

  .eq-order-summary-body {
    display: flex;
    flex-direction: column;
    gap: var(--eq-space-3);
  }

  .eq-order-summary-list,
  .eq-order-summary-totals {
    display: flex;
    flex-direction: column;
    gap: var(--eq-space-2);
    margin: 0;
  }

  /* Label at the start, amount at the end; the amount never wraps, the label may. */
  .eq-order-summary-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--eq-space-3);
  }

  .eq-order-summary-label {
    display: inline-flex;
    align-items: baseline;
    gap: var(--eq-space-1);
    min-width: 0;
    color: var(--eq-ink-2);
  }

  .eq-order-summary-value {
    margin: 0;
    margin-inline-start: auto;
    font-variant-numeric: tabular-nums;
    text-align: end;
    white-space: nowrap;
  }

  .eq-order-summary-count {
    color: var(--eq-ink-3);
  }

  .eq-order-summary-tag {
    align-self: center;
    color: var(--eq-ink-3);
  }

  .eq-order-summary-row[data-kind="discount"] .eq-order-summary-value {
    color: var(--eq-ok);
  }

  .eq-order-summary-free {
    color: var(--eq-ok);
    font-weight: var(--eq-weight-strong);
  }

  .eq-order-summary-pending {
    color: var(--eq-ink-2);
    font-size: var(--eq-text-s);
    white-space: normal;
  }

  .eq-order-summary-extra {
    padding-block: var(--eq-space-1);
  }

  /* The total stands apart: a rule above, a larger strong figure. */
  .eq-order-summary-totals {
    padding-top: var(--eq-space-3);
    border-top: 1px solid var(--eq-line-strong);
  }

  .eq-order-summary-row[data-kind="total"] .eq-order-summary-label {
    color: var(--eq-ink);
    font-weight: var(--eq-weight-strong);
  }

  .eq-order-summary-row[data-kind="total"] .eq-order-summary-value {
    font-size: var(--eq-text-l);
    font-weight: var(--eq-weight-strong);
    letter-spacing: -0.01em;
  }

  @container (width >= 20rem) {
    .eq-order-summary-row[data-kind="total"] .eq-order-summary-value {
      font-size: calc(var(--eq-text-l) * 1.25);
    }
  }

  .eq-order-summary-row[data-kind="included"] {
    margin-top: calc(-1 * var(--eq-space-1));
    font-size: var(--eq-text-s);
  }

  .eq-order-summary-row[data-kind="included"] .eq-order-summary-value {
    color: var(--eq-ink-2);
  }

  /* The disclosure: "Show order summary" and the total, on one row. */
  .eq-order-summary-toggle {
    display: flex;
    align-items: center;
    gap: var(--eq-space-1);
    min-height: var(--eq-h-m);
    margin-inline: calc(-1 * var(--eq-space-2));
    padding-inline: var(--eq-space-2);
    border-radius: var(--eq-radius-s);
    list-style: none;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--eq-dur) var(--eq-ease);
  }

  .eq-order-summary-toggle::-webkit-details-marker {
    display: none;
  }

  @media (hover: hover) {
    .eq-order-summary-toggle:hover {
      background: var(--eq-tint);
    }
  }

  .eq-order-summary-toggle:focus-visible {
    outline: 2px solid var(--eq-focus);
    outline-offset: 2px;
  }

  .eq-order-summary-toggle-label {
    font-weight: var(--eq-weight-strong);
  }

  .eq-order-summary-disclosure[open] .eq-order-summary-show,
  .eq-order-summary-disclosure:not([open]) .eq-order-summary-hide {
    display: none;
  }

  .eq-order-summary-chevron {
    color: var(--eq-ink-2);
    transition: rotate var(--eq-dur-move) var(--eq-spring);
  }

  .eq-order-summary-disclosure[open] .eq-order-summary-chevron {
    rotate: 180deg;
  }

  .eq-order-summary-toggle-total {
    margin-inline-start: auto;
    font-weight: var(--eq-weight-strong);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  /* Open: the total already sits at the bottom, so the toggle drops its copy. */
  .eq-order-summary-disclosure[open] .eq-order-summary-toggle-total {
    opacity: 0;
  }

  .eq-order-summary-disclosure .eq-order-summary-body {
    padding-top: var(--eq-space-3);
  }

  .eq-order-summary-disclosure[open] .eq-order-summary-body {
    transition:
      opacity var(--eq-dur-move) var(--eq-spring),
      translate var(--eq-dur-move) var(--eq-spring);
  }

  @starting-style {
    .eq-order-summary-disclosure[open] .eq-order-summary-body {
      opacity: 0;
      translate: 0 -4px;
    }
  }

  /* "auto": in a wide container the rows are always shown and the toggle goes. Only where
     ::details-content is supported, so a closed summary is never stuck shut. */
  @supports selector(::details-content) {
    @container (width >= 30rem) {
      .eq-order-summary[data-collapsible="auto"] .eq-order-summary-toggle {
        display: none;
      }

      .eq-order-summary[data-collapsible="auto"] .eq-order-summary-disclosure::details-content {
        content-visibility: visible;
      }

      .eq-order-summary[data-collapsible="auto"] .eq-order-summary-disclosure .eq-order-summary-body {
        padding-top: 0;
      }
    }
  }

  .eq-order-summary-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

EqUIp is in beta: free for non-commercial use, no warranty, and things can change. Terms

Nothing picked yet. Press A on a part, or use the plus on the board, and the install command builds here.

Loading the index.

Loading the index