Skip to content

Design improvements for retention offer#26712

Merged
minimaluminium merged 6 commits intomainfrom
retention-offer-design-improvements-BER-3388
Mar 5, 2026
Merged

Design improvements for retention offer#26712
minimaluminium merged 6 commits intomainfrom
retention-offer-design-improvements-BER-3388

Conversation

@minimaluminium
Copy link
Copy Markdown
Member

@minimaluminium minimaluminium commented Mar 5, 2026

ref https://linear.app/ghost/issue/BER-3388/design-bugsimprovements


Note

Low Risk
Purely presentational/layout and accessibility tweaks with no changes to business logic or data flows; primary risk is minor CSS/layout regressions in the offers list and retention-offer screen.

Overview
Improves retention-offer UI in both Admin and Portal.

In Admin (offers-index-retention.tsx), updates the offers table for better horizontal scrolling: makes the Name column sticky, sets a minimum table width/column sizing, and tweaks the filter button styling and accessibility (aria-label).

In Portal (account-plan-page.js), adjusts retention-offer spacing and markup so the price block only renders when applicable, and tightens button/footnote margins; bumps @tryghost/portal version to 2.65.2.

Written by Cursor Bugbot for commit e18bcd7. This will update automatically on new commits. Configure here.

The retention offer screen rendered an empty gh-portal-retention-offer-price
div when the discount type was free months, causing a large visual gap.
Moved the conditional to wrap the entire div so it's not rendered at all
for free month offers, and adjusted spacing accordingly.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 5, 2026

Walkthrough

Updated UI layout and rendering in the account plan and offers index screens. On the account plan page: header padding was added for non-full-size layouts; retention-offer vertical spacing and acceptance-button spacing were reduced; the inner price block is no longer rendered for free-month offers. In the offers index: the filter trigger was simplified to a labeled button; table layout switched to a minimum width with adjusted column widths; the first column and its header were made sticky with background/z-index fixes. apps/portal package version bumped; no exported APIs changed.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Design improvements for retention offer' directly describes the main changes: CSS/layout tweaks and refinements to the retention offer UI in both Admin and Portal components.
Description check ✅ Passed The description is clearly related to the changeset, providing a Linear issue reference, risk assessment, detailed overview of changes in both Admin and Portal, and version bump rationale.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch retention-offer-design-improvements-BER-3388

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ErisDS
Copy link
Copy Markdown
Member

ErisDS commented Mar 5, 2026

🤖 Velo CI Failure Analysis

Classification: 🟠 SOFT FAIL

  • Workflow: CI
  • Failed Step: Check app version bump
  • Run: View failed run
    What failed: Version bump not updated for the portal app
    Why: The logs indicate that the version of the portal app was changed, but the version was not bumped above the main branch version. This is a code issue that the author should fix by running 'yarn ship' in the apps/portal directory to update the package version.
    Action:
    The author should update the version of the portal app by running 'yarn ship' in the apps/portal directory and commit the changes.

return (
<tr key={offer.id} className={`group relative scale-100 border-b border-b-grey-200 dark:border-grey-800 ${archived ? 'opacity-60' : ''}`} data-testid="offer-item">
<td className='p-0'><a className='block cursor-pointer p-5 pl-0' onClick={() => handleOfferEdit(offer.id)}><span className='font-semibold'>{offer?.name}</span><br /><span className='text-sm text-grey-700'>{offerTier.name} {getOfferCadence(offer.cadence)}</span></a></td>
<td className='sticky left-0 z-10 bg-white p-0 dark:bg-black'><a className='block cursor-pointer p-5 pl-0' onClick={() => handleOfferEdit(offer.id)}><span className='font-semibold'>{offer?.name}</span><br /><span className='text-sm text-grey-700'>{offerTier.name} {getOfferCadence(offer.cadence)}</span></a></td>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sticky column background bleeds through on archived rows

Low Severity

The newly added sticky Name column (bg-white dark:bg-black) on the <td> won't fully mask scrolled-under content for archived offer rows, because the parent <tr> applies opacity-60. CSS opacity on a parent makes all descendant backgrounds semi-transparent, so the sticky column's opaque background becomes see-through when the row is archived. This defeats the purpose of the sticky column during horizontal scrolling.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/admin-x-settings/src/components/settings/growth/offers/offers-index-retention.tsx`:
- Line 90: The icon-only filter trigger Button (the Button with
label={<LucideIcon.ListFilter .../>} and unstyled={true}) needs an accessible
name; add an aria-label or aria-labelledby to the Button (for example
aria-label="Filter options" or similar descriptive text) so screen readers
announce it, or include visually-hidden text associated with the Button; ensure
the change is applied on the same Button component rendering the
LucideIcon.ListFilter.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f703dc42-123e-414c-affa-714ba4534d05

📥 Commits

Reviewing files that changed from the base of the PR and between 66b59f4 and 81175f8.

📒 Files selected for processing (1)
  • apps/admin-x-settings/src/components/settings/growth/offers/offers-index-retention.tsx

Changelog for v2.65.1 -> 2.65.2:
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/admin-x-settings/src/components/settings/growth/offers/offers-index-retention.tsx (1)

371-377: ⚠️ Potential issue | 🟠 Major

Replace click-only anchors with buttons for keyboard accessibility.

Lines 371–376 use <a> elements with onClick handlers but no href attribute. This pattern is not keyboard-accessible (missing focus management, Enter key support) and is semantically incorrect for in-app actions. Convert these to <button type="button"> elements instead:

  • Line 371: Offer name cell
  • Line 372: Discount amount cell
  • Line 373: Price cell
  • Line 376: Status cell

All four cells in the row should use buttons for consistency and accessibility compliance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/admin-x-settings/src/components/settings/growth/offers/offers-index-retention.tsx`
around lines 371 - 377, Replace the click-only anchor elements used for in-row
actions with semantic buttons: change the <a> tags that call
handleOfferEdit(offer.id) in the offer name cell, discount cell, price cell and
status cell to <button type="button"> so keyboard users can focus and activate
via Enter/Space; ensure the redemption count link still uses an anchor when it
has an href (keep createRedemptionFilterUrl(offer.id) for actual navigation) and
when it falls back to invoking handleOfferEdit(offer.id) use a button instead,
preserving existing className, onClick logic and conditional href behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@apps/admin-x-settings/src/components/settings/growth/offers/offers-index-retention.tsx`:
- Around line 371-377: Replace the click-only anchor elements used for in-row
actions with semantic buttons: change the <a> tags that call
handleOfferEdit(offer.id) in the offer name cell, discount cell, price cell and
status cell to <button type="button"> so keyboard users can focus and activate
via Enter/Space; ensure the redemption count link still uses an anchor when it
has an href (keep createRedemptionFilterUrl(offer.id) for actual navigation) and
when it falls back to invoking handleOfferEdit(offer.id) use a button instead,
preserving existing className, onClick logic and conditional href behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5840bce-6e08-46ce-a036-42a953543562

📥 Commits

Reviewing files that changed from the base of the PR and between 69b7670 and e18bcd7.

📒 Files selected for processing (1)
  • apps/admin-x-settings/src/components/settings/growth/offers/offers-index-retention.tsx

@minimaluminium minimaluminium enabled auto-merge (squash) March 5, 2026 07:53
@minimaluminium minimaluminium merged commit dd7f0db into main Mar 5, 2026
31 checks passed
@minimaluminium minimaluminium deleted the retention-offer-design-improvements-BER-3388 branch March 5, 2026 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants