Publish dialog
Picks where a landing page goes live, shows what it goes live with, and takes a live page offline.
import { PublishDialog } from "@/pages/library/PageSettings";
import "@/pages/library/library.css";PublishDialog is the short dialog behind the page builder's Publish button. It asks only where the page goes: a domain and an address. Confirming it is the approval, and the page goes live straight away. Everything else about the page lives in Page settings, and this dialog shows a summary of those settings so nothing is published blind.
The two dialogs are kept apart on purpose. Publishing is a decision people make often and quickly. Page settings change rarely and have many fields.
A draft page
The first publish. The address starts from the page's name: "Q4 demo request page" becomes q4-demo-request, through slugFor in src/mocks/pageBuilder.js. The full address is shown under the field as it is typed.
{publishing && (
<PublishDialog
page={page}
ownDomain="go.meridian.com"
onClose={() => setPublishing(false)}
onSettings={() => { setPublishing(false); setSettingsOpen(true); }}
onUnpublish={() => { unpublish(page.id); setPublishing(false); }}
onPublish={({ domain, slug }) => { publish(page.id, { domain, slug }); setPublishing(false); }}
/>
)}The address field cleans what is typed as it goes: lowercase letters, digits and single hyphens only, with no hyphen at the start (cleanSlug). A trailing hyphen is removed when the page is published.
A live page with changes
Once a page is live, later edits are held back until it is published again (page.unpublished). The title becomes "Publishing", the confirm label "Publish changes", and a "Take offline" group appears with an Unpublish button.
<PublishDialog page={{ ...page, status: "published", unpublished: true }} … />A live page with no changes
With nothing waiting, the only thing confirming can change is the address, so the confirm label is "Update address". The domain and address start from where the page is live now.
<PublishDialog page={{ ...page, status: "published", unpublished: false, settings: { domain: "go.meridian.com", slug: "q4-demo" } }} … />States
| Page | Title | Confirm label | Last group |
|---|---|---|---|
status: "draft" | Publish page | Publish page | A note: "The page goes live at this address as soon as you publish." |
status: "published", unpublished: true | Publishing | Publish changes | Take offline, with Unpublish |
status: "published", unpublished: false | Publishing | Update address | Take offline, with Unpublish |
If the address is cleared, the field shows "Give the page an address." and confirming does nothing.
What "Goes live with" shows
The summary reads the page's settings through metaOf(page), which fills in the defaults.
| Row | From | Default |
|---|---|---|
| Search title | meta.title, or the page name | The page name |
| Access | meta.access | "Anyone on the internet" |
| Search engines | meta.sitemap | "Can list this page" |
| Tracking pixel | meta.pixel | "On" |
"Change in page settings" calls onSettings. The page builder closes this dialog and opens Page settings.
Layout
| Part | Style |
|---|---|
| Panel | Dialog at md, 650px, with .lib-dialog--publish: the body scrolls past min(64vh, 620px). |
| Group | .lib-publish__group: a 12px uppercase heading (.lib-publish__heading, semibold, 0.05em tracking), 20px padding above and below, a --color-grey-100 line between groups. |
| Address preview | .lib-publish__url: 12px monospace with a 14px Globe icon. |
| Summary | .lib-publish__summary: a bordered list with 8px corners, 12px text, labels in --color-grey-500, values in medium weight. |
| Note | .lib-publish__note: 12px text on --color-grey-50, 8px corners, 10px by 12px padding. |
| Footer | Cancel and the confirm action at 32px, as in all library dialogs. |
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
page | page object | Required. Reads name, status, unpublished, settings ({ domain, slug }) and meta. | |
ownDomain | string | Required. The workspace's connected domain, offered as the second radio option. The page builder makes it from the brand: go.meridian.com. | |
onPublish | ({ domain, slug }) => void | Called on confirm when the address is not empty. Does not close the dialog. | |
onUnpublish | () => void | The Unpublish button on a live page. | |
onSettings | () => void | "Change in page settings". | |
onClose | () => void | Escape, scrim click, the close icon and Cancel. |
The domain options are pages.petavue.com (exported as PETAVUE_DOMAIN) and ownDomain.
Accessibility
- The wrapper has
role="dialog",aria-modal="true"andaria-label"Publish page" or "Publishing", matching the title. - The domain choice is a
RadioGroup, afieldsetwith a "Domain" legend, so arrow keys move between the two domains. - The address error is announced with
role="alert"and linked to the field. - Nothing is focused when the dialog opens, focus is not kept inside, and it is not returned to the Publish button on close.
Do and don't
- Do keep this dialog to where the page goes. Add new page options to Page settings, and a row to "Goes live with" if people should see it before publishing.
- Do say in the toast where the page went: "Published at go.meridian.com/q4-demo."
- Don't ask for confirmation again after this dialog. Confirming it is the approval.
- Don't hide Unpublish behind a menu. Taking a page offline should be as easy to find as publishing it.
When to use it
Use it for landing pages built in the page builder. Publishing a set of changes from a workflow or a recommendation is a different decision; use a Dialog from @/ui that lists the changes, as in Dialogs and confirmation.
Where it is used
| File | What |
|---|---|
src/pages/library/PageBuilderPage.jsx | Opened by Publish, Publish changes and Publishing in the editor header. After a publish it shows a toast and, for a page drafted for a recommendation, marks the recommendation accepted. |