# Review filtering by star rating is functional

- **Pattern:** `ab-001207` (`ecommerce-reviews.display-ux.review-filtering`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001207
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001207)

## Why it matters

On products with 50+ reviews, shoppers looking to validate a concern — say, "does this fail after six months?" — cannot surface 1-star and 2-star reviews without scrolling through dozens of positives. A star-rating filter lets them find that signal in one click, which increases time-on-page and reduces refund rates because buyers self-disqualify before purchase instead of after. Without filters, low-rated reviews get drowned and the product reads falsely uniform.

## Severity rationale

Low because filtering is a quality-of-life affordance; reviews are still readable without it, just harder to navigate at scale.

## Remediation

Render a `components/ReviewFilter.tsx` component with a checkbox per rating level (1-5), track selected ratings in state, and pass them to the review query as a `WHERE rating IN (...)` clause. Keep the control visible above the review list:

```tsx
{[5, 4, 3, 2, 1].map(rating => (
  <label key={rating}>
    <input
      type="checkbox"
      checked={selectedRatings.includes(rating)}
      onChange={(e) => toggle(rating, e.target.checked)}
    />
    {rating} stars
  </label>
))}
```

## Detection

- **ID:** `review-filtering`
- **Severity:** `low`
- **What to look for:** List all filter controls in the review display area. For each filter, count the number of rating levels it supports (1-star through 5-star). Verify the filter onChange handler triggers a re-query or client-side filter that changes the displayed reviews.
- **Pass criteria:** A filter control exists supporting at least 5 rating levels (1 through 5 stars) and successfully filters reviews by the selected rating when activated. The filter must produce a visible change in the displayed review list.
- **Fail criteria:** No filter control exists, or the filter UI renders but has no functional onChange handler that actually filters the review list.
- **Skip (N/A) when:** The project has fewer than 10 reviews total in the database, making filtering impractical.
- **Detail on fail:** `"No star rating filter found in review display components. Users cannot narrow 47 reviews by rating."`
- **Remediation:** Add a filter component in `components/ReviewFilter.tsx`:

  ```tsx
  // components/ReviewFilter.tsx
  export function ReviewFilter({ selectedRatings, onFilter }) {
    return (
      <div className="rating-filters">
        {[5, 4, 3, 2, 1].map(rating => (
          <label key={rating}>
            <input
              type="checkbox"
              checked={selectedRatings.includes(rating)}
              onChange={(e) => {
                if (e.target.checked) {
                  onFilter([...selectedRatings, rating])
                } else {
                  onFilter(selectedRatings.filter(r => r !== rating))
                }
              }}
            />
            {rating}⭐
          </label>
        ))}
      </div>
    )
  }
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001207
