Skip to content

Added Customize button to welcome emails behind labs flag#26770

Merged
cmraible merged 15 commits intomainfrom
NY-1142-welcome-email-customize-button
Mar 11, 2026
Merged

Added Customize button to welcome emails behind labs flag#26770
cmraible merged 15 commits intomainfrom
NY-1142-welcome-email-customize-button

Conversation

@cmraible
Copy link
Copy Markdown
Collaborator

@cmraible cmraible commented Mar 11, 2026

closes https://linear.app/ghost/issue/NY-1135/add-the-customize-button-and-an-empty-modal

Summary

  • Re-adds the Customize button to the Welcome emails settings section
  • Gated behind the welcomeEmailsDesignCustomization private feature flag (Labs → Developer experiments)
  • Button opens up a placeholder modal that we can expand on iteratively in future commits.

@cmraible cmraible requested a review from 9larsons as a code owner March 11, 2026 00:21
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 46d1193c-76f3-454f-97f7-904b9ed11d6b

📥 Commits

Reviewing files that changed from the base of the PR and between 75af217 and 07f2853.

📒 Files selected for processing (2)
  • apps/admin-x-settings/src/components/settings/membership/member-emails/welcome-email-customize-modal.tsx
  • e2e/tests/admin/settings/member-welcome-emails.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/admin-x-settings/src/components/settings/membership/member-emails/welcome-email-customize-modal.tsx
  • e2e/tests/admin/settings/member-welcome-emails.test.ts

Walkthrough

Adds a feature-flagged "Customize" button to the member welcome emails UI that appears when the welcomeEmailsDesignCustomization flag is enabled and opens a new WelcomeEmailCustomizeModal. Implements the WelcomeEmailCustomizeModal component and wires the button to open and close it. Updates e2e test helpers with locators for the customize button and modal, and adds end-to-end tests that verify the button's visibility based on the feature flag and that the modal can be opened and closed.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a Customize button to welcome emails that is controlled by a labs feature flag.
Description check ✅ Passed The description is directly related to the changeset, clearly explaining the purpose (re-adding a button), the gating mechanism (feature flag), and the intended use (placeholder modal for future expansion).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 NY-1142-welcome-email-customize-button

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.

@cmraible cmraible force-pushed the NY-1142-welcome-email-customize-button branch from 7ec1100 to 82d97c1 Compare March 11, 2026 00:23
@cmraible cmraible removed the request for review from 9larsons March 11, 2026 00:29
@cmraible cmraible force-pushed the NY-1142-welcome-email-customize-button branch from 4c66d91 to a8907e4 Compare March 11, 2026 00:38
Base automatically changed from NY-1142-welcome-email-design-updates to main March 11, 2026 09:36
peterzimon and others added 12 commits March 11, 2026 10:02
ref https://linear.app/ghost/issue/NY-1142

Matched the automated email rows to newsletter-style table hover behavior and fixed width/flex layout so title and description fill available space without changing functionality.
ref https://linear.app/ghost/issue/NY-1142

Updated Membership sidebar item and section heading to use Email wording for consistency with the new email settings structure.
ref https://linear.app/ghost/issue/NY-1142

Restored automated emails as a separate Membership section, reverted newsletters section ordering and naming, and aligned sidebar labels/navigation accordingly.
The rename to "Automated emails" was premature — keeping it as
"Welcome emails" for now
The button had no functionality — removing it until it's needed
Added data-testid to welcome email title for simpler test selectors,
simplified section order test using toEqual, and used toBeHidden for
clearer visibility assertions.
The button is gated behind the `welcomeEmailsDesignCustomization` private
feature flag and currently has no functionality wired up
Opens a simple modal when clicking the Customize button (behind
the welcomeEmailsDesignCustomization labs flag)
@cmraible cmraible force-pushed the NY-1142-welcome-email-customize-button branch from a8907e4 to 7dc7fe7 Compare March 11, 2026 17:04
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

🧹 Nitpick comments (3)
apps/admin-x-settings/src/components/settings/membership/member-emails/welcome-email-customize-modal.tsx (1)

2-2: Consider using shade design system instead of admin-x-design-system.

The coding guidelines indicate that admin-x-design-system is being phased out and new components should use the shade design system. If shade has an equivalent Modal component, consider migrating to it.

As per coding guidelines: "Use shade design system for new components in Admin UI. Avoid admin-x-design-system as it is being phased out."

