A story is a top-level function decorated @story("Component / state") that
returns the component's View in one named state. Its parameters, if any,
all carry defaults: zolo test mounts the story with them, and the gallery
turns them into controls.
zolo test mounts every story, checks it with to_be_accessible() and
compares it with a snapshot, and the editor offers a "Run Story" lens on it,
so the decorator has to be complete and unambiguous. TE155 reports the shapes
the tooling cannot use:
@story // error[TE155]: needs a label
fn pagination_first() -> View { ... }
@story("Pagination / first page")
fn pagination(page: int) -> View { ... } // error[TE155]: a story takes no parameters
@story("Pagination / first page") // error[TE155]: duplicate label
fn pagination_again() -> View { ... }
mod previews {
@story("Nested") // error[TE155]: top-level functions only
fn nested() -> View { ... }
}The same code covers @story_layout, the page the dev gallery wraps every
story in: it takes no decorator arguments, exactly one parameter (the
story's View), needs a body, must be top-level, and a file declares at
most one.
Named arguments are rejected too. play: is reserved for interaction stories
on the headless client; until that layer ships, a play: that ran nowhere
would be a silent lie, so the compiler refuses it.
Give each story a unique label, no parameters and a body:
@story("Pagination / first page")
fn pagination_first() -> View {
<UsersPagination page={load_users(42, 1, 50, TOTAL_USERS)} />
}