@@ -294,6 +294,43 @@ Creation of a Term is asynchronous because it may involve WASM module
294294preparation. A Term instance MAY be used for any number of render transactions.
295295The Term retains its cell buffers across frames for diffing purposes.
296296
297+ ### 7.5 Clip semantics
298+
299+ An element whose ` props ` include a ` clip ` group declares a ** clip region** : a
300+ rectangular bound on the cells its descendants are permitted to write. Cells
301+ produced by descendants that fall outside this region MUST be suppressed from
302+ the output. The clip region is determined by the element's computed layout box
303+ and the axes selected by the ` clip ` group (` horizontal ` , ` vertical ` , or both).
304+
305+ Clip regions stack. When clip elements nest:
306+
307+ - The effective clip region of an element MUST be the intersection of its own
308+ declared region with the effective clip region of its nearest clipping
309+ ancestor, if any.
310+ - When the renderer finishes processing a clip element's subtree, it MUST
311+ restore the effective clip region of that element's clipping ancestor. Later
312+ siblings drawn within an ancestor clip MUST therefore remain bounded by that
313+ ancestor.
314+ - A ` clip ` element whose declared region is fully outside its ancestor's
315+ effective region produces an empty effective region; descendants of that
316+ element MUST NOT contribute any cells to the output.
317+
318+ The renderer MAY impose an implementation-defined limit on the depth of clip
319+ regions it can track. The limit itself is not normatively bounded. When a frame
320+ nests clip regions more deeply than the renderer can track:
321+
322+ - All clip regions whose entry the renderer successfully tracked MUST continue
323+ to be honored for the remainder of the frame, including for siblings drawn
324+ after the over-deep subtree closes. The renderer MUST maintain push/pop
325+ symmetry so that exiting an untracked clip does not disturb any ancestor's
326+ effective region.
327+ - Content drawn inside an untracked clip region MUST remain bounded by the
328+ deepest successfully-tracked ancestor clip region. The untracked region's own
329+ additional restriction MAY be lost.
330+ - The renderer MUST surface the condition via the render result's error channel
331+ (see §12.3) before returning, so the caller can detect that some clipping was
332+ not applied.
333+
297334---
298335
299336## 8. Public Rendering API
@@ -648,7 +685,10 @@ The `open()` constructor currently accepts the following property groups in its
648685 color
649686- ** ` cornerRadius ` ** — per-corner radius values, producing rounded box-drawing
650687 characters
651- - ** ` clip ` ** — clip region configuration for scroll containers
688+ - ** ` clip ` ** — Declares the element as a clip region (see §7.5). Currently
689+ accepts ` horizontal: boolean ` and ` vertical: boolean ` axis selectors.
690+ Originally added for scroll containers; nesting and standalone use are
691+ supported.
652692- ** ` floating ` ** — floating-element configuration (offset, expansion, parent
653693 reference, attach target, structured attach points, pointer capture mode, clip
654694 target, z-index)
@@ -770,7 +810,8 @@ The `errors` field contains any errors reported by the Clay layout engine during
770810the most recent ` render() ` call. Each error is a ` ClayError ` object with:
771811
772812- ` type ` : a string identifying the error category. The following types are
773- defined, matching Clay's error taxonomy:
813+ defined. Most mirror Clay's error taxonomy; ` "CLIP_DEPTH_EXCEEDED" ` is
814+ Clayterm-specific.
774815 - ` "TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED" `
775816 - ` "ARENA_CAPACITY_EXCEEDED" `
776817 - ` "ELEMENTS_CAPACITY_EXCEEDED" `
@@ -780,6 +821,9 @@ the most recent `render()` call. Each error is a `ClayError` object with:
780821 - ` "PERCENTAGE_OVER_1" `
781822 - ` "INTERNAL_ERROR" `
782823 - ` "UNBALANCED_OPEN_CLOSE" `
824+ - ` "CLIP_DEPTH_EXCEEDED" ` — A frame nested clip regions more deeply than the
825+ renderer could track. See §7.5 for the guarantees that still hold in this
826+ case. The ` message ` SHOULD identify the renderer's tracking limit.
783827- ` message ` : a human-readable string describing the error in detail.
784828
785829Errors are collected per-render; each call to ` render() ` returns only the errors
@@ -852,6 +896,30 @@ background color.
852896accumulates per-cell direction bitmasks and resolves them to correct box-drawing
853897junction glyphs in a post-render pass.
854898
899+ ** Clip stack.** Section 7.5 requires the effective clip region of a nested
900+ ` clip ` element to be the intersection of its declared region with its clipping
901+ ancestor's effective region. The underlying layout engine (Clay) emits
902+ per-clip-element bounding boxes that are not pre-intersected with any ancestor's
903+ clip, so the renderer maintains an internal stack of effective clip rectangles:
904+ it pushes the intersected rect on each clip-region entry and pops on exit. The
905+ stack capacity is a small fixed value sufficient for realistic UIs; depth beyond
906+ that is handled per §7.5 (prior clips honored, the over-deep level coalesced
907+ into its deepest tracked ancestor, and a ` "CLIP_DEPTH_EXCEEDED" ` error
908+ surfaced).
909+
910+ Upstream Clay may eventually flatten nested clip emission so renderers only need
911+ single-rect handling; see
912+ [ nicbarker/clay #466 ] ( https://github.com/nicbarker/clay/issues/466 ) (the
913+ underlying issue),
914+ [ nicbarker/clay #485 ] ( https://github.com/nicbarker/clay/pull/485 ) (in-flight
915+ Clay-side fix), and
916+ [ nicbarker/clay #87 ] ( https://github.com/nicbarker/clay/issues/87 ) (renderer
917+ guidance). When upgrading Clay, check whether a single clip element now produces
918+ multiple ` SCISSOR_START ` /` SCISSOR_END ` pairs across its lifetime (one per
919+ nesting transition rather than just an outer pair); if so, the renderer-side
920+ stack can be removed and replaced with a single rect storing Clay's bounding box
921+ directly.
922+
855923---
856924
857925## 14. Deferred / Future Areas
0 commit comments