From 84b907077500d72a960afcf9b65100d5f53aa7d3 Mon Sep 17 00:00:00 2001 From: Ognjen Stefanovic Date: Mon, 29 Jun 2026 09:09:25 +0200 Subject: [PATCH 1/2] fix(DocumentTitle): prevent errors in server-side rendering by checking for document availability --- packages/cx/src/widgets/DocumentTitle.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cx/src/widgets/DocumentTitle.ts b/packages/cx/src/widgets/DocumentTitle.ts index da8e6b8f6..20779ef33 100644 --- a/packages/cx/src/widgets/DocumentTitle.ts +++ b/packages/cx/src/widgets/DocumentTitle.ts @@ -80,6 +80,8 @@ export class DocumentTitle extends Widget { } 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; } From ff7216e8cb7fdd6210c47e03094ef18721ba9ea6 Mon Sep 17 00:00:00 2001 From: Ognjen Stefanovic Date: Mon, 29 Jun 2026 09:09:35 +0200 Subject: [PATCH 2/2] feat(DocumentTitle): add DocumentTitle widget and documentation Introduced the DocumentTitle widget to set the browser tab title from the widget tree. Added an example implementation and comprehensive documentation detailing its usage, properties, and behavior in the context of dynamic title updates. --- homedocs/src/data/navigation.js | 6 +++ .../examples/layout/DocumentTitleExample.tsx | 27 +++++++++++ .../src/pages/docs/layout/document-title.mdx | 46 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 homedocs/src/examples/layout/DocumentTitleExample.tsx create mode 100644 homedocs/src/pages/docs/layout/document-title.mdx diff --git a/homedocs/src/data/navigation.js b/homedocs/src/data/navigation.js index 8addac285..f7f74697d 100644 --- a/homedocs/src/data/navigation.js +++ b/homedocs/src/data/navigation.js @@ -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", + }, ], }, { diff --git a/homedocs/src/examples/layout/DocumentTitleExample.tsx b/homedocs/src/examples/layout/DocumentTitleExample.tsx new file mode 100644 index 000000000..46daab43c --- /dev/null +++ b/homedocs/src/examples/layout/DocumentTitleExample.tsx @@ -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(); +// @model-end + +// @index +export default ( + + + +

+ Look at your browser tab — its title updates as you type. +

+
+); +// @index-end diff --git a/homedocs/src/pages/docs/layout/document-title.mdx b/homedocs/src/pages/docs/layout/document-title.mdx new file mode 100644 index 000000000..a4ca92d5d --- /dev/null +++ b/homedocs/src/pages/docs/layout/document-title.mdx @@ -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 + + + +`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. + + + + + +## 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 +; + +// A page deeper in the tree — prepends its name with a 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. |