Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions homedocs/src/data/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,12 @@ export const navigation = [
llms: "small",
description: "Inject content into layout placeholders",
},
{
title: "DocumentTitle",
slug: "document-title",
llms: "small",
description: "Set the browser tab title from the widget tree",
},
],
},
{
Expand Down
27 changes: 27 additions & 0 deletions homedocs/src/examples/layout/DocumentTitleExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { createModel } from "cx/data";
import { DocumentTitle, TextField } from "cx/widgets";
import { bind, LabelsLeftLayout } from "cx/ui";

// @model
interface PageModel {
pageTitle: string;
}

const m = createModel<PageModel>();
// @model-end

// @index
export default (
<LabelsLeftLayout>
<DocumentTitle value={bind(m.pageTitle, "CxJS Documentation")} action="replace" />
<TextField
value={bind(m.pageTitle, "CxJS Documentation")}
label="Tab title:"
placeholder="Type something..."
/>
<p className="text-sm text-gray-500">
Look at your browser tab — its title updates as you type.
</p>
</LabelsLeftLayout>
);
// @index-end
46 changes: 46 additions & 0 deletions homedocs/src/pages/docs/layout/document-title.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
layout: ../../../layouts/DocsLayout.astro
title: DocumentTitle
description: Set the browser document (tab) title from the widget tree
---

import ImportPath from "../../../components/ImportPath.astro";
import CodeExample from "../../../components/CodeExample.astro";

import DocumentTitleExample from "../../../examples/layout/DocumentTitleExample.tsx";
import DocumentTitleExampleCode from "../../../examples/layout/DocumentTitleExample.tsx?raw";

# DocumentTitle

<ImportPath path="import { DocumentTitle } from 'cx/widgets';" />

`DocumentTitle` is a non-visual widget that sets `document.title` (the text shown in the browser tab). It renders nothing, so it can be placed anywhere in the widget tree. Because the title is data-bound, it updates automatically whenever the bound value changes — making it easy to reflect the current route, selected record, or unsaved-changes state in the tab.

<CodeExample code={DocumentTitleExampleCode}>
<DocumentTitleExample client:load />
</CodeExample>

## Combining titles

Multiple `DocumentTitle` widgets compose into a single title. The first instance encountered in the tree becomes the one that actually writes to `document.title`, while every instance contributes its `text` according to its `action` (`append`, `prepend`, or `replace`).

This is convenient for app shells: place a base `DocumentTitle` at the application root and add per-page `DocumentTitle` widgets that prepend the page name.

```tsx
// Application root — establishes the base title
<DocumentTitle value="My App" action="replace" />;

// A page deeper in the tree — prepends its name with a separator
<DocumentTitle value="Dashboard" action="prepend" separator=" – " />;
// Result: "Dashboard – My App"
```

## Configuration

| Property | Type | Description |
| ----------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `value` | `string` | Text value to use for the document title. Supports data binding. |
| `text` | `string` | Alias for `value`. If both are set, `value` takes precedence. |
| `action` | `"append" \| "prepend" \| "replace"` | How to combine this widget's text with the title contributed by other `DocumentTitle` widgets. Defaults to `"append"`. |
| `separator` | `string` | Separator inserted between titles when using `append` or `prepend`. Defaults to an empty string. |
| `append` | `boolean` | Deprecated. Use `action="append"` instead. |
2 changes: 2 additions & 0 deletions packages/cx/src/widgets/DocumentTitle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ export class DocumentTitle extends Widget<DocumentTitleConfig> {
}

prepare(context: RenderingContext, instance: Instance): void {
if (typeof document == "undefined") return;

if ((context as any).documentTitle.activeInstance == instance)
document.title = (context as any).documentTitle.title;
}
Expand Down
Loading