Skip to content

feat(billing): Move locked products to bottom of usage overview table#107701

Merged
dashed merged 5 commits intomasterfrom
billing/BIL-2114
Feb 6, 2026
Merged

feat(billing): Move locked products to bottom of usage overview table#107701
dashed merged 5 commits intomasterfrom
billing/BIL-2114

Conversation

@dashed
Copy link
Copy Markdown
Member

@dashed dashed commented Feb 5, 2026

Closes https://linear.app/getsentry/issue/BIL-2114/move-locked-products-to-bottom-of-subscription-overview-table

Summary

  • Reorder the subscription overview usage table so that locked/disabled products are grouped at the bottom, instead of being interspersed with enabled products based on their backend order field
  • Extract inline rendering logic into reusable helpers (renderCategoryRow, renderAddOnRows) to support the partitioning without code duplication

Fixes BIL-2114

How it works

Uses the existing productIsEnabled() utility to partition both regular data categories and add-on categories into enabled/disabled groups at the table level. The rendering order becomes:

  1. Enabled regular categories (sorted by existing order)
  2. Enabled add-ons (with sub-category rows)
  3. Disabled/locked regular categories (with lock icon)
  4. Disabled/locked add-ons (with lock icon)

No changes to individual row rendering, side panel behavior, or trial CTAs.

Screenshot 2026-02-05 at 4 33 45 PM

Test plan

  • All 44 existing usage overview tests pass (5 test suites)
  • New test verifies all disabled rows appear after all enabled rows in DOM order
  • Pre-commit hooks pass (eslint, stylelint, prettier)
  • Visual verification on subscription overview page with a plan that has both enabled and disabled products

@linear
Copy link
Copy Markdown

linear bot commented Feb 5, 2026

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Feb 5, 2026
@dashed dashed marked this pull request as ready for review February 5, 2026 21:34
@dashed dashed requested a review from a team as a code owner February 5, 2026 21:34
Copy link
Copy Markdown
Member

@shashjar shashjar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, left a couple of nits

const filteredCategories = sortedCategories.filter(
categoryInfo => !addOnDataCategories.includes(categoryInfo.category)
);
const enabledCategories = filteredCategories.filter(categoryInfo =>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking but if you prefer i think you could use lodash/partition to simplify the enabled/disabled filtering here and for the add-ons

addOnInfo => !productIsEnabled(subscription, addOnInfo.apiName)
);

const renderCategoryRow = (categoryInfo: (typeof sortedCategories)[number]) => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe worth extracting the type out here and in renderAddOnRows for clarity?

Extract inline rendering logic into `renderCategoryRow` and
`renderAddOnRows` helper functions, and pre-compute
`filteredCategories` and `availableAddOns` before the return
statement. No behavior change.
Partition categories and add-ons into enabled/disabled groups using
`productIsEnabled`, then render enabled products first followed by
disabled (locked) products at the bottom. This improves the UX by
grouping active products together instead of interspersing locked
products throughout the list.

BIL-2114
Add test that asserts all disabled product rows appear after all
enabled product rows in DOM order, validating the locked-products-
at-bottom behavior.

BIL-2114
Address PR feedback:
- Use `lodash/partition` instead of dual filter calls for
  enabled/disabled partitioning
- Replace inline `typeof` expressions with named types
  (`BillingMetricHistory`, `AddOnCategoryInfo`) for clarity
Replace document.querySelectorAll with screen.getAllByTestId to follow
React Testing Library conventions.
@dashed dashed enabled auto-merge (squash) February 6, 2026 16:58
@dashed dashed merged commit 2b2d18d into master Feb 6, 2026
59 checks passed
@dashed dashed deleted the billing/BIL-2114 branch February 6, 2026 17:01
jaydgoss pushed a commit that referenced this pull request Feb 12, 2026
…#107701)

Closes
https://linear.app/getsentry/issue/BIL-2114/move-locked-products-to-bottom-of-subscription-overview-table

## Summary
- Reorder the subscription overview usage table so that locked/disabled
products are grouped at the bottom, instead of being interspersed with
enabled products based on their backend `order` field
- Extract inline rendering logic into reusable helpers
(`renderCategoryRow`, `renderAddOnRows`) to support the partitioning
without code duplication

Fixes BIL-2114

## How it works
Uses the existing `productIsEnabled()` utility to partition both regular
data categories and add-on categories into enabled/disabled groups at
the table level. The rendering order becomes:

1. Enabled regular categories (sorted by existing `order`)
2. Enabled add-ons (with sub-category rows)
3. Disabled/locked regular categories (with lock icon)
4. Disabled/locked add-ons (with lock icon)

No changes to individual row rendering, side panel behavior, or trial
CTAs.

<img width="1001" height="691" alt="Screenshot 2026-02-05 at 4 33 45 PM"
src="https://github.com/user-attachments/assets/a9c18afc-b515-4c82-b10a-e925feb1d3bb"
/>


## Test plan
- [x] All 44 existing usage overview tests pass (5 test suites)
- [x] New test verifies all disabled rows appear after all enabled rows
in DOM order
- [x] Pre-commit hooks pass (eslint, stylelint, prettier)
- [ ] Visual verification on subscription overview page with a plan that
has both enabled and disabled products
dcramer pushed a commit that referenced this pull request Feb 17, 2026
…#107701)

Closes
https://linear.app/getsentry/issue/BIL-2114/move-locked-products-to-bottom-of-subscription-overview-table

## Summary
- Reorder the subscription overview usage table so that locked/disabled
products are grouped at the bottom, instead of being interspersed with
enabled products based on their backend `order` field
- Extract inline rendering logic into reusable helpers
(`renderCategoryRow`, `renderAddOnRows`) to support the partitioning
without code duplication

Fixes BIL-2114

## How it works
Uses the existing `productIsEnabled()` utility to partition both regular
data categories and add-on categories into enabled/disabled groups at
the table level. The rendering order becomes:

1. Enabled regular categories (sorted by existing `order`)
2. Enabled add-ons (with sub-category rows)
3. Disabled/locked regular categories (with lock icon)
4. Disabled/locked add-ons (with lock icon)

No changes to individual row rendering, side panel behavior, or trial
CTAs.

<img width="1001" height="691" alt="Screenshot 2026-02-05 at 4 33 45 PM"
src="https://github.com/user-attachments/assets/a9c18afc-b515-4c82-b10a-e925feb1d3bb"
/>


## Test plan
- [x] All 44 existing usage overview tests pass (5 test suites)
- [x] New test verifies all disabled rows appear after all enabled rows
in DOM order
- [x] Pre-commit hooks pass (eslint, stylelint, prettier)
- [ ] Visual verification on subscription overview page with a plan that
has both enabled and disabled products
@github-actions github-actions bot locked and limited conversation to collaborators Feb 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants