Documentation
- Zeta Flutter
- Zeta Web
Widgetbook serves as both an interactive development sandbox and published documentation at design.zebra.com. Just adding a use-case is not enough - ensure that the documentation is thorough and complete, and that all properties and events are documented.
What is auto-generated
@widgetbook.UseCase generates a Docs page from the component's dart doc and use case definition. Keep dart doc accurate and complete — it is the documentation:
| Source | Generated as |
|---|---|
| Class dart doc description | Component description on the Docs page |
| Constructor parameter dart docs | Parameter descriptions in knobs panel |
context.knobs.* calls | Interactive controls |
designLink in @UseCase | Figma design panel |
Run dart run build_runner build -d from the widgetbook/ directory before opening a PR — otherwise the controls panel will be out of date.
Standard template
import 'package:flutter/material.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook;
import 'package:zeta_flutter/zeta_flutter.dart';
.UseCase(
name: 'ZetaFoo',
type: ZetaFoo,
path: 'components/Foo',
designLink: 'https://www.figma.com/design/JesXQFLaPJLc1BdBM4sisI/...',
)
Widget zetaFoo(BuildContext context) {
return ZetaFoo(
label: context.knobs.string(label: 'Label', initialValue: 'Foo'),
flavor: context.knobs.list(
label: 'Flavor',
options: ZetaWidgetStatus.values,
labelBuilder: (v) => v.name,
),
size: context.knobs.list(
label: 'Size',
options: ZetaWidgetSize.values,
labelBuilder: (v) => v.name,
),
rounded: context.knobs.boolean(label: 'Rounded', initialValue: true),
onTap: context.knobs.boolean(label: 'onTap enabled', initialValue: true)
? () {}
: null,
);
}
Count and naming
All variants are explored through the knobs panel. Add a named use case only when a variant cannot be expressed through knobs — for example, a use case requiring specific child widgets or a complex composed state.
Never create one use case per flavor or per size — that is what knobs are for.
Keep names short: WithLeadingIcon, Disabled, WithActions.
Storybook serves as both an interactive development sandbox and published documentation at design.zebra.com. Just adding a story is not enough - ensure that the documentation is thorough and complete, and that all properties, events, slots, and css properties are documented.
What is auto-generated
Setting tags: ["autodocs"] causes Storybook to generate a Docs page from the component's source. Keep the JSDoc accurate and complete — it is the documentation:
| Source | Generated as |
|---|---|
| Class JSDoc description | Component description on the Docs page |
@property decorators + JSDoc comments | Props table (type, default, description) |
@slot JSDoc tags | Slots table |
@cssproperty JSDoc tags | CSS custom properties table |
@event JSDoc tags | Events table |
@part JSDoc tags | Parts table |
argTypes in story meta | Controls panel |
parameters.design.url | Figma design panel |
yarn analyze after changing propertiesThe props table is built from the custom elements manifest. If you add or remove a @property, run yarn analyze before opening a PR — otherwise the Docs page will be out of date.
Standard template
import type { Meta, StoryObj } from "@storybook/web-components";
import { html } from "lit";
import { fn } from "@storybook/test";
import { ZetaIconNameList } from "@zebra-fed/zeta-icons";
import { spreadGenerator } from "../../utils.js";
import { ZetaFoo } from "../../../components/foo/foo.js";
import "../../../components/foo/foo.js";
const spread = spreadGenerator(ZetaFoo);
const meta: Meta<ZetaFoo> = {
component: "zeta-foo",
title: "Components/Foo",
tags: ["autodocs"],
args: {
disabled: false,
rounded: true,
slot: "Label text",
},
argTypes: {
flavor: {
options: [
"primary",
"positive",
"negative",
"outline",
"outline-subtle",
"text",
"subtle",
],
control: { type: "select" },
},
size: {
options: ["small", "medium", "large"],
control: { type: "select" },
},
onchange: { action: "change" },
},
parameters: {
design: {
url: "https://www.figma.com/file/JesXQFLaPJLc1BdBM4sisI/...",
},
status: { type: "ready" },
},
};
export default meta;
export const Foo: StoryObj<ZetaFoo> = {
render: ({ slot, ...args }) =>
html`<zeta-foo ${spread(args)}>${slot}</zeta-foo>`,
};
spreadGenerator inspects the component's elementProperties at runtime and maps each arg to the correct Lit binding automatically — you do not write attribute bindings manually.
Count and naming
All variants are explored through the controls panel. Add a named story only when a variant cannot be expressed through args — for example, a story requiring specific slotted children or a complex composed state.
Never create one story per flavor or per size — that is what controls are for.
Keep names short: WithLabel, WithLeadingIcon, Disabled.
Storybook status values
| Value | Meaning |
|---|---|
"ready" | Matches Figma, tested, accessible — safe for production |
"designPending" | Design requires updates |
"needsAttention" | Component requires updates — do not use |