Overview

delegates rendering of a block to a plain JavaScript function znai creates a DOM node and hands your function the DOM node to render into the parameters from markdown as a so rendering can react to light dark theme switches themeBox my custom content box custom value See the sample function at the end of this page include javascript function args themeObservable include javascript function themeBox label my custom content box customKey custom value

Registering A Function

Attach your function to under the name you want to reference and load the script via window extensions json function window themeBox function node args themeObservable draw inside `node` read initial theme via `themeObservable current` subscribe to updates via `themeObservable subscribe listener `

Function Signature

Your function receives three arguments the parent to append content to the parameters passed from markdown Framework level keys are handled by znai and not forwarded live access to the current znai theme The function may return a cleanup function znai calls it when the block is removed or re rendered dispose timers external listeners or other resources here The sample function below returns a cleanup that logs to the browser console Open DevTools then navigate away from this page every rendered above is unmounted and its cleanup runs node div args title wide className anchorId height themeObservable current light | dark subscribe listener listener is called with the new theme name on every change return function cleanup console log themeBox cleanup block removed from the page themeBox

Theme Toggle

themeBox Switch the theme to see me update demo theme Toggle the theme using the switcher in the bottom left corner and watch the custom content restyle The hookup is one line themeObservable subscribe applyTheme

Title

Pass to render a title bar above the block znai owns the title via its shared container so your function never sees it themeBox theme aware box rendered inside a titled container title include javascript function themeBox title theme aware box message rendered inside a titled container

Wide

Pass to span the full page width matching wide images and iframes themeBox wide theme aware box true this block breaks out of the single column width and spans edge to edge of the page container giving long values plenty of horizontal room to stretch before they need to wrap onto a second line wide demo edge to edge theme 1024 42 0 003 wide true include javascript function themeBox title wide theme aware box wide true note this block breaks out of the single column width and spans edge to edge of the page container giving long values plenty of horizontal room to stretch before they need to wrap onto a second line tags wide demo edge to edge theme metrics requests 1024 latency_ms 42 error_rate 0 003

Height

By default the block grows to fit whatever the function renders into it Pass to pin the block to a fixed size content past it scrolls inside the viewport znai gives the function accepts either a number treated as pixels or any CSS length string like or The function below appends one row per event Without all twelve rows render and the block grows to fit them activityFeed deploys 09 14 build started commit a31f9b on main 09 17 tests passed 248 248 green 09 18 image pushed registry io web@sha256 c2 09 19 deploy started rolling out to canary 09 21 canary healthy p99 42ms error rate 0 0% 09 24 promoted 100% of fleet now on a31f9b 09 31 alert fired latency spike on shard 4 09 33 shard restarted shard 4 back to baseline 09 40 config reload feature flag billing v2 on 09 47 backfill queued 1 2M rows over 6 batches 09 58 backfill complete elapsed 11m02s 10 05 deploy started rolling out to prod eu Add and the same twelve events scroll inside a fixed size box instead activityFeed deploys 220 09 14 build started commit a31f9b on main 09 17 tests passed 248 248 green 09 18 image pushed registry io web@sha256 c2 09 19 deploy started rolling out to canary 09 21 canary healthy p99 42ms error rate 0 0% 09 24 promoted 100% of fleet now on a31f9b 09 31 alert fired latency spike on shard 4 09 33 shard restarted shard 4 back to baseline 09 40 config reload feature flag billing v2 on 09 47 backfill queued 1 2M rows over 6 batches 09 58 backfill complete elapsed 11m02s 10 05 deploy started rolling out to prod eu height height 320px 30vh activityFeed height include javascript function activityFeed title deploys events time 09 14 action build started detail commit a31f9b on main time 09 17 action tests passed detail 248 248 green height include javascript function activityFeed title deploys height 220 events * same twelve events *

Styling With A Class Name

Pass to attach an arbitrary class to the parent node znai creates Use it to decorate the wrapper without touching the function themeBox highlighted by an outer border theme box with border The dashed outline comes from the class on the outer wrapper the box itself is untouched className include javascript function themeBox label highlighted by an outer border className theme box with border theme box with border padding 6px border 2px dashed var znai color green border radius 6px theme box box sizing border box width 100% padding 12px 16px border 1px solid var znai snippets outer border color #dedede border left 4px solid var znai color blue border radius 4px background color var znai snippets title background color #efeff1 color var znai regular text color font family var znai regular font family theme box theme dark border left color var znai color yellow theme box title color var znai section title color font weight 600 font size 0 95rem margin bottom 8px theme box list display grid grid template columns auto 1fr column gap 12px row gap 4px font family var znai code font family monospace font size 0 9rem theme box empty font style italic color var znai regular text light color theme box key color var znai brand primary color font weight 600 theme box value color var znai regular text color word break break word white space pre wrap theme box current theme font size 0 8rem margin top 10px color var znai regular text light color

Search

Values passed via flow into znai s local search Searching for any word inside the parameters surfaces the page and the rendered block args

Sample Function

The function below powers the examples on this page It reads the initial theme and subscribes to future changes * * custom javascript global function to render custom content within znai * generated guides * * renders a panel that lists every argument passed via the plugin as * a key value row reacts to znai theme switches via the theme observable * to toggle a `theme dark` class that drives the accent color via CSS * function function formatValue value if value null || value undefined return String value if typeof value object return JSON stringify value return String value function createElement tagName className textContent var el document createElement tagName el className className if textContent undefined el textContent textContent return el window themeBox function node args themeObservable var box createElement div theme box var titleEl createElement div theme box title args passed to the function var list createElement div theme box list var themeEl createElement div theme box current theme var argKeys Object keys args if argKeys length 0 list appendChild createElement div theme box empty no args passed else argKeys forEach function key list appendChild createElement div theme box key key list appendChild createElement div theme box value formatValue args key box appendChild titleEl box appendChild list box appendChild themeEl node appendChild box function applyTheme themeName box classList toggle theme dark themeName dark themeEl textContent current theme themeName applyTheme themeObservable current themeObservable subscribe applyTheme return function cleanup console log themeBox cleanup block removed from the page * * sample plugin showing a list of rows that grows to fit its content * * the parent node sized by znai `height` arg is what constrains us when * unset the feed renders all rows tall enough to show them all when set * the same content scrolls inside the fixed viewport znai gave us * function function createElement tagName className textContent var el document createElement tagName el className className if textContent undefined el textContent textContent return el function buildRow event var row createElement div activity feed row row appendChild createElement span activity feed time event time || row appendChild createElement span activity feed action event action || row appendChild createElement span activity feed detail event detail || return row window activityFeed function node args themeObservable var events Array isArray args events args events var feed createElement div activity feed events forEach function event feed appendChild buildRow event node appendChild feed function applyTheme themeName feed classList toggle activity feed dark themeName dark applyTheme themeObservable current themeObservable subscribe applyTheme