Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs/develop/java/activities/standalone-activities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ReleaseNoteHeader } from '@site/src/components';

<ReleaseNoteHeader
featureName="standaloneActivity"
language="Java"
/>

[Standalone Activities](/standalone-activity) are Activities that run independently, without being orchestrated by a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: Offload large payloads to external storage using the claim check pa

import { ReleaseNoteHeader } from '@site/src/components';

<ReleaseNoteHeader type="prerelease">
<ReleaseNoteHeader featureName="externalStorage">
APIs and configuration may change before General Availability. Join the
[#large-payloads Slack channel](https://temporalio.slack.com/archives/C09VA2DE15Y) to provide feedback or ask for
help.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ tags:
- Temporal
---

import { FeatureStageTable } from '@site/src/components';

:::tip CHANGELOG
To stay up-to-date with the latest feature changes, visit the [changelog](https://temporal.io/change-log).
:::
Expand All @@ -27,6 +29,8 @@ Product Release Guide Expectations:
| **Feature Cloud pricing** | No additional cost. | Pricing changes are kept to a minimum. | Pricing is stable. |
| **Feature Interoperability** | Limited. | Features are compatible with each other, unless otherwise stated. | Features are compatible with each other. |

<FeatureStageTable />

## Pre-release {/* #pre-release */}

**Access:** Most Pre-release features are released in the open source Temporal software and are publicly available.
Expand Down
59 changes: 56 additions & 3 deletions readme/COMPONENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Whether you’re using core components or experimenting with new ones, this guid
- [Using SdkGuideLinks](#using-sdkguidelinks)
- [Using AnnotatedCode](#using-annotatedcode)
- [Using ReleaseNoteHeader](#using-release-note-header)
- [Using FeatureStageLabel](#using-featurestagelabel)
- [Using FeatureStageTable](#using-featurestagetable)

## Finding Components

Expand Down Expand Up @@ -521,9 +523,22 @@ Role: To provide a consistent component for adding, updating, and removing relea

Usage:

In `/src/constants`, update the [`featureReleaseTypes.js`](../src/constants/featureReleaseTypes.js) file to include the release stage for the feature you want.
In `/src/constants`, update the [`featureReleaseTypes.js`](../src/constants/featureReleaseTypes.js) file to include the feature you want, its stage, and its display metadata (used by the `FeatureStageTable` on the [release stages page](../docs/evaluate/development-production-features/release-stages.mdx)).

Example: `serverlessWorkers: "prerelease"`
```js
serverlessWorkers: {
stage: "prerelease",
name: "Serverless Workers",
description: "Run a Temporal Worker as a serverless function invoked by Temporal Cloud.",
infoLink: "/serverless-workers",
// Optional — only add this when a feature's stage genuinely differs by SDK
// language. Keys must match ReleaseNoteHeader's SDK language vocabulary
// (".NET" | "Go" | "Java" | "PHP" | "Python" | "Ruby" | "Rust" | "TypeScript").
languageOverrides: {
Java: "publicPreview",
},
},
```

Then on the pages you want it to show, add this to the top of the content, right below the frontmatter. The `featureName` prop is how you share the release stages you add to `featureReleaseTypes.js` across pages.

Expand Down Expand Up @@ -569,4 +584,42 @@ Use the `href` prop to make the `children` content a link.
>
Sign up for updates to be notified when Serverless Workers reach Public Preview.
</ReleaseNoteHeader>
```
```

If a feature's `languageOverrides` includes the SDK this page is about, add the `language` prop so the badge resolves to that language's stage instead of the feature's default.
```js
<ReleaseNoteHeader
featureName="serverlessWorkers"
language="Java"
/>
```

## Using FeatureStageLabel

Role: The inline sibling of `ReleaseNoteHeader`, for mentioning a feature's stage mid-sentence in prose instead of as a page-level banner. Sourced from the same [`featureReleaseTypes.js`](../src/constants/featureReleaseTypes.js) registry, so these mentions can't drift out of sync with the banner the way a hand-written `[Public Preview](/evaluate/development-production-features/release-stages#public-preview)` link can.

Usage:

```js
import { FeatureStageLabel } from '@site/src/components';

The Rust SDK is in <FeatureStageLabel featureName="rustSdk" />, and its API can change between releases.
```

Accepts the same `featureName`, `language`, and `type` props as `ReleaseNoteHeader`, resolved the same way. Renders a plain prose link — no pill/badge styling — since it's meant to sit inline in a sentence.

## Using FeatureStageTable

Role: Renders every feature currently in `featureReleaseTypes.js`, grouped by stage, as a Markdown-style table. Used on the [release stages page](../docs/evaluate/development-production-features/release-stages.mdx) to give a single, always-current view of what's non-GA — no separate list to hand-maintain.

Usage:

```js
import { FeatureStageTable } from '@site/src/components';

<FeatureStageTable />
```

Takes no props — it reads `featureReleaseTypes.js` directly, so a feature appears here automatically once it has a registry entry with `name`, `description`, and `infoLink`. Each stage section (Pre-release, Public Preview) is its own table with two columns, Feature and Details — there's no separate Stage column, since the section heading already says it. The Details cell is the feature's `description`; a feature with a `languageOverrides` entry gets a bolded note appended (e.g. "…without a Workflow orchestrating it. **Note:** Java support is in Pre-release.") instead of a separate row per language.

Write `description` as its own brief, feature-specific summary — what the feature actually does, in one sentence — rather than reusing the target page's meta `description` verbatim. A page's meta description is written for the whole page and SEO, so it's often too broad (e.g. a general SDK setup page) or too generic ("Learn how...") for a table row about one specific feature.
5 changes: 3 additions & 2 deletions readme/COMPONENT_REGISTRY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

Generated by `scripts/audit-components.mjs`. Run to update.

**Coverage: 43/51 (84%)**
**Coverage: 44/52 (85%)**

| Component | File Count | Strategy | Covered |
|-----------|------------|----------|---------|
| `ReleaseNoteHeader` | 84 | `release-note-header` | ✅ |
| `TabItem` | 84 | `tabitem` | ✅ |
| `Tabs` | 83 | `tabs` | ✅ |
| `ReleaseNoteHeader` | 76 | `release-note-header` | ✅ |
| `NoZoom` | 60 | `UNKNOWN` | ❌ |
| `RelatedReadContainer` | 23 | `related-read-container` | ✅ |
| `RelatedReadItem` | 20 | `related-read-item` | ✅ |
Expand Down Expand Up @@ -44,6 +44,7 @@ Generated by `scripts/audit-components.mjs`. Run to update.
| `CallerWorkflow` | 1 | `UNKNOWN` | ❌ |
| `SdkOverviewCards` | 1 | `sdk-overview-cards` | ✅ |
| `TemporalLifecycleDemo` | 1 | `UNKNOWN` | ❌ |
| `FeatureStageTable` | 1 | `feature-stage-table` | ✅ |
| `CloudRegionCount` | 1 | `strip-block` | ✅ |
| `GuidesGrid` | 1 | `UNKNOWN` | ❌ |
| `HeroWrapper` | 1 | `strip-tag` | ✅ |
Expand Down
2 changes: 2 additions & 0 deletions readme/MARKDOWN_PIPELINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Each component maps to a strategy in `COMPONENT_REGISTRY` (in `scripts/mdx-to-md
| YouTube/`<iframe>` embeds (often in a styled `<div>`) | strip | Removed; keep a markdown Watch link in surrounding tip/prose for LLMs |
| `CallToAction` | `call-to-action` | `- [h3 title](href): p description` |
| `ReleaseNoteHeader` | `release-note-header` | `> **Public Preview** — Go, Java…` availability note + body blockquote. The self-closing form (`<ReleaseNoteHeader … />`) emits just the note and leaves the page body intact. |
| `FeatureStageLabel` | `inline-feature-stage-label` | Inline: replaced with `[Public Preview](…#public-preview)` (or Pre-release), resolved from `featureReleaseTypes.js` the same way as `ReleaseNoteHeader` |
| `FeatureStageTable` | `feature-stage-table` | Two Markdown tables (Pre-release, then Public Preview) listing every registered feature, resolved from `featureReleaseTypes.js` |
| `RelatedReadContainer` / `RelatedReadItem` | `related-read-container` / `related-read-item` | `**Related:**` Markdown link list |
| `RelatedReadList` | `related-read` | Link list from the `readList` prop |
| `ToolTipTerm` | `tooltip-term` | Inline: replaced with the bare `term` text |
Expand Down
59 changes: 59 additions & 0 deletions scripts/component-handlers/feature-stage-table.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* component-handlers/feature-stage-table.mjs
*
* Handler for <FeatureStageTable /> (self-closing, no props).
* Component: src/components/elements/Tables/FeatureStageTable.js
*
* Renders the current FEATURE_RELEASE_TYPES registry as Markdown tables, one
* per stage (Pre-release, then Public Preview), matching the React
* component's grouping and Notes-column behavior for language overrides.
*/

// Language-override note, e.g. "**Note:** Java support is in Pre-release." The
// stage itself isn't repeated here — the section heading already says it.
function noteFor(entry, stageLabels) {
if (!entry.languageOverrides) return "";
const clauses = Object.entries(entry.languageOverrides).map(
([lang, stage]) => `${lang} support is in ${stageLabels[stage].label}`
);
return `**Note:** ${clauses.join("; ")}.`;
}

function detailsFor(entry, stageLabels) {
const note = noteFor(entry, stageLabels);
return note ? `${entry.description} ${note}` : entry.description;
}

/**
* @param {object} featureReleaseTypes FEATURE_RELEASE_TYPES from featureReleaseTypes.js
* @param {object} stageLabels STAGE_LABELS from featureReleaseTypes.js
* @returns {string}
*/
export function featureStageTableToMarkdown(featureReleaseTypes, stageLabels) {
const stageOrder = ["prerelease", "publicPreview"];
const headingByStage = {
prerelease: "### Pre-release features",
publicPreview: "### Public Preview features",
};

const sections = stageOrder
.map((stage) => {
const entries = Object.values(featureReleaseTypes).filter((entry) => entry.stage === stage);
if (entries.length === 0) return null;

const rows = entries.map(
(entry) => `| [${entry.name}](${entry.infoLink}) | ${detailsFor(entry, stageLabels)} |`
);

return [
headingByStage[stage],
"",
"| Feature | Details |",
"| --- | --- |",
...rows,
].join("\n");
})
.filter(Boolean);

return sections.join("\n\n");
}
38 changes: 33 additions & 5 deletions scripts/mdx-to-md.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* - <CodeSnippet language="x"> → fenced code block
* - <CallToAction href> → markdown link (h3 title + p description)
* - <ReleaseNoteHeader> → availability blockquote + body
* - <FeatureStageLabel /> → inline `[Public Preview](...)` link
* - <FeatureStageTable /> → Markdown tables resolved from FEATURE_RELEASE_TYPES
* - <RelatedReadContainer> → markdown link list from <RelatedReadItem>s
* - <RelatedReadList> → markdown link list from readList prop
* - <SdkGuideLinks> → markdown link list, one per SDK (path/filter/title or links prop)
Expand All @@ -39,7 +41,8 @@ import { cookbookPreviewToMarkdown } from "./component-handlers/cookbook-preview
import { heroCardToMarkdown, heroHeadlineToMarkdown } from "./component-handlers/hero.mjs";
import { parseCardItems, cardsToMarkdown } from "./component-handlers/cards.mjs";
import { sdkOverviewCardsToMarkdown } from "./component-handlers/sdk-overview-cards.mjs";
import { FEATURE_RELEASE_TYPES } from "../src/constants/featureReleaseTypes.js";
import { featureStageTableToMarkdown } from "./component-handlers/feature-stage-table.mjs";
import { FEATURE_RELEASE_TYPES, STAGE_LABELS, resolveFeatureStage } from "../src/constants/featureReleaseTypes.js";
import { readFileSync, existsSync } from "fs";
import { join } from "path";

Expand Down Expand Up @@ -75,6 +78,8 @@ export const COMPONENT_REGISTRY = {
CookbookPreview: "cookbook-preview",
SdkOverviewCards: "sdk-overview-cards",
ViewSourceCodeNotice: "view-source-code-notice",
FeatureStageLabel: "inline-feature-stage-label",
FeatureStageTable: "feature-stage-table",

// Homepage hero (docs/index.mdx). Copy is authored in the MDX and composed
// from presentational components in src/components/elements/HomePageHero.js.
Expand Down Expand Up @@ -141,9 +146,9 @@ const RELEASE_NOTE_LABELS = {
deprecated: "Deprecated",
};

/** Mirrors ReleaseNoteHeader.getResolvedType — featureName lookup, then type, then default. */
function resolveReleaseNoteType(featureName, type) {
return FEATURE_RELEASE_TYPES[featureName] || type || "publicPreview";
/** Thin call-through to the shared resolver in featureReleaseTypes.js. */
function resolveReleaseNoteType(featureName, type, language) {
return resolveFeatureStage(featureName, { type, language });
}

function releaseNoteLabelFromType(resolvedType) {
Expand Down Expand Up @@ -358,6 +363,16 @@ export function applyInlineTransforms(line) {
(m, inner) => extractProp(m, "term") || inner
);

// Inline <FeatureStageLabel featureName="x" /> → [Public Preview](descriptionLink)
out = out.replace(/<FeatureStageLabel\b[^>]*\/>/g, (m) => {
const featureName = extractProp(m, "featureName") || "";
const language = extractProp(m, "language");
const type = extractProp(m, "type");
const stage = resolveFeatureStage(featureName, { type, language });
const meta = STAGE_LABELS[stage] || STAGE_LABELS.publicPreview;
return `[${meta.label}](${meta.descriptionLink})`;
});

// Collapse a line left whitespace-only (e.g. after a comment was stripped)
// to a true blank line — an indented blank could otherwise read as code.
if (/^\s+$/.test(out)) return "";
Expand Down Expand Up @@ -1109,8 +1124,9 @@ export function transformMdx(mdxContent, options = {}) {
}
const featureName = extractProp(tag, "featureName") || "";
const type = extractProp(tag, "type");
const language = extractProp(tag, "language");
const labelOverride = extractProp(tag, "label");
const resolvedType = resolveReleaseNoteType(featureName, type);
const resolvedType = resolveReleaseNoteType(featureName, type, language);
releaseNoteLabel = labelOverride || releaseNoteLabelFromType(resolvedType);
const langsMatch = tag.match(/languages=\{(\[[^\]]*\])\}/);
if (langsMatch) {
Expand Down Expand Up @@ -1310,6 +1326,18 @@ export function transformMdx(mdxContent, options = {}) {
continue;
}

// --- FeatureStageTable (self-closing, no props) → resolved Markdown tables ---
if (state === State.NORMAL && /^\s*<FeatureStageTable\b/.test(line)) {
let tag = line;
while (!/\/?>/.test(tag) && i + 1 < lines.length) {
i++;
tag += " " + lines[i].trim();
}
outputLines.push(featureStageTableToMarkdown(FEATURE_RELEASE_TYPES, STAGE_LABELS));
outputLines.push("");
continue;
}

// --- QuickstartCards / PatternCards / GridCardList → Markdown link list from items prop ---
if (state === State.NORMAL && /^\s*<(QuickstartCards|PatternCards|GridCardList)\b/.test(line)) {
let tag = line;
Expand Down
14 changes: 14 additions & 0 deletions src/components/elements/FeatureStageLabel/FeatureStageLabel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
import Link from "@docusaurus/Link";
import { resolveFeatureStage, STAGE_LABELS } from "../../../constants/featureReleaseTypes";

// Inline sibling of ReleaseNoteHeader for mid-sentence prose, e.g.
// "The Rust SDK is in <FeatureStageLabel featureName="..." />." Renders a
// plain prose link — no pill/badge styling — sourced from the same registry
// so these mentions can't drift the way hand-written links have.
export default function FeatureStageLabel({ featureName, language, type }) {
const resolvedType = resolveFeatureStage(featureName, { type, language });
const meta = STAGE_LABELS[resolvedType] || STAGE_LABELS.publicPreview;

return <Link to={meta.descriptionLink}>{meta.label}</Link>;
}
1 change: 1 addition & 0 deletions src/components/elements/FeatureStageLabel/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as FeatureStageLabel } from './FeatureStageLabel'
20 changes: 11 additions & 9 deletions src/components/elements/ReleaseNoteHeader/ReleaseNoteHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@ import React from "react";
import Link from "@docusaurus/Link";
import SdkSvg from '../SdkSvgs/SdkSvg';
import styles from "./ReleaseNoteHeader.module.css";
import { FEATURE_RELEASE_TYPES } from "../../../constants/featureReleaseTypes";
import { resolveFeatureStage, STAGE_LABELS } from "../../../constants/featureReleaseTypes";

export const BASE_RELEASE_STAGES = {
prerelease: {
label: "Pre-release",
descriptionLink: "/evaluate/development-production-features/release-stages#pre-release",
...STAGE_LABELS.prerelease,
backgroundColor: "var(--release-prerelease-bg)",
borderColor: "var(--release-prerelease-border)",
textColor: "var(--release-prerelease-text)",
},
publicPreview: {
label: "Public Preview",
descriptionLink: "/evaluate/development-production-features/release-stages#public-preview",
...STAGE_LABELS.publicPreview,
backgroundColor: "var(--release-public-preview-bg)",
borderColor: "var(--release-public-preview-border)",
textColor: "var(--release-public-preview-text)",
Expand Down Expand Up @@ -45,8 +43,8 @@ const LANGUAGE_TO_SDK_SLUG = {
"TypeScript": "typescript",
}

function getResolvedType({ featureName, type }) {
return FEATURE_RELEASE_TYPES[featureName] || type || "publicPreview";
function getResolvedType({ featureName, type, language }) {
return resolveFeatureStage(featureName, { type, language });
}

function getTheme(type, overrides = {}) {
Expand All @@ -63,6 +61,10 @@ export default function ReleaseNoteHeader({
type = "publicPreview",
// name of the feature being released
featureName,
// If featureName has a languageOverrides entry for this language, it wins
// over the feature's default stage. Distinct from `languages` below, which
// only controls which SDK icons are rendered.
language,
// If there is anything specific to say about the release, it can be passed as a child to the component. It can also be a link if href is provided.
children = "APIs and configuration may change before the stable release.",
// If child is a link, this is where the link can be passed.
Expand All @@ -74,7 +76,7 @@ export default function ReleaseNoteHeader({
// If you want to override the default label for the release type, you can pass it here. This is useful for cases like "generalAvailability" where you might want to just say "Stable".
label,
}) {
const resolvedType = getResolvedType({ featureName, type });
const resolvedType = getResolvedType({ featureName, type, language });
const theme = getTheme(resolvedType);

const releaseLabel = label || theme.label;
Expand All @@ -91,7 +93,7 @@ export default function ReleaseNoteHeader({
style={style}
role="note"
aria-label={releaseLabel}
data-release-type={type}
data-release-type={resolvedType}
>
<div className={styles.accent} aria-hidden="true" />
<div className={styles.content}>
Expand Down
Loading