Order History

Your orders

@use 'sprucecss/scss/spruce' as *;

.order-history {
  @include layout-stack('m');

  &__top {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: spacer('s');
    justify-content: space-between;
  }

  &__title {
    font-size: font-size('h3');
    margin: 0;
  }

  &__filter {
    @include layout-cluster('xs');

    .form-control {
      inline-size: auto;
    }
  }

  &__label {
    color: color('muted');
    font-size: config('font-size-sm', $typography);
  }

  &__list {
    // The parent's layout-stack sets the margins.
    list-style: none;
    padding: 0;
    @include layout-stack('s');
  }

  &__order {
    background-color: color('surface');
    border: config('border-width-base', $display) solid color('border');
    border-radius: radius('lg');
    overflow: hidden;
  }

  &__header {
    align-items: center;
    background-color: color('surface-muted');
    border-block-end: config('border-width-base', $display) solid color('border');
    display: flex;
    flex-wrap: wrap;
    gap: spacer('xs') spacer('m');
    justify-content: space-between;
    padding: spacer('s') spacer('m');
  }

  &__facts {
    display: flex;
    flex-wrap: wrap;
    gap: spacer('xs') spacer('l');
    margin: 0;

    dt {
      color: color('muted');
      font-size: 0.75rem;
      font-weight: 400;
    }

    dd {
      color: color('heading');
      font-weight: 700;
      margin: 0;
    }
  }

  &__invoice {
    font-size: config('font-size-sm', $typography);
  }

  &__body {
    align-items: center;
    display: grid;
    gap: spacer('s') spacer('m');
    padding: spacer('m');

    @include breakpoint('md') {
      grid-template-columns: minmax(0, 1fr) auto auto;
    }
  }

  &__status {
    @include layout-stack('xxs');

    p {
      margin: 0;
    }
  }

  &__badge {
    align-items: center;
    color: color('heading');
    display: flex;
    font-weight: 700;
    gap: spacer('xs');

    &::before {
      aspect-ratio: 1;
      background-color: color('muted');
      border-radius: 50%;
      content: '';
      inline-size: 0.625rem;
    }

    &--shipped::before {
      background-color: color('info', 'alert');
    }

    &--delivered::before {
      background-color: color('success', 'alert');
    }

    &--returned::before {
      background-color: color('warning', 'alert');
    }
  }

  &__note,
  &__count {
    color: color('muted');
    font-size: config('font-size-sm', $typography);
  }

  &__items {
    @include clear-list;
    display: flex;
    gap: spacer('xs');

    li {
      margin: 0;
    }

    img {
      aspect-ratio: 1;
      background-color: color('surface-muted');
      border-radius: radius('md');
      inline-size: 4rem;
      object-fit: cover;
    }

    // The items sit side by side: clear the stack margins of the base list style.
    > li {
      margin-block: 0;
      padding-block: 0;
    }
  }

  &__actions {
    display: flex;
    flex-wrap: wrap;
    gap: spacer('xs');

    @include breakpoint('md') {
      flex-direction: column;

      .btn {
        inline-size: 100%;
      }
    }
  }
}
<section class="order-history" aria-labelledby="order-history-title">
    <header class="order-history__top">
        <h2 class="order-history__title" id="order-history-title">Your orders</h2>
        <form class="order-history__filter" action="#" method="get">
            <label class="order-history__label" for="order-history-period">Show orders from</label>
            <select class="form-control form-control--sm" id="order-history-period" name="period">
                <option value="3m">The last 3 months</option>
                <option value="2026">2026</option>
                <option value="2025">2025</option>
            </select>
            <button class="btn btn--outline-secondary btn--sm" type="submit">Show</button>
        </form>
    </header>
    <ol class="order-history__list" role="list">
    <li>
        <article class="order-history__order" aria-labelledby="order-10482">
            <header class="order-history__header">
                <dl class="order-history__facts">
                    <div><dt>Order</dt><dd id="order-10482">#10482</dd></div>
                    <div><dt>Placed</dt><dd><time datetime="2026-10-03">October 3, 2026</time></dd></div>
                    <div><dt>Total</dt><dd>$186.84</dd></div>
                </dl>
                <a class="order-history__invoice" href="#">Invoice<span class="sr-only"> for order #10482</span> <span aria-hidden="true">(PDF)</span></a>
            </header>
            <div class="order-history__body">
                <div class="order-history__status">
                    <p class="order-history__badge order-history__badge--shipped">On the way</p>
                    <p class="order-history__note">Arriving Thursday, October 8</p>
                    <p class="order-history__count">3 items</p>
                </div>
                <ul class="order-history__items" role="list" aria-label="Products">
                <li><img src="https://images.unsplash.com/photo-1577733966973-d680bffd2e80?auto=format&fit=crop&w=128&h=128&q=60" alt="" width="64" height="64" loading="lazy"></li>
                <li><img src="https://images.unsplash.com/photo-1602143407151-7111542de6e8?auto=format&fit=crop&w=128&h=128&q=60" alt="" width="64" height="64" loading="lazy"></li>
                </ul>
                <div class="order-history__actions">
                <a class="btn btn--primary btn--sm" href="#">Track package<span class="sr-only">, order #10482</span></a>
                <a class="btn btn--outline-secondary btn--sm" href="#">View order<span class="sr-only">, order #10482</span></a>
                </div>
            </div>
        </article>
    </li>
    <li>
        <article class="order-history__order" aria-labelledby="order-10215">
            <header class="order-history__header">
                <dl class="order-history__facts">
                    <div><dt>Order</dt><dd id="order-10215">#10215</dd></div>
                    <div><dt>Placed</dt><dd><time datetime="2026-09-12">September 12, 2026</time></dd></div>
                    <div><dt>Total</dt><dd>$89.00</dd></div>
                </dl>
                <a class="order-history__invoice" href="#">Invoice<span class="sr-only"> for order #10215</span> <span aria-hidden="true">(PDF)</span></a>
            </header>
            <div class="order-history__body">
                <div class="order-history__status">
                    <p class="order-history__badge order-history__badge--delivered">Delivered</p>
                    <p class="order-history__note">Delivered on September 15</p>
                    <p class="order-history__count">1 item</p>
                </div>
                <ul class="order-history__items" role="list" aria-label="Products">
                <li><img src="https://images.unsplash.com/photo-1553062407-98eeb64c6a62?auto=format&fit=crop&w=128&h=128&q=60" alt="" width="64" height="64" loading="lazy"></li>
                </ul>
                <div class="order-history__actions">
                <a class="btn btn--outline-secondary btn--sm" href="#">Buy again<span class="sr-only">, order #10215</span></a>
                <a class="btn btn--outline-secondary btn--sm" href="#">View order<span class="sr-only">, order #10215</span></a>
                </div>
            </div>
        </article>
    </li>
    <li>
        <article class="order-history__order" aria-labelledby="order-9874">
            <header class="order-history__header">
                <dl class="order-history__facts">
                    <div><dt>Order</dt><dd id="order-9874">#9874</dd></div>
                    <div><dt>Placed</dt><dd><time datetime="2026-08-20">August 20, 2026</time></dd></div>
                    <div><dt>Total</dt><dd>$241.00</dd></div>
                </dl>
                <a class="order-history__invoice" href="#">Invoice<span class="sr-only"> for order #9874</span> <span aria-hidden="true">(PDF)</span></a>
            </header>
            <div class="order-history__body">
                <div class="order-history__status">
                    <p class="order-history__badge order-history__badge--returned">Refunded</p>
                    <p class="order-history__note">Refund of $42.00 issued on August 29</p>
                    <p class="order-history__count">2 items</p>
                </div>
                <ul class="order-history__items" role="list" aria-label="Products">
                <li><img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?auto=format&fit=crop&w=128&h=128&q=60" alt="" width="64" height="64" loading="lazy"></li>
                <li><img src="https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?auto=format&fit=crop&w=128&h=128&q=60" alt="" width="64" height="64" loading="lazy"></li>
                </ul>
                <div class="order-history__actions">
                <a class="btn btn--outline-secondary btn--sm" href="#">View order<span class="sr-only">, order #9874</span></a>
                </div>
            </div>
        </article>
    </li>
    </ol>
