Skip to main content

Capabilities

Capabilities are the things a component can do. Which ones a component has depends on its type: videos play, text can be rewritten, anything visible can be shown, hidden, or switched between states.

Each capability is a namespace on the component. It exists only if the component carries it — otherwise the property is undefined.

CapabilityOnMethods
mediacml-videoplay(), pause()
textcml-textsetText(text), getText()
statesAny visible elementactivate(name), deactivate(name), toggle(name), list(), current()
visibilityAny visible elementshow(), hide(), isHidden()
pagesThe experiencelist(), current(), goTo(page), next(), previous()

"Any visible element" means cml-section, cml-group, cml-oval, cml-rectangle, cml-polygon, cml-image, cml-video, cml-svg, cml-text, and cml-embed.

Check before using, or use optional chaining:

const hero = experience.findByLocator('hero').only()

if (hero.has('media')) hero.media.play()
hero.text?.setText('Hi') // does nothing if it isn't text

On a ComponentSet these same namespaces reach every member that carries the capability, and skip the rest.


media

interface MediaCapability {
play(): void
pause(): void
}

Video playback, on cml-video.

const video = experience.findByLocator('hero-video').only()

video.media.play()
video.media.pause()

experience.findByTag('cml-video').media.pause() // pause every video
  • play() behaves like a viewer tapping play. If the browser blocks autoplay it does nothing rather than raising an error, so an unattended page stays quiet. Browsers generally allow playback that follows a real user gesture — starting a video from inside a component.click handler is the reliable pattern.
  • Before the video has finished rendering, both methods do nothing.

text

interface TextCapability {
setText(text: string): void
getText(): string
}

Read and replace the text of a cml-text component.

const headline = experience.findByLocator('headline').only()

headline.text.setText('Welcome back')
headline.text.getText() // 'Welcome back'
  • setText replaces the text and keeps the styling you designed.
  • getText returns the plain text with no markup, or '' before the component has rendered.
  • Always use setText rather than writing to the element's textContent, which can corrupt what Ceros renders.
  • getText is a read, so on a set it runs on the first match — see how calls fan out.

states

interface StatesCapability {
activate(name: string): void
deactivate(name: string): void
toggle(name: string): void
list(): string[]
current(): string | null
}

Switch a component between the states set up in Flex — an expanded card, a selected option, a hover treatment. Carried by every visible element.

const card = experience.findByLocator('product-card').only()

card.states.list() // ['expanded', 'minimized'] — what this component declares
card.states.current() // 'expanded', or null when it's in its default state
card.states.activate('expanded') // turn on
card.states.deactivate('expanded') // turn off
card.states.toggle('expanded') // flip whichever way it currently is

// toggle a state across every match
experience.findByLocator('faq-item').states.toggle('open')
  • name is the state's name as it appears in Flex.
  • toggle(name) is a genuine toggle — it takes no arguments beyond the name. Use activate / deactivate when you want to force a direction.
  • A name the component doesn't have does nothing and logs the names it does have.
  • list() and current() are reads, so on a set they run on the first match.

visibility

interface VisibilityCapability {
show(): void
hide(): void
isHidden(): boolean
}

Show and hide elements at runtime. Carried by every visible element.

const banner = experience.findByLocator('promo-banner').only()

banner.visibility.hide()
banner.visibility.isHidden() // true
banner.visibility.show()

// reveal everything the design hides by default
experience.findByLocator('hidden-on-load').visibility.show()
  • show() and hide() override what you published for this page view. They pull the same lever as a show/hide interaction authored in Flex.
  • isHidden() reports what's actually true right now: your override if you've set one, otherwise the published visibility.
  • show() / hide() apply to every member of a set; isHidden() reads the first.
note

show(), hide(), and isHidden() are available today, but the VisibilityCapability TypeScript type isn't exported yet. Use the methods freely — just don't import that one type name until it lands.


pages

interface PageInfo {
slug: string // the page's URL-safe identifier — what goTo() takes
label: string // its display name (falls back to the slug when unnamed)
}

interface PagesCapability {
list(): PageInfo[]
current(): PageInfo | undefined
goTo(page: string | number): void
next(): void
previous(): void
}

Navigate a multi-page experience. Carried by the experience itself, so you reach it as experience.pages.

const experience = await connect()

experience.pages.list() // [{ slug: 'intro', label: 'Intro' }, …] in order
experience.pages.current() // { slug: 'intro', label: 'Intro' }
experience.pages.goTo('pricing') // by slug
experience.pages.goTo(2) // or by index, matching list()
experience.pages.next()
experience.pages.previous()
  • A slug that doesn't exist, or an index out of range, does nothing and logs the pages that are available.
  • next() on the last page and previous() on the first do nothing.
  • On an embedded experience (Flex Inline or SSR) navigation happens in place, and your handle needs re-connecting afterwards — see Delivery modes.

Anything you change is runtime only

Text, states, and visibility all change the live page and nothing more. None of it is written back to your experience, and a reload restores exactly what was published. See Limits.