@open-press/core
Frame
A fixed page surface or a nested region inside a page. Root Frames become output pages; nested Frames become selectable object boundaries inside the current page.
Renders a <section> with data-openpress-* attributes the engine reads. A root Frame is the page address used for allocation, comments, editing, and export. A nested Frame is a region object scoped under the current page.
import { Frame } from "@open-press/core"; <Frame
frameKey="cover"
role?="document.cover"
chrome?={true}
className?="reader-page--cover"
...sectionProps
>
{/* page or region contents */}
</Frame> Props
| Name | Type | Default | Description |
|---|---|---|---|
frameKey required | string | Stable identifier. On a root Frame, this is the page allocation key, page address, and data-openpress-frame-key. On a nested Frame, this is a region key scoped under the parent Frame and written to data-openpress-region-frame-key. Must be non-empty and must not contain :extended:. | |
children required | ReactNode | The page contents. Typically one or more <MdxArea> slots wrapped in a layout (.page-frame / .page-body) plus any header/footer chrome. | |
role | string | Semantic label. The core runtime does not branch on this value. It writes the value to data-frame-role; root Frames also derive data-page-kind from the last dot segment, such as cover from document.cover. Themes, inspectors, and agents can use it as a stable hint. | |
chrome | boolean | true | Root Frame only. When false, writes data-frame-chrome="false" and data-page-footer="false". Theme helpers use these flags to hide page chrome such as footer/header bands. Nested Frames inherit the page and do not emit chrome flags. |
className | string | Appended to the rendered section. Root Frames automatically include reader-page; nested Frames do not, so they can be used as neutral region boundaries. | |
...rest | HTMLAttributes | All other props pass through to the underlying <section>. data-* attributes are commonly used for layout flags read by CSS or the inspector. |
<Frame frameKey="ch-2" role="document.content" className="reader-page--content">
<div className="page-frame">
<header className="page-header" aria-hidden="true" />
<main className="page-body">
<MdxArea chainId="story" />
</main>
<footer className="page-footer">
<span className="footer-left">{title}</span>
<span className="footer-right">{pageIndex + 1}/{totalPages}</span>
</footer>
</div>
</Frame> <Frame
frameKey="slide-1"
role="canvas.slide"
chrome={false}
className="reader-page--slide"
>
<div className="page-frame">
<main className="page-body">
<MdxArea chainId="slides" overflow="truncate" />
</main>
</div>
</Frame> Page geometry
The <Frame> contract does not include a page prop. Paper or canvas size is
set on each <Press page> JSX prop. One Press → one fixed geometry; mixed-geometry
projects use a multi-Press <Workspace> with one geometry per Press.
Low-level context for custom helpers. MdxArea calls consumeArea to claim its slot in the engine's allocation table. Normal documents usually do not need to read this context directly.
import { FrameContext } from "@open-press/core"; const frame = useContext(FrameContext);
// -> { frameKey, objectId, pageId, consumeArea(chainId) } | null consumeArea(chainId) increments the per-chain counter on each call so multiple
<MdxArea> with the same chainId in one frame map to distinct
allocation slots in source order.
Symbol identifier the renderer uses to detect Frame instances during tree walking. Custom frame wrappers can re-export Frame and attach this marker.
import { FRAME_MARKER } from "@open-press/core"; Data attributes the renderer writes
The rendered <section> carries these attributes — theme selectors and
inspector behavior depend on them:
| Name | Type | Default | Description |
|---|---|---|---|
data-openpress-frame-key | string | Root Frames only. Mirrors the page frameKey. | |
data-openpress-region-frame-key | string | Nested Frames only. Mirrors the region frameKey inside the current page. | |
data-openpress-object-id | string | Object id used by the inspector, editing layer, and comment-marker system. | |
data-frame-role | string | Mirrors the role prop. | |
data-page-kind | string | Root Frames only. Last dot segment of role, for example cover from document.cover. | |
data-frame-chrome | "true" | "false" | Root Frames only. Reflects the chrome prop. | |
data-page-footer | "true" | "false" | Root Frames only. Matches data-frame-chrome by default. |
Role naming convention
role is a free string, but the framework documents a two-segment convention so themes
and docs stay consistent:
-
document.*— long-form pages that flow MDX content through the allocator:document.cover,document.toc,document.content,document.back-cover. -
canvas.*— fixed-format pages with one designed surface andoverflow="truncate"MDX areas:canvas.slide,canvas.post,canvas.card. -
manuscript.*— used by the bundled manuscript helpers (manuscript.contentfromDefaultSectionPage).