Phi
Page Header
@dicehub/phiv1.0.0-beta.1

Page Header

A composite component that combines breadcrumbs and tabs for page navigation.

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import { Button } from "@dicehub/phi/components/button";
import { PhCode, PhGlobe, PhHouse } from "@phosphor-icons/vue";
import PageHeader from "./components/phi/page-header/PageHeader.vue";

const tabs = [
  { label: "Overview", value: "overview" },
  { label: "Metrics", value: "metrics" },
  { label: "Deployments", value: "deployments" },
  { label: "Bindings", value: "bindings" },
  { label: "Observability", value: "observability" },
  { label: "Settings", value: "settings" },
];
</script>

<template>
  <PageHeader
    :tabs="tabs"
    default-tab="overview"
    @value-change="(value) => console.log(value)"
  >
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link :icon="PhHouse" href="#">
          Workers & Pages
        </Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>cloudflare-dev-platform</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>

    <Button :icon="PhCode">Edit code</Button>
    <Button :icon="PhGlobe" variant="primary">Visit</Button>
  </PageHeader>
</template>

Installation

PageHeader is a source block: the Phi CLI copies its source into your app so you own and can customize the code.

pnpm dlx @dicehub/phi@beta add PageHeader

The command writes the block into the blocksDir from your phi.json, for examplesrc/components/phi/page-header/PageHeader.vue. Import it from there:

import PageHeader from "./components/phi/page-header/PageHeader.vue";

Run pnpm dlx @dicehub/phi@beta init once before the first block. See the CLI reference for every command.

Usage

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import { PhHouse } from "@phosphor-icons/vue";
import PageHeader from "./components/phi/page-header/PageHeader.vue";

const tabs = [
  { label: "Overview", value: "overview" },
  { label: "Settings", value: "settings" },
];

function handleValueChange(value: string) {
  console.log(value);
}
</script>

<template>
  <PageHeader
    :tabs="tabs"
    default-tab="overview"
    @value-change="handleValueChange"
  >
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link :icon="PhHouse" href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Link href="#">Projects</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>My Project</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>
  </PageHeader>
</template>

Examples

Basic

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import PageHeader from "./components/phi/page-header/PageHeader.vue";
</script>

<template>
  <PageHeader>
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>Dashboard</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>
  </PageHeader>
</template>

With Icons

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import { PhGear, PhHouse } from "@phosphor-icons/vue";
import PageHeader from "./components/phi/page-header/PageHeader.vue";
</script>

<template>
  <PageHeader>
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link :icon="PhHouse" href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current :icon="PhGear">Settings</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>
  </PageHeader>
</template>

With Tabs

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import PageHeader from "./components/phi/page-header/PageHeader.vue";

const tabs = [
  { label: "General", value: "general" },
  { label: "Security", value: "security" },
  { label: "Notifications", value: "notifications" },
];
</script>

<template>
  <PageHeader :tabs="tabs" default-tab="general">
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>Settings</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>
  </PageHeader>
</template>

With Actions

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import { Button } from "@dicehub/phi/components/button";
import PageHeader from "./components/phi/page-header/PageHeader.vue";

const tabs = [
  { label: "Overview", value: "overview" },
  { label: "Settings", value: "settings" },
];
</script>

<template>
  <PageHeader :tabs="tabs" default-tab="overview">
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Link href="#">Projects</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>My Project</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>

    <Button variant="primary">Deploy</Button>
  </PageHeader>
</template>

With Title

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import PageHeader from "./components/phi/page-header/PageHeader.vue";
</script>

<template>
  <PageHeader title="Page title">
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Link href="#">Products</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>Page title</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>
  </PageHeader>
</template>

With Title and Description

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import PageHeader from "./components/phi/page-header/PageHeader.vue";
</script>

<template>
  <PageHeader
    title="Page title"
    description="Action-led, value-oriented description of what this page does. Optional second sentence with use cases or prerequisites."
  >
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Link href="#">Products</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>Page title</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>
  </PageHeader>
</template>

Complete Example

Combining breadcrumbs, title, description, tabs, and actions.

<script setup lang="ts">
import { Breadcrumbs } from "@dicehub/phi/components/breadcrumbs";
import { Button } from "@dicehub/phi/components/button";
import { PhPlus } from "@phosphor-icons/vue";
import PageHeader from "./components/phi/page-header/PageHeader.vue";

const tabs = [
  { label: "Overview", value: "overview" },
  { label: "Analytics", value: "analytics" },
  { label: "Settings", value: "settings" },
];
</script>

<template>
  <PageHeader
    title="Page title"
    description="Action-led, value-oriented description of what this page does."
    :tabs="tabs"
    default-tab="overview"
  >
    <template #breadcrumbs>
      <Breadcrumbs>
        <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Link href="#">Products</Breadcrumbs.Link>
        <Breadcrumbs.Separator />
        <Breadcrumbs.Current>Page title</Breadcrumbs.Current>
      </Breadcrumbs>
    </template>

    <Button variant="outline">Export</Button>
    <Button :icon="PhPlus" variant="primary">New Item</Button>
  </PageHeader>
</template>

API Reference

PropTypeDefaultDescription
spacing"compact" | "base" | "relaxed""base"Vertical gap between the breadcrumbs, heading, and tab row.
breadcrumbsslot-Breadcrumb trail rendered above the title.
titlestring-Page title. Omit to hide the heading block.
descriptionstring-Supporting sentence below the title.
tabsTabsItem[]-Page sections rendered as a tab row.
defaultTabstring-Value of the tab selected on first render.
valueChange(value: string) => void-Emitted when the selected tab changes.
default slotslot-Actions rendered at the end of the tab row. Rendered only when tabs are set.
classstring-Forwarded to the root element.

TabsItem

PropertyType
labelstring
valuestring