Repeater
import "@taprootio/espalier/repeater";
<esp-repeater>
General-purpose virtualized repeater for rich repeated content such as cards, image rows, or other custom-element item layouts. Consumers provide the item renderer and own the visual design of each repeated item.
Because the list is virtualized, repeated item content is supplied through
the renderItem property instead of light-DOM children. This lets the
repeater create item DOM on demand as the user scrolls.
Use layout="grid" to opt into responsive card layouts. Consumers can
provide a fixed fallback with grid-columns and override the live column
count with --esp-repeater-grid-columns in media queries.
Use scroll-model="page" when the repeater should participate in the
document's natural page scroll instead of owning a nested scrolling
viewport. In page mode, list-height is ignored.
Examples
Basic image list
Cursor-paged image list
Grid mode with responsive columns
Full-page gallery with page scroll
Properties
EspalierRepeater has the following properties:
virtualizerRef
—
containerRef
—
pageLoads
—
nextCursor
Type: string | null
lastObservedWidth
Type: number
observersAttached
Type: boolean
gridObserversAttached
Type: boolean
resolvedGridColumns
Type: number
memoizedGridRowsSource
Type: unknown[] | null
memoizedGridRowsColumns
Type: number
memoizedGridRows
Type: RepeaterGridRow<unknown>[]
hostAttributeObserver
Type: MutationObserver | null
resizeObserver
Type: ResizeObserver | null
viewportResizeListener
Type: (() => void) | null
pageScrollStabilizerActive
Type: boolean
activePageScrollStabilizer
Type: PageScrollStabilizer | null
isAdjustingHeight
Type: boolean
pendingHeightRetry
Type: boolean
heightRetryObserver
Type: IntersectionObserver | null
isLoadingPage
Type: boolean
loadedItems
Type: unknown[]
hasMoreData
Type: boolean
effectiveListHeight
Type: string
loadError
Type: string
items
items has a type of unknown[].
Items to render when the repeater is used without cursor paging.
If fetchPage is set, the repeater manages its own loaded item
collection internally.
renderItem
renderItem has a type of RepeaterRenderItem<unknown> | null.
Callback used to render each repeated item. This is the recommended API for rich custom-element content because the repeater virtualizes items and instantiates them on demand.
layout
layout has a type of "list" | "grid".
Visual layout mode for the rendered content.
Use grid to opt into responsive card-style rows while
preserving virtualization and paging behavior.
scrollModel
scrollModel has a type of "contained" | "page".
Scroll behavior model for the repeater viewport.
Use contained for the current nested scrolling behavior driven by
list-height. Use page when the repeater should scroll with the
document/page instead.
gridColumns
gridColumns has a type of number.
Fixed grid column count fallback used when layout="grid"
and no --esp-repeater-grid-columns custom property override
is applied.
ariaLabel
ariaLabel has a type of string | null.
Accessible label forwarded to the internal virtualized list.
listHeight
listHeight has a type of string.
The height of the repeater viewport. Accepts any valid CSS height
value. Defaults to 60vh. Ignored when scroll-model="page".
pageSize
pageSize has a type of number.
Number of items requested per page when fetchPage is used.
prefetchThreshold
prefetchThreshold has a type of number.
Number of items from the end of the currently loaded set at which the repeater should prefetch the next page.
loading
loading has a type of boolean.
External loading flag for non-paged usage or for cases where the consumer wants to force a loading state.
loadingMessage
loadingMessage has a type of string.
Default loading message used when no custom loading or skeleton
slot content is provided.
emptyMessage
emptyMessage has a type of string.
Default empty-state message used when no custom empty slot content
is provided.
errorMessage
errorMessage has a type of string.
Optional consumer-provided error message. When set it takes priority over internal fetch errors for display purposes.
fetchPage
fetchPage has a type of | ((params: CursorPageRequest) => Promise<CursorPageResult<unknown>>) | null.
Provide a callback to enable cursor-based infinite paging. When set, the repeater fetches additional items as the user scrolls near the end of the currently loaded range.
fetchPageBacker
Type: | ((params: CursorPageRequest) => Promise<CursorPageResult<unknown>>) | null
isPagedMode
Type: boolean
isGridLayout
Type: boolean
isPageScrollModel
Type: boolean
isContainedScrollModel
Type: boolean
renderedItems
Type: unknown[]
virtualizerItems
Type: Array<unknown | RepeaterGridRow<unknown>>
isBusy
Type: boolean
activeErrorMessage
Type: string
normalizedPageSize
Type: number
normalizedPrefetchThreshold
Type: number
normalizedGridColumns
Type: number
effectiveGridColumns
Type: number
renderVirtualItem
Type: RenderItemFunction<unknown>
renderVirtualRow
Type: RenderItemFunction<RepeaterGridRow<unknown>>
renderGridVirtualItem
Type: RenderItemFunction<unknown>
seedColorBacker
Type: string
espRoot
Type: EspalierRoot | null
contextBacker
Type: string
scopedTokenOriginalValues
—
warnedUnknownContexts
—
pendingInitialThemeRoot
Type: EspalierRoot | null
rootEventSubscriptionsActive
Type: boolean
subscribedRoot
Type: EspalierRoot | null
rootEventUnsubscribers
Type: Array<() => void>
intentBacker
Type: EspalierIntentVariant
intentEmitsTokens
intentEmitsTokens has a type of boolean.
Whether a non-neutral intent emits its inline tokens
(--esp-color-primary and the filled-action pair). Interactive
controls need them; chrome whose intent treatment is class-based
(badges, callouts, status pills — see intentSurfaceTokens) opts
out so a decorative intent never rewrites inherited tokens for
slotted content.
warnedUnknownIntents
—
seedColor
Type: string
correlationId
—
scheme
scheme has a type of "dark" | "light".
The scheme to use for the component. This property is used internally to control the light/dark scheme so it matches the scheme of esp-root. It should not be set manually, it exists as an attribute for styling purposes.
intent
intent has a type of EspalierIntentVariant.
The element's intent — its meaning: neutral
(no pin), or success, warning, danger, info — each pinned
to its fixed status family (blue for info), retunable per theme
via intents. On token-emitting controls a non-neutral intent pins the
filled-action pair to that family, derived over the governing
zone's theme; class-styled chrome (badges, callouts, status pills)
opts out of inline emission and renders its treatment from CSS
classes instead. An intent never repaints the surrounding zone,
which is what contexts are for. Removing the attribute restores
the element's own default intent.
context
context has a type of string.
A theme-defined color zone. The selected context rebinds designer-facing roles and emits a complete, contrast-enforced semantic token table on this host for descendants to inherit.
handleSeedColorChanged
—
handleSchemeChanged
—
handleThemeChanged
—
handleIconSpriteUrlChanged
—
intentColorSources
intentColorSources has a type of `Readonly<
Record<EspalierIntentVariant, ColorSource | "">
`.
Intent color sources: the meaning-bearing families an intent pins
the filled-action pair to. neutral pins nothing; each other
intent maps to its own fixed status family (ESP0172 gave info a
real blue family, replacing the complementary borrow the retired
variant system used), and a theme's intents field retunes the
family colors themselves.
semanticActionTokens
semanticActionTokens has a type of ReadonlySet<SemanticColorName>.
Semantic tokens that paint a control's filled action surface — the
pair an intent recolors. Everything else inherits the zone cascade,
which is the ESP0166 fix: under the SHY fitted theme the retired
variant re-seeding painted a danger callout's background mint
green; an intent leaves the zone's surfaces alone and pins only the
action pair (plus --esp-color-primary for state derivations) to
the intent's own status family — fixed hues by default, retunable
per theme via intents. Task 098's
guarantee survives structurally: the
pin is by source, so no theme mapping can rotate a destructive /
warning / positive action off its semantic hue.
Methods
<esp-repeater> has the following methods:
clear
Clear the currently rendered items. In cursor-paged mode this also clears the cursor and any pending load error.
reload
Clear any loaded pages and request the first page again when cursor paging is enabled.
scrollToIndex
Delegate scrolling to the underlying virtualizer.
traverseToClosest
Traverse up the DOM tree to find the closest element that matches the selector. This method is aware of shadow DOM boundaries and will traverse through them to find the element.
Slots
<esp-repeater> has the following slots:
empty
Optional empty-state content shown when the repeater has no items.
error
Optional error-state content shown when loading fails or errorMessage is set.
loading
Optional loading-state footer shown while additional pages are loading.
skeleton
Optional initial loading state shown when loading starts before any items are rendered.
CSS Properties
<esp-repeater> has the following CSS properties:
--esp-repeater-background
Background of the repeater container.
--esp-repeater-border
Border of the repeater container.
--esp-repeater-border-radius
Border radius of the repeater container.
--esp-repeater-gap
Space between repeated items.
--esp-repeater-padding
Padding used by repeater state panels and the loading/error footer.
--esp-repeater-content-padding
Padding inside the virtualized content region. Defaults to 0.
--esp-repeater-grid-columns
Grid column count when layout="grid". Supports media-query overrides.
--esp-repeater-grid-column-gap
Horizontal gap between grid columns.
--esp-repeater-grid-row-gap
Vertical gap between grid rows.
--esp-field-background
Background color of the shared field shell. Defaults to var(--esp-color-layer-2).
--esp-field-border-color
Border color of the shared field shell. Defaults to var(--esp-color-border).
--esp-field-border-width
Border width of the shared field shell. Defaults to 1px.
--esp-field-text-color
Text color used inside the shared field shell. Defaults to var(--esp-color-text).
--esp-field-hover-bg
Hover background color of the shared field shell. Derived from --esp-field-background.
--esp-field-focus-bg
Focus background color of the shared field shell. Derived from --esp-field-background.
--esp-field-focus-shadow
Shadow color used for shared field focus treatment. Defaults to var(--esp-color-shadow).