diff --git a/cypress/integration/sitemap-vrt/constants.ts b/cypress/integration/sitemap-vrt/constants.ts
index eecffb97f6..983c65f97b 100644
--- a/cypress/integration/sitemap-vrt/constants.ts
+++ b/cypress/integration/sitemap-vrt/constants.ts
@@ -136,6 +136,9 @@ export const SITEMAP = [
"/components/meter",
"/components/meter/api",
"/components/meter/changelog",
+ "/components/page-header",
+ "/components/page-header/api",
+ "/components/page-header/changelog",
"/components/pagination/",
"/components/pagination/api",
"/components/pagination/changelog",
diff --git a/packages/paste-core/components/page-header/CHANGELOG.md b/packages/paste-core/components/page-header/CHANGELOG.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/paste-website/package.json b/packages/paste-website/package.json
index 9e637bfd89..d6cd5a4818 100644
--- a/packages/paste-website/package.json
+++ b/packages/paste-website/package.json
@@ -91,6 +91,7 @@
"@twilio-paste/modal": "^16.1.1",
"@twilio-paste/modal-dialog-primitive": "^2.0.1",
"@twilio-paste/non-modal-dialog-primitive": "^2.0.2",
+ "@twilio-paste/page-header": "^0.0.0",
"@twilio-paste/pagination": "^7.1.1",
"@twilio-paste/paragraph": "^10.1.1",
"@twilio-paste/popover": "^13.2.0",
diff --git a/packages/paste-website/src/assets/images/PageHeaderPNG.png b/packages/paste-website/src/assets/images/PageHeaderPNG.png
new file mode 100644
index 0000000000..df7b1dce64
Binary files /dev/null and b/packages/paste-website/src/assets/images/PageHeaderPNG.png differ
diff --git a/packages/paste-website/src/component-examples/PageHeaderExamples.ts b/packages/paste-website/src/component-examples/PageHeaderExamples.ts
new file mode 100644
index 0000000000..53570a804a
--- /dev/null
+++ b/packages/paste-website/src/component-examples/PageHeaderExamples.ts
@@ -0,0 +1,214 @@
+export const defaultPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+
+ Manage billing
+
+
+
+
+
+
+ Beta
+
+
+ Subscriptions
+
+
+
+
+
+ Manage your subscriptions here. Costs listed here may exclude taxes, fees, support fees, expert services costs, and certain other products.
+
+
+
+
+ Subscriptions
+
+ Recurring items
+
+
+
+ );
+};
+render(
+
+)
+`.trim();
+
+export const interruptedPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+ Return to Flex
+
+
+ Getting started with Segment
+ Download the help guide PDF
+
+
+ );
+};
+render(
+
+)
+`.trim();
+
+export const compactPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+
+
+ Parker Smith
+
+
+
+
+
+
+
+ Customer since June 11, 2009
+
+ Online
+
+
+
+
+
+
+ Customer details
+
+ Customer history
+
+
+
+
+ );
+};
+render(
+
+)
+`.trim();
+
+export const objectDetailsPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+
+ Voice
+ Calls
+
+
+
+ Call details
+
+
+
+
+
+
+
+ Overview
+
+ Insights summary
+
+
+
+ );
+};
+render(
+
+)
+`.trim();
+
+export const objectsListPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+
+ Phone numbers
+ Manage
+
+
+
+ Verified caller IDs
+
+
+
+ Use numbers you own as caller ID or the "To" number for outbound calls and messages. Phone numbers you buy from Twilio or port to Twilio can always be used as caller IDs.
+
+
+ );
+};
+render(
+
+)
+`.trim();
+
+export const settingsPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+
+ Phone numbers
+ Manage
+
+
+
+ Billing settings
+ Use numbers you own as caller ID or the "To" number for outbound calls and messages. Phone numbers you buy from Twilio or port to Twilio can always be used as caller IDs.
+
+
+
+
+ Invoicing
+
+ Service address
+ Tax information
+
+
+
+ );
+};
+render(
+
+)
+`.trim();
+
+export const wizardPageHeaderExample = `
+const PageHeaderExample = () => {
+ return (
+
+
+
+ Breadcrumb
+ Breadcrumb
+
+
+ Select warehouse type
+
+ Connect warehouse
+
+ Set sync schedule
+
+
+
+ Add warehouse
+ Connect Azure SQL data warehouse
+ Follow the steps below to start setting up Azure SQL data warehouse.
+
+
+ );
+};
+render(
+
+)
+`.trim();
diff --git a/packages/paste-website/src/components/homepage/HomeHero.tsx b/packages/paste-website/src/components/homepage/HomeHero.tsx
index 0cd75fe005..340b94cba8 100644
--- a/packages/paste-website/src/components/homepage/HomeHero.tsx
+++ b/packages/paste-website/src/components/homepage/HomeHero.tsx
@@ -77,14 +77,14 @@ const HomeHero = (): JSX.Element => {
New
- Introducing page templates!
+ The Page Header component is here!
event({
category: "Hero",
action: "click-new-banner",
- label: "Page templates announcement",
+ label: "Page header announcement",
})
}
>
diff --git a/packages/paste-website/src/pages/components/page-header/api.mdx b/packages/paste-website/src/pages/components/page-header/api.mdx
new file mode 100644
index 0000000000..cc70df3e0a
--- /dev/null
+++ b/packages/paste-website/src/pages/components/page-header/api.mdx
@@ -0,0 +1,105 @@
+export const meta = {
+ title: 'Page Header',
+ package: '@twilio-paste/page-header',
+ description: 'Page Header is a layout component that wraps all top-level components on a page.',
+ slug: '/components/page-header/api',
+};
+
+import Changelog from '@twilio-paste/page-header/CHANGELOG.md'; // I don't know why this is needed but if you remove it the page fails to render
+import packageJson from '@twilio-paste/page-header/package.json';
+
+import {SidebarCategoryRoutes} from '../../../constants';
+import ComponentPageLayout from '../../../layouts/ComponentPageLayout';
+import {getFeature, getNavigationData, getComponentApi} from '../../../utils/api';
+
+export default ComponentPageLayout;
+
+export const getStaticProps = async () => {
+ const navigationData = await getNavigationData();
+ const feature = await getFeature('Page header');
+ const {componentApi, componentApiTocData} = getComponentApi('@twilio-paste/page-header');
+ return {
+ props: {
+ data: {
+ ...packageJson,
+ ...feature,
+ },
+ componentApi,
+ mdxHeadings: [...mdxHeadings, ...componentApiTocData],
+ navigationData,
+ pageHeaderData: {
+ categoryRoute: SidebarCategoryRoutes.COMPONENTS,
+ githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/page-header',
+ storybookUrl: '/?path=/story/components-page-header--default',
+ },
+ },
+ };
+};
+
+## Installation
+
+```bash
+yarn add @twilio-paste/page-header - or - yarn add @twilio-paste/core
+```
+
+## Usage
+
+```jsx
+import {
+ PageHeader,
+ PageHeaderActions,
+ PageHeaderDetails,
+ PageHeaderHeading,
+ PageHeaderInPageNavigation,
+ PageHeaderKeyword,
+ PageHeaderMeta,
+ PageHeaderParagraph,
+ PageHeaderPrefix,
+ PageHeaderSetting,
+} from '@twilio-paste/core/page-header';
+
+const MyPageHeader = () => {
+ return (
+
+
+
+ Breadcrumb
+ Breadcrumb
+
+
+
+ Wizard title
+
+
+
+ Page title
+
+
+
+
+
+
+
+
+ Badge
+
+ Meta
+ Meta
+
+ Paragraph text
+
+
+
+
+ Label
+
+ Label
+ Label
+
+
+
+ );
+};
+```
+## Props
+
\ No newline at end of file
diff --git a/packages/paste-website/src/pages/components/page-header/changelog.mdx b/packages/paste-website/src/pages/components/page-header/changelog.mdx
new file mode 100644
index 0000000000..bb54860b6d
--- /dev/null
+++ b/packages/paste-website/src/pages/components/page-header/changelog.mdx
@@ -0,0 +1,37 @@
+export const meta = {
+ title: 'Page Header',
+ package: '@twilio-paste/page-header',
+ description: 'Page Header is a layout component that wraps all top-level components on a page.',
+ slug: '/components/page-header/changelog',
+};
+
+import Changelog from '@twilio-paste/page-header/CHANGELOG.md';
+import packageJson from '@twilio-paste/page-header/package.json';
+
+import {SidebarCategoryRoutes} from '../../../constants';
+import ComponentPageLayout from '../../../layouts/ComponentPageLayout';
+import {getFeature, getNavigationData} from '../../../utils/api';
+
+export default ComponentPageLayout;
+
+export const getStaticProps = async () => {
+ const navigationData = await getNavigationData();
+ const feature = await getFeature('Page header');
+ return {
+ props: {
+ data: {
+ ...packageJson,
+ ...feature,
+ },
+ navigationData,
+ mdxHeadings,
+ pageHeaderData: {
+ categoryRoute: SidebarCategoryRoutes.COMPONENTS,
+ githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/page-header',
+ storybookUrl: '/?path=/story/components-page-header--default',
+ },
+ },
+ };
+};
+
+
\ No newline at end of file
diff --git a/packages/paste-website/src/pages/components/page-header/index.mdx b/packages/paste-website/src/pages/components/page-header/index.mdx
new file mode 100644
index 0000000000..cfdaaa261c
--- /dev/null
+++ b/packages/paste-website/src/pages/components/page-header/index.mdx
@@ -0,0 +1,238 @@
+export const meta = {
+ title: 'Page Header',
+ package: '@twilio-paste/page-header',
+ description: 'Page Header is a layout component that wraps all top-level components on a page.',
+ slug: '/components/page-header/',
+};
+
+import {Anchor} from '@twilio-paste/anchor';
+import { Avatar } from "@twilio-paste/avatar";
+import {Box} from '@twilio-paste/box';
+import {Text} from '@twilio-paste/text';
+import { UserIcon } from "@twilio-paste/icons/esm/UserIcon";
+import {Callout, CalloutHeading, CalloutText} from '@twilio-paste/callout';
+import { MoreIcon } from "@twilio-paste/icons/esm/MoreIcon";
+import { NewIcon } from "@twilio-paste/icons/esm/NewIcon";
+import { Breadcrumb, BreadcrumbItem } from "@twilio-paste/breadcrumb";
+import { InPageNavigation, InPageNavigationItem } from "@twilio-paste/in-page-navigation";
+import { StatusBadge } from "@twilio-paste/status";
+import { Badge } from "@twilio-paste/badge";
+import { ArrowForwardIcon } from "@twilio-paste/icons/esm/ArrowForwardIcon";
+import {
+ PageHeader,
+ PageHeaderActions,
+ PageHeaderDetails,
+ PageHeaderHeading,
+ PageHeaderInPageNavigation,
+ PageHeaderKeyword,
+ PageHeaderMeta,
+ PageHeaderParagraph,
+ PageHeaderPrefix,
+ PageHeaderSetting
+} from '@twilio-paste/page-header';
+import {
+ ProgressStepComplete,
+ ProgressStepCurrent,
+ ProgressStepIncomplete,
+ ProgressStepSeparator,
+ ProgressSteps,
+} from "@twilio-paste/progress-steps";
+import {ArrowBackIcon} from '@twilio-paste/icons/esm/ArrowBackIcon';
+import { Button } from "@twilio-paste/button";
+import { ButtonGroup } from "@twilio-paste/button-group";
+import Changelog from '@twilio-paste/page-header/CHANGELOG.md';
+import {Codeblock} from '../../../components/codeblock';
+import {ResponsiveImage} from '../../../components/ResponsiveImage';
+import {SidebarCategoryRoutes} from '../../../constants';
+import {Blockquote} from '../../../components/Blockquote';
+import {DoDont, Do, Dont} from '../../../components/DoDont';
+import PageHeaderPNG from '../../../assets/images/PageHeaderPNG.png';
+import packageJson from '@twilio-paste/page-header/package.json';
+import ComponentPageLayout from '../../../layouts/ComponentPageLayout';
+import {getFeature, getNavigationData} from '../../../utils/api';
+import {defaultPageHeaderExample, interruptedPageHeaderExample, compactPageHeaderExample, objectDetailsPageHeaderExample, objectsListPageHeaderExample, settingsPageHeaderExample, wizardPageHeaderExample} from '../../../component-examples/PageHeaderExamples'
+
+export default ComponentPageLayout;
+
+export const getStaticProps = async () => {
+ const navigationData = await getNavigationData();
+ const feature = await getFeature('Page header');
+ return {
+ props: {
+ data: {
+ ...packageJson,
+ ...feature,
+ },
+ navigationData,
+ mdxHeadings,
+ pageHeaderData: {
+ categoryRoute: SidebarCategoryRoutes.COMPONENTS,
+ githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/page-header',
+ storybookUrl: '/?path=/story/components-page-header--default',
+ },
+ },
+ };
+};
+
+
+ {defaultPageHeaderExample}
+
+
+## Guidelines
+
+Page Header controls the spacing and layout for any potential components used above the main content of the page. Components that may be a part of the Page Header include [Breadcrumb](/components/breadcrumb), [Progress Steps](/components/progress-steps), [Heading](/components/heading), and [Button Group](/components/button-group), among others.
+
+There are 3 sections that make up the Page Header component, though you won’t always use all 3 at the same time.
+
+1. **PageHeaderSetting** contains any components that relate to the positioning of the current page in relation to parent or sibling pages, including navigating between those pages. Context components may include:
+ - [Breadcrumb](/components/breadcrumb)
+ - [Anchor](/components/anchor) (e.g. “<-- Back to parent page” link)
+ - [Progress Steps](/components/progress-steps)
+2. **PageHeaderDetails** is where all page-related information belongs. It includes static text and interactive components that relate to the page as a whole. Components that might live within the PageHeaderDetails include:
+ - [Detail Text](/components/detail-text) (e.g. the title of the entire wizard flow)
+ - [Heading](/components/heading) (e.g. the page title)
+ - [Badge](/components/badge) (e.g. “enabled”, “beta”, etc.)
+ - [Paragraph](/components/paragraph) (e.g. additional text below the title)
+ - [Button](/components/button) and [Button Group](/components/button-group) (e.g. “create”, “edit”, “cancel”, etc. buttons)
+ - [Anchor](/components/anchor) (e.g. link to a related/useful page such as docs - not a parent page)
+ - [Select](/components/select)
+3. **PageHeaderInPageNavigation** contains the [In Page Navigation](/components/in-page-navigation) for the page content, if using.
+
+Here’s what the component layout looks like with all its bits and pieces:
+
+
+
+
+
+ Using Alerts with Page Headers
+ There are times when you’ll need to display an Alert at the top of a page to communicate an important message to the user. Alerts should not be children of the Page Header component. If the Alert communicates a platform-level message, place it above the Page Header. If the Alert communicates a page-level message, place it below the Page Header.
+
+
+Much of the Paste Page Header component was inspired by the wonderful work of Github’s Primer Design system and [their own Page Header](https://primer.style/components/page-header) API and documentation.
+
+### Accessibility
+
+Page Header has no inherent accessibility concerns. However, there will likely need to manage accessibility concerns based on the components used within Page Header. Recommended considerations include:
+- The accessibility considerations of the components used. See the component’s documentation.
+- How the order and visual or content hierarchy of the children passed to Page Header affect readability.
+- What you pass to the `as` property when using [Headings](/components/heading). Headings that live at the top of the page and are the title of the page (most Page Headers fall under this category) should be `h1`s. Only use a heading level lower than `h1` if the Page Header exists within a page that already has an `h1` title (very few Page Headers fall under this category).
+
+
+## Examples
+
+### Default Page Header
+
+The Page Header can be composed to fit the needs of your page. Only include necessary components.
+
+Default Page Headers should have `space-130` clearspace above them. Place platform-level Alerts above this clearspace.
+
+
+ {defaultPageHeaderExample}
+
+
+### Page Header in an interrupted flow
+
+When the user navigates to an unrelated page, such as a separate product’s marketing page, it might not make sense to use a Breadcrumb in the page header for navigation. Instead, use an anchor with the text “<-- Return to [previous page name]”.
+
+
+ {interruptedPageHeaderExample}
+
+
+### Compact Page Header
+
+Use the compact size of Page Header for narrow containers, such as a [Chat Log](/components/chat-log) within a [Minimizable Dialog](/components/minimizable-dialog) or a custom dialog. If the Page Header only applies to a small portion of the page, you may pass a non-`h1` value to the `as` property.
+
+Compact Page Headers should have at least `space-50` clearspace above them. Be sure to use size small Buttons for Page Header Actions.
+
+
+ {compactPageHeaderExample}
+
+
+### Page Header on an object details page
+
+See the [object details page template](/page-templates/object-details) documentation for more guidance.
+
+
+ {objectDetailsPageHeaderExample}
+
+
+### Page Header on an objects list page
+
+See the [objects list page template](/page-templates/objects-list) documentation for more guidance.
+
+
+ {objectsListPageHeaderExample}
+
+
+### Page Header on a settings page
+
+See the [settings page template](/page-templates/settings) documentation for more guidance.
+
+
+ {settingsPageHeaderExample}
+
+
+### Page Header on a wizard page
+
+Use the [Progress Steps](/components/progress-steps) in the context wrapper when included as part of the [wizard page template](/page-templates/wizard).
+
+
+ {wizardPageHeaderExample}
+
+
+## Composition notes
+
+When deciding which components to include in your Page Header, only use what is absolutely necessary. Most Page Headers will include a minimum of Breadcrumb and a Heading, with additional components when needed.
+
+### PageHeaderSetting
+
+The most common navigation component that will be used is [Breadcrumb](/components/breadcrumb). In some cases, such as when the user navigates to an unrelated page (e.g., marketing for another product), Breadcrumbs might not make the most sense because the new page isn’t hierarchically related to the previous page. In cases when Breadcrumb isn’t the best option, use an Anchor with the ArrowBackIcon (for example “<-- Return to [previous page name]”).
+
+### PageHeaderDetails
+
+Again, we encourage you to be conservative here when deciding which components to include. Page Headers can feel overwhelming when crowded, so only use what is necessary.
+
+#### Above and before the heading
+
+When using PageHeaderKeyword above the Heading:
+- Detail Text should appear above the Heading only on [Wizard pages](/page-templates/wizard#content-structure). Use it to describe the overall goal the customer is trying to achieve.
+- Badges should only be used to describe the release stage of the feature on the page, like “Beta” or “Experimental”. [Status Badges](/components/status-badge) or other badges that have dynamic content should be placed in the PageHeaderMeta.
+
+When using PageHeaderPrefix (visual that appears before the Heading):
+- If you’re using the default size of Page Header, set the height of the Prefix element to `size-icon-90` or `size-square-110` to match the line height of the Heading.
+- If you’re using the compact size, set the height of the Prefix element to `size-icon-100` or `size-square-140` as the closest match to the line heights of the Heading and Meta combined. If you have no Meta content, use `size-icon-60` or `size-square-80`.
+
+#### The heading
+
+Follow the [composition guidelines on the Heading component](/components/heading#composition-notes).
+
+#### After and below the heading
+
+PageHeaderActions lives on the right side of the Page Header and is vertically aligned with the heading. When deciding whether to include actions in your Page Header, consider the importance of the action in relation to the entire content of the page.
+
+Use no more than 2 text Buttons in the actions. If you need to include additional actions, use a [Menu Button](/components/menu) with the `MoreIcon`. A primary Button in the header should only be used for [Create actions](/patterns/create).
+
+PageHeaderMeta can include:
+- Short details about the feature or object on the page, like a version number. If you find yourself explaining the page, or if the text gets lengthy, use PageHeaderParagraph underneath the Meta instead.
+- A documentation link
+- [Badges](/components/badge), [Status Badges](/components/status-badge), or [Display Pills](/components/display-pill-group)
+- Other inline elements
+
+Generally, the PageHeaderMeta will have content that dynamically changes (like status) or text content that is fairly consistent between related pages (like a documentation link or the name of the source that a destination is receiving data from).
+
+PageHeaderParagraph explains what the page is for or how to use it.
+
+### When to use Page Header
+
+
+
+
+
diff --git a/yarn.lock b/yarn.lock
index c95f585717..5f53cd7089 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -15679,6 +15679,7 @@ __metadata:
"@twilio-paste/modal": ^16.1.1
"@twilio-paste/modal-dialog-primitive": ^2.0.1
"@twilio-paste/non-modal-dialog-primitive": ^2.0.2
+ "@twilio-paste/page-header": ^0.0.0
"@twilio-paste/pagination": ^7.1.1
"@twilio-paste/paragraph": ^10.1.1
"@twilio-paste/popover": ^13.2.0