Skip to content

Web Previewer ​

Every ArkTS example in these docs is read by a small parser and rendered with Vue components that imitate SparkUI. It cannot reproduce ArkUI 100%, but sizes, radii, colour tokens and interactions are aligned as closely as possible.

How it works ​

  1. Parse — docs/.vitepress/theme/previewer/parser.js turns the code into a syntax tree. A statement it cannot read becomes an error node and parsing resumes on the next line, so one odd line never breaks the whole preview.
  2. Evaluate — interp.js evaluates expressions. this.x resolves against the demo state (initial values of the gallery page's @Local fields are extracted automatically); this.theme.colors.* resolves to CSS variables.
  3. Render — runtime.js turns every component call into a descriptor and the Vue components in components.js render it. Components without an imitation render as a labelled placeholder box, with their children still rendered inside.
  4. Theme — colour tokens (including the status colours --success / --warning / --info) are generated by the build script from library/.../Presets.ets (.ark-theme.ark-preset-*, .ark-accent-*) and icon paths from LucideIcons.ets, so they cannot drift from the library. The imitations read the D13 component tokens as var(--<component>-<property>, <recipe>): a snippet's SparkUI.themes.setVariable / loadString / toggleDark applies to its own preview, and a tokens: { … } param becomes inline custom properties.
  5. Data — library classes the snippets construct (new SparkChartSeries(…), new SparkShellNavItem(…), new SparkTopbarAction(…) …) are read from the library sources and run as plain objects; the gallery page's constants (MONTHS, MAILS …) and getters (get mail()) are available to its snippets.

Supported syntax subset ​

SyntaxExample
Component calls with object-literal argsSButton({ text: 'Save', variant: 'outline' })
Trailing-closure childrenColumn({ space: 8 }) { Text('a') }
Chained attributes.width('100%').padding({ left: 12 }).fontColor(...)
Literalsstrings, template strings, numbers, booleans, null / undefined, arrays, objects, regexes
Expressionsmember access, calls, new, unary / binary / ternary, assignment, ++ / --, as casts, ! non-null
Two-way bindingchecked: this.on!! — interactions write back to the demo state
Control flowif / else, ForEach(arr, (item, i) => { ... }), const / let
Structs@Entry @ComponentV2 struct X { @Local v = 1; build() { ... } }; @Builder methods via this.xxx()
Events.onClick(() => { this.count++ }), onCheckedChange: (v) => { this.x = v }
EnumsFlexAlign.Center, HorizontalAlign.Start, Color.Red, FontWeight.Medium …

Imitated components ​

  • ArkUI basics: Column, Row, Flex, Stack, Text, Span, Button, Image, Divider, Blank, Scroll, List / ListItem, Grid / GridItem, Toggle, TextInput, TextArea, Progress, LoadingProgress, Circle, Rect…
  • SparkUI: Button, Badge, the Card family, Input, Textarea, Label, Switch, Checkbox, RadioGroup, Slider, Progress (linear / circle / gauge), Tabs, Accordion, Collapsible, Toggle, ToggleGroup, ButtonGroup, Alert, Avatar / AvatarGroup, Separator, Skeleton, Spinner, Kbd, typography, Empty, Item, Breadcrumb, Pagination, Field, Table, AspectRatio, ScrollArea, NumberField, PinInput, TagsInput, InputGroup, Stepper, Calendar / DatePicker (simplified), SGrid / SColumns / SFlow / SStack / SRow / SPage;
  • Charts (laid out with a port of ChartMath.ets: nice ticks, band / point scales, diverging stacks, monotone / step curves, rounded bars, label thinning): SLineChart, SAreaChart (stacked, gradient), SBarChart (grouped, stacked, horizontal, negative values), SPieChart / SDonutChart (centre label, active slice grows, pad angle), SRadialChart (track, rounded ends, partial sweep), SRadarChart (polygon / circle grid, dots, outline), SSparkline, SChartContainer (shared legend, empty state). Hover shows the crosshair or band cursor and the tooltip card, legend entries toggle series, shapes draw in with CSS animations;
  • Blocks (breakpoint-free: each block measures its preview container with a ResizeObserver and applies the policies and numbers of BlocksLogic.ets): SSidebarProvider + the SSidebar family (docked / icon rail / off-canvas, variants sidebar / floating / inset, active item, a sheet when the expanded sidebar no longer fits next to minInsetWidth), STopbar (sidebar trigger or back, title / subtitle, actions, condensed below 520 px with search behind an icon), SAppShell, SListDetail (side by side vs push with back), SSupportingPane (beside / below / bottom sheet + trigger), SDashboardGrid / SDashboardTile (spans clamped to the column count);
  • Overlays: Dialog, AlertDialog, Sheet, Drawer, Popover, Tooltip, HoverCard, DropdownMenu, ContextMenu (right click), Menubar, Select, Combobox, Command / CommandDialog, Toast (SparkToast.show);
  • Gallery helpers (Brand, UserRow, MailRow …) are not imitated: the previews render the gallery's real demo bodies together with the helper structs they use.

Code only. Examples the web cannot reproduce faithfully show only their code, without a preview: the Transition page (pure animation — the previewer does not animate) and the Title Bar page (window chrome that only exists in a HarmonyOS free window). The list lives in CODE_ONLY in docs/scripts/lib/pages-config.mjs.

npm run test:previewer renders every previewed gallery demo, lists the components still shown as placeholders and reports the code-only demos it skips. npm run docs:gen also audits the structure of every generated page.

Known gaps ​

  • Code highlighting in SCodeBlock is plain text.
  • Components called by a snippet that have no source and no imitation (your own StatCard(...), or code-only components such as STitleBar and STransition) render as placeholders.
  • There is no ArkUI layout engine: CSS flex / grid approximate it. Common attributes (layoutWeight, constraintSize, alignment…) are mapped; complex RelativeContainer rules, @Styles, AttributeModifier and animation parameters are ignored. Charts and blocks animate with CSS (draw-in, sweep, slide) rather than morphing between shapes.
  • Runtime machinery such as SparkContext / @Consumer is covered only for the common cases (this.theme; SparkUI.layout reports a fixed wide + pointer environment, while the blocks follow their measured width). Custom layoutPolicy functions run; controllers passed as controller: do not.
  • Snippet identifiers that are not declared in the snippet (config, rows) fall back to the gallery page's constants or to the shadcn sample data.
  • vp / fp units map 1:1 to CSS px.

MIT Licensed