</section>

Order History

The order list of a customer account: every order with its number, date, total, status, products and the next actions (track, buy again, invoice).

Anatomy

  • .order-history__top: the title and a GET filter for the period.
  • .order-history__order: an article per order, labelled by its number. The __header holds the key facts (a description list) and the invoice link; the __body the __status, the product __items and the __actions.
  • .order-history__badge: the status (--shipped, --delivered, --returned).

Accessibility and Usability

  • The orders are an ordered list (newest first) of articles, each labelled by its order number, so screen reader users can jump between them.
  • The repeated links and buttons have hidden context ("View order, order #10482", "Invoice for order #10482"), so a list of links makes sense out of context.
  • The status is text ("On the way") with a sentence that answers the next question ("Arriving Thursday, October 8"); the colored dot is decorative.
  • Lead with the most useful action for the state: "Track package" while it's on the way, "Buy again" after delivery.

Technical Details

  • No JavaScript: the filter is a GET form, and the actions are links.
  • The product images are decorative (alt=""); the order detail page lists the products by name. If you show only the images, give them the product names as alt text.
  • From the md breakpoint, the status, the images and the actions sit in one row; below it, they stack.
  • Link "Track package" to the Order Tracking and the invoice to the Invoice.

Documentation

Learn about Spruce CSS through our extensive documentation.

Components

Explore our UI library of accessible components built with Spruce CSS.

Blocks and Pages

Full-width page blocks and complete page templates, ready to copy.

Find us on GitHub

Did you find a bug? Have an idea or a question? Please open an issue to help us develop the project.