🤖 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/membership/member-emails/welcome-email-customize-modal.tsx`
at line 2, The import currently pulls Modal from
'@tryghost/admin-x-design-system'; update the component to use the Shade design
system Modal by replacing the import of Modal with the equivalent from 'shade'
(or the correct Shade package name), update any prop names or usage inside
welcome-email-customize-modal (the Modal component and any props like onClose,
open, title, children) to match Shade's API, and run the component build/tests
to ensure the new Modal's props and styling are compatible and adjust markup
where prop names differ.
apps/admin-x-settings/src/components/settings/membership/member-emails.tsx (1)

7-7: Same design system consideration applies here.

The Button import from @tryghost/admin-x-design-system follows the same pattern flagged in the modal file. For consistency, if migrating to shade, both components should be updated together.

🤖 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/membership/member-emails.tsx`
at line 7, Update the Button import in member-emails.tsx to match the migration
to the new "shade" package: replace importing Button from
'@tryghost/admin-x-design-system' with the equivalent Button from the shade
package (while leaving Icon, Table, TableRow, Toggle, showToast,
withErrorBoundary imported from '@tryghost/admin-x-design-system'), and ensure
the paired component you changed in the modal file is updated to import Button
from the same shade package so both components come from the same source.
e2e/tests/admin/settings/member-welcome-emails.test.ts (1)

129-142: Consider splitting into separate tests for better isolation.

This test covers multiple scenarios: (1) customize button is visible, (2) clicking opens modal, and (3) close button dismisses modal. Per E2E guidelines, each test should cover one scenario for clearer failure diagnostics and test isolation.

As per coding guidelines: "One test should equal one scenario - never mix multiple scenarios in a single test."

