style: cohesive empty-cart layout — single button rhythm, no duplicates

The empty-cart view rendered three different button sizes side-by-side:
two compact `mps-button-small` chips in the left well ("View Saved
Carts", "Let's go shopping!") and three full-width primaries in the
right column ("Make Cart Active", "Delete Cart", "Continue shopping").
"Let's go shopping!" and "Continue shopping" pointed at the same `/`
link — a literal duplicate split across two columns.

Fix:

  templates/cart.j2
    - Replace the centered `<br>`-stacked left block with a proper
      `.cart-empty-state` well that uses full-width buttons sized to
      match the right column.
    - Drop unrelated cosmetic class aliases (product-edit-button,
      cart-checkout-button) inherited from other contexts.
    - Hide the right column's "Continue shopping" when the cart is
      empty — same intent as "Let's go shopping!" above it.

  static/css/common.css
    - New .cart-empty-state / .cart-empty-hint / .cart-empty-actions
      Grid-only rules: stacked, centered, max-width 320 so the buttons
      don't stretch awkwardly wide. Reuses var(--space-N) tokens.

  templates/styleguide.j2
    - New "Empty Cart State" subsection under Cart Action Buttons so
      the pattern lives where future empty-state work can find it.

All 25 cart-related functional tests pass.
This commit is contained in:
russell@unturf.com 2026-05-15 10:19:04 -04:00
parent 55137af986
commit d86372c288
No known key found for this signature in database
3 changed files with 70 additions and 18 deletions

View file

@ -1237,11 +1237,44 @@ button.cart-public-button span.lock {
}
/* Continue shopping button */
.cart-continue-shopping {
display: grid;
justify-items: center;
margin-top: var(--space-3, 12px);
}
.cart-continue-shopping-button {
background-color: var(--color-blue, #98b6fa);
color: white;
}
/* Empty cart state stacked buttons matching the right column's
full-width treatment so the page reads as one cohesive button rhythm
instead of mixed small + full-width sizes. */
.cart-empty-state {
display: grid;
justify-items: center;
gap: var(--space-2, 8px);
padding: var(--space-4, 16px) var(--space-3, 12px);
text-align: center;
}
.cart-empty-state h2 {
margin: 0;
}
.cart-empty-hint {
margin: 0;
color: var(--text-muted, #777);
}
.cart-empty-actions {
display: grid;
gap: var(--space-2, 8px);
width: 100%;
max-width: 320px;
margin-top: var(--space-3, 12px);
}
.cart-empty-actions .mps-button {
width: 100%;
}
.coupon-apply-button {
background-color: var(--color-green, #a3c765);
}

View file

@ -134,22 +134,16 @@
{% if cart.is_empty %}
<center>
<h2>This cart is empty.</h2>
Nothing to see here.
{% if request.user and request.user.authenticated and request.user.carts.count() > 1 %}
<br/>
<br/>
<a href="/u/carts" class="product-edit-button mps-button mps-button-small">View Saved Carts</a>
<br/>
<br/> or
<br/>
<br/>
{% endif %}
<a href="/" class="cart-checkout-button mps-button mps-button-small mps-button-green">Let's go shopping!</a>
</center>
<div class="cart-empty-state">
<h2>This cart is empty.</h2>
<p class="cart-empty-hint">Nothing to see here.</p>
<div class="cart-empty-actions">
<a href="/" class="mps-button mps-button-green">Let's go shopping!</a>
{% if request.user and request.user.authenticated and request.user.carts.count() > 1 %}
<a href="/u/carts" class="mps-button">View Saved Carts</a>
{% endif %}
</div>
</div>
{% else %}
@ -396,9 +390,13 @@
<br/>
{% endif %}
<center>
{# When the cart is empty, "Let's go shopping!" in the empty-state
block already covers this intent — don't render twice. #}
{% if not cart.is_empty %}
<div class="cart-continue-shopping">
<a href="/" class="mps-button cart-continue-shopping-button">Continue shopping</a>
</center>
</div>
{% endif %}
</section>
{% endif %}

View file

@ -636,6 +636,27 @@ Dark mode: background-image patterns, colored borders</div>
.cart-delete-button — danger (#CC6958, white text)
.cart-remove-link — bare link, no button chrome</div>
</div>
<div class="sg-subsection">
<div class="sg-label">Empty Cart State</div>
<div class="sg-demo">
<div class="cart-empty-state" style="background: var(--surface-dim, #f9f9fa); border-radius: var(--radius-md, 8px);">
<h2>This cart is empty.</h2>
<p class="cart-empty-hint">Nothing to see here.</p>
<div class="cart-empty-actions">
<a href="#" class="mps-button mps-button-green">Let's go shopping!</a>
<a href="#" class="mps-button">View Saved Carts</a>
</div>
</div>
</div>
<div class="sg-code">.cart-empty-state — centered well, stacked heading + hint + actions
.cart-empty-hint — muted one-line subhead
.cart-empty-actions — width-capped grid of full-width stacked buttons
Primary CTA (green) first, secondary (default gray) below. Same
button size as the right-column saved-cart actions so the page reads
as one cohesive button rhythm instead of mixed small + full-width.</div>
</div>
</div>