♻️ Suggested test split
-    test('customize button opens modal when labs flag is enabled', async ({page}) => {
+    test('customize button is visible when labs flag is enabled', async ({page}) => {
         const welcomeEmailsSection = new MemberWelcomeEmailsSection(page);
-
         await welcomeEmailsSection.goto();
-
         await expect(welcomeEmailsSection.customizeButton).toBeVisible();
-        await welcomeEmailsSection.customizeButton.click();
-
-        await expect(welcomeEmailsSection.customizeModal).toBeVisible();
+    });
 
-        await welcomeEmailsSection.customizeModal.getByRole('button', {name: 'Close'}).click();
+    test('customize button opens modal', async ({page}) => {
+        const welcomeEmailsSection = new MemberWelcomeEmailsSection(page);
+        await welcomeEmailsSection.goto();
+        await welcomeEmailsSection.customizeButton.click();
+        await expect(welcomeEmailsSection.customizeModal).toBeVisible();
+    });
 
-        await expect(welcomeEmailsSection.customizeModal).toBeHidden();
+    test('customize modal can be closed', async ({page}) => {
+        const welcomeEmailsSection = new MemberWelcomeEmailsSection(page);
+        await welcomeEmailsSection.goto();
+        await welcomeEmailsSection.customizeButton.click();
+        await welcomeEmailsSection.customizeModal.getByRole('button', {name: 'Close'}).click();
+        await expect(welcomeEmailsSection.customizeModal).toBeHidden();
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/tests/admin/settings/member-welcome-emails.test.ts` around lines 129 -
142, Split the single multi-assert test into separate focused tests: (1) verify
the customize button is visible by asserting
MemberWelcomeEmailsSection.customizeButton isVisible(), (2) verify clicking
MemberWelcomeEmailsSection.customizeButton opens the modal by clicking it and
asserting MemberWelcomeEmailsSection.customizeModal isVisible(), and (3) verify
the modal can be dismissed by clicking the Close button inside
MemberWelcomeEmailsSection.customizeModal and asserting it becomes hidden; keep
navigation via MemberWelcomeEmailsSection.goto() in each test for isolation and
give each test a descriptive name like "shows customize button", "opens
customize modal on click", and "closes customize modal on close button click".
🤖 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/membership/member-emails/welcome-email-customize-modal.tsx`:
- Around line 14-19: The modal currently shows okLabel='Save' while onOk only
calls modal.remove(), which misleads users; change the okLabel to a neutral
label like 'OK' or 'Close' (e.g., okLabel='OK' or okLabel='Close') or implement
a real save handler in the component so that the label matches behavior—update
the JSX where okLabel and onOk are set (okLabel and onOk props and the
modal.remove call) to keep label and action consistent.

---

Nitpick comments:
In `@apps/admin-x-settings/src/components/settings/membership/member-emails.tsx`:
- Line 7: Update the Button import in member-emails.tsx to match the migration
to the new "shade" package: replace importing Button from
'@tryghost/admin-x-design-system' with the equivalent Button from the shade
package (while leaving Icon, Table, TableRow, Toggle, showToast,
withErrorBoundary imported from '@tryghost/admin-x-design-system'), and ensure
the paired component you changed in the modal file is updated to import Button
from the same shade package so both components come from the same source.

In
`@apps/admin-x-settings/src/components/settings/membership/member-emails/welcome-email-customize-modal.tsx`:
- Line 2: The import currently pulls Modal from
'@tryghost/admin-x-design-system'; update the component to use the Shade design
system Modal by replacing the import of Modal with the equivalent from 'shade'
(or the correct Shade package name), update any prop names or usage inside
welcome-email-customize-modal (the Modal component and any props like onClose,
open, title, children) to match Shade's API, and run the component build/tests
to ensure the new Modal's props and styling are compatible and adjust markup
where prop names differ.

In `@e2e/tests/admin/settings/member-welcome-emails.test.ts`:
- Around line 129-142: Split the single multi-assert test into separate focused
tests: (1) verify the customize button is visible by asserting
MemberWelcomeEmailsSection.customizeButton isVisible(), (2) verify clicking
MemberWelcomeEmailsSection.customizeButton opens the modal by clicking it and
asserting MemberWelcomeEmailsSection.customizeModal isVisible(), and (3) verify
the modal can be dismissed by clicking the Close button inside
MemberWelcomeEmailsSection.customizeModal and asserting it becomes hidden; keep
navigation via MemberWelcomeEmailsSection.goto() in each test for isolation and
give each test a descriptive name like "shows customize button", "opens
customize modal on click", and "closes customize modal on close button click".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 577d5637-b6c9-4b65-80b2-90a579912f84

📥 Commits

Reviewing files that changed from the base of the PR and between 1b158dd and 7dc7fe7.

📒 Files selected for processing (4)
  • apps/admin-x-settings/src/components/settings/membership/member-emails.tsx
  • apps/admin-x-settings/src/components/settings/membership/member-emails/welcome-email-customize-modal.tsx
  • e2e/helpers/pages/admin/settings/sections/member-welcome-emails-section.ts
  • e2e/tests/admin/settings/member-welcome-emails.test.ts

Replaced legacy admin-x-design-system Modal with Shade Dialog component
to align with the design system migration direction
@@ -0,0 +1,23 @@
import NiceModal, {useModal} from '@ebay/nice-modal-react';
import {Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle} from '@tryghost/shade';
Copy link
Copy Markdown
Collaborator Author

@cmraible cmraible Mar 11, 2026

Choose a reason for hiding this comment

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

I'm not sure exactly how this will workout, but I think our Plan A should be to build the new reusable design customization modal based on shade, to avoid further dependence on admin-x-design-system.

test.describe('Ghost Admin - Welcome Email Customize Button', () => {
test.use({labs: {welcomeEmailsDesignCustomization: true}});

test('customize button opens modal when labs flag is enabled', async ({page}) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe a second test to make sure it doesn't show when disabled? so we'd have two tests (however you want to nest them and set them up):

test.describe('Ghost Admin - Welcome Email Customize Button - flag enabled', () => {
    test.use({labs: {welcomeEmailsDesignCustomization: true}});

    test('customize button opens modal when labs flag is enabled', async ({page}) => {
        const welcomeEmailsSection = new MemberWelcomeEmailsSection(page);

        await welcomeEmailsSection.goto();

        await expect(welcomeEmailsSection.customizeButton).toBeVisible();
        await welcomeEmailsSection.customizeButton.click();

        await expect(welcomeEmailsSection.customizeModal).toBeVisible();

        await welcomeEmailsSection.customizeModal.getByRole('button', {name: 'Close'}).click();

        await expect(welcomeEmailsSection.customizeModal).toBeHidden();
    });
});

test.describe('Ghost Admin - Welcome Email Customize Button - flag disabled', () => {
    test('customize button is hidden when labs flag is disabled', async ({page}) => {
        const welcomeEmailsSection = new MemberWelcomeEmailsSection(page);

        await welcomeEmailsSection.goto();

        await expect(welcomeEmailsSection.customizeButton).toBeHidden();
    });
});

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Ah - good call!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added the flag disabled test and setting this PR to automerge

Copy link
Copy Markdown
Contributor

@troyciesco troyciesco left a comment

Choose a reason for hiding this comment

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

lgtm, though i think we should add the extra test to make sure it doesn't show so we don't mistakenly move it or something

@cmraible cmraible enabled auto-merge (squash) March 11, 2026 21:51
@cmraible cmraible merged commit 2f8d5cf into main Mar 11, 2026
28 checks passed
@cmraible cmraible deleted the NY-1142-welcome-email-customize-button branch March 11, 2026 22:18
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.

3 participants