Skip to main content

Release notes *2.6.7*

· 4 min read

The latest release introduces enhanced formatting features, including support for indexed expressions and improved Image3D rendering using maximum intensity projection. The REST API has been added to enable broader functionality for developers. Additionally, the integration of the WebUI Framework with WLX enables building complex applications directly within the notebook environment.

Download original notebook

const balloonContainer = document.getElementById("balloon-container");

function random(num) {
  return Math.floor(Math.random() * num);
}

function getRandomStyles() {
  var r = random(255);
  var g = random(255);
  var b = random(255);
  var mt = random(200);
  var ml = random(50);
  var dur = random(5) + 5;
  return `
  background-color: rgba(${r},${g},${b},0.7);
  color: rgba(${r},${g},${b},0.7); 
  box-shadow: inset -7px -3px 10px rgba(${r - 10},${g - 10},${b - 10},0.7);
  margin: ${mt}px 0 0 ${ml}px;
  animation: float ${dur}s ease-in infinite
  `;
}

function createBalloons(num) {
  for (var i = num; i > 0; i--) {
    var balloon = document.createElement("div");
    balloon.className = "balloon";
    balloon.style.cssText = getRandomStyles();
    balloonContainer.append(balloon);
  }
}

function removeBalloons() {
  balloonContainer.style.opacity = 0;
  setTimeout(() => {
    balloonContainer.remove()
  }, 500)
}

createBalloons(10);
setTimeout(removeBalloons, 15000);

return '';

Markdown

Admonitions

Make admonitions like in Docusaurus (Facebook) using directives

.md

:::tip
Use admonitions
:::

:::custom
Text text
:::
tip

Use admonitions

Text text

Supported types: info, warning, tip, todo, while any other combination will be styled as info.

TODO list

There is a special type of admonition, which also adds a live counter to the right-top corner of the notebook

  • Task 1
  • Task 2

Bookmarks

This is a special keyword in markdown editor, which adds a bookmark on a page. It also appears in the top-right corner, by clicking on it you will be directed to the marked place on the page

.md

@bookmark

@bookmark

Iframe API

Want to embed WLJS interface to your app? The good old iframe tag is a way to go.

REST API

API is provided by a core extension wljs-api. All communication is done via HTTP POST request in JSON format. In a nutshell it allows to

  • create transactions to evaluate Wolfram, WLX, any other support languages (see Cell Types) code and get back the result
  • control evaluation kernels
  • fetch Frontend Objects used for 3D, 2D graphics
  • fetch extensions, assets

In principle public REST API is enough to write your own small notebook interface with full support of all available cell types, 3D graphics, sound and etc.

For example

.js
const result = document.createElement('span');

fetch('http://127.0.0.1:20560/api/kernels/list/', {
  method:'POST'
}).then((res) => {
  res.json().then((r) => {
    result.innerText = JSON.stringify(r);
  }); 
})  

return result;

const dom = document.createElement('span');

fetch('http://127.0.0.1:20560/api/kernels/list/', {
  method:'POST'
}).then((res) => {
  res.json().then((r) => {
    dom.innerText = JSON.stringify(r);
  }); 
})  

return dom;

EventHandler update

There are some minor changes. Attaching an event listener to any Graphics expression should feel more natural. For example

pc = {0.,0.};
EventHandler[
  Plot[x, {x,0,1}, Epilog->{Disk[pc // Offload, 0.1]}]
, {"mousemove" -> ((pc = #)&)}]

Alternative way is still valid

Plot[x, {x,0,1}, Epilog->{
  Disk[pc // Offload, 0.1],
  EventHandler[Null, {"mousemove" -> ((pc = #)&)}]
}]

Here is forces event listener to attach to the nearest parent, which emits events. In this case, it is Graphics produced by Plot.

More formatting

We added the support for more formatting expressions

Indexed

It represents the component of expr with index i and formats as follows

Indexed[x, 3]
(*TB[*)Indexed[(*|*)x(*|*), {(*|*)3(*|*)}](*|*)(*1:eJxTTMoPSmMAgmIuIOGZl5JakZrilF8BAECTBhI=*)(*]TB*)

Or multiple

Indexed[x, {3, 5}]
(*TB[*)Indexed[(*|*)x(*|*), {(*|*)3,5(*|*)}](*|*)(*1:eJxTTMoPSmMAgmIuIOGZl5JakZrilF8BAECTBhI=*)(*]TB*)

Better support for Image3D

We implemented a shader version of Image3D using maximum intensity projection (MIP).

It still lacks some options and can only work with grayscale 3D images

Image3D[
  ExampleData[{"TestImage3D","CThead"}], 
  BoxRatios->{1,1,1}, 
  ColorFunction->"GrayLevelOpacity"
]
(*VB[*)(FrontEndRef["3e31314e-aee1-4d05-af77-65e516b83005"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKG6caGxobmqTqJqamGuqapBiY6iammZvrmpmmmhqaJVkYGxiYAgCB5BU4"*)(*]VB*)

WebUI Framework and WLX

WLJS Notebook is built on the WLX and WebUI technology stack. Now it is fully usable even inside the notebook and does not conflict with the existing WebUI from the master Kernel.

Want to build a more complex application? A fully functional sidebar? Here we go!

<<JerryI`WLX`Importer`
<<JerryI`WLX`WebUI`

Now disable caching and load a component

JerryI`WLX`Importer`Private`CacheControl[False];
SidebarBody = ImportComponent["attachments/Sidebar/Body.wlx"];

Use it as if it was a normal WL function

.wlx
event = CreateUUID[];
EventHandler[event, {
  filename_String :> (Print[URLDecode[filename]];&)
}];

SidebarBody["Path"->NotebookDirectory[], "Channel"->event]
<nav class="flex flex-1 flex-col" style="-webkit-app-region:none"><ul role="list" class="flex flex-1 flex-col gap-y-7 p-0"><li class="list-none"><ul class="p-0 -mx-2 space-y-0 pl-0"><li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="bfc310c1-8882-4a3c-b8c8-cfeae1a1096a" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.0.wln</button><script type="module"> const el = document.getElementById('bfc310c1-8882-4a3c-b8c8-cfeae1a1096a');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.0.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="9142bee9-8680-4b58-a089-ec4e761d9736" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.2.wln</button><script type="module"> const el = document.getElementById('9142bee9-8680-4b58-a089-ec4e761d9736');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.2.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="3776c0fa-a914-4aa3-a34d-794cfafded7c" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.3.wln</button><script type="module"> const el = document.getElementById('3776c0fa-a914-4aa3-a34d-794cfafded7c');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.3.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="77caf817-e2bd-4e45-9b21-ba43e44b0a41" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.4.wln</button><script type="module"> const el = document.getElementById('77caf817-e2bd-4e45-9b21-ba43e44b0a41');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.4.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="60c6182b-d9b4-4794-90c3-f81b4c4fb385" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.6.wln</button><script type="module"> const el = document.getElementById('60c6182b-d9b4-4794-90c3-f81b4c4fb385');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.6.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="c867458f-4ee3-4e51-8c85-165e4366b3bc" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.7.wln</button><script type="module"> const el = document.getElementById('c867458f-4ee3-4e51-8c85-165e4366b3bc');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.7.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="b66d56e3-6950-4c57-bb64-02a81ff8e033" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.5.9.wln</button><script type="module"> const el = document.getElementById('b66d56e3-6950-4c57-bb64-02a81ff8e033');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.5.9.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="85bc22dd-d455-4843-b3a6-022b152fbbaf" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.6.1.wln</button><script type="module"> const el = document.getElementById('85bc22dd-d455-4843-b3a6-022b152fbbaf');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.6.1.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="fd2d3e79-a572-44b1-a140-e415343fa05a" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.6.2.wln</button><script type="module"> const el = document.getElementById('fd2d3e79-a572-44b1-a140-e415343fa05a');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.6.2.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="27ee74ee-7fa8-41ca-ac6f-003fe87a1620" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.6.3.wln</button><script type="module"> const el = document.getElementById('27ee74ee-7fa8-41ca-ac6f-003fe87a1620');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.6.3.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="cbd73e5d-6a28-4e17-8054-71d45f3ea244" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.6.4.wln</button><script type="module"> const el = document.getElementById('cbd73e5d-6a28-4e17-8054-71d45f3ea244');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.6.4.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="f50259dc-d20b-4ff1-9d0b-e943ddda412d" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.6.5.wln</button><script type="module"> const el = document.getElementById('f50259dc-d20b-4ff1-9d0b-e943ddda412d');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.6.5.wln');
        });</script></div></li>
<li class="list-none"><div class=" pb-0.5 pt-0.5 text-gray-700 dark:text-gray-400 flex flex-start items-center pl-7 gap-x-1 rounded-md" style="position: relative"><div ><svg class="w-4 h-5 text-gray-800" viewBox="2 0 20 24" stroke="currentColor" fill="rgb(153 246 228)" stroke-width="1"><path d="M8 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H8M8 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H8M8 4V20M12 11H16M12 8H16"></path></svg></div><button id="44136947-71ec-4b0b-9648-3e1b58cd75bf" class="block rounded-md py-0 pr-0 text-sm leading-tight">2.6.6.wln</button><script type="module"> const el = document.getElementById('44136947-71ec-4b0b-9648-3e1b58cd75bf');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('ef5a58cc-5768-4d4b-8da0-190995165ec6', '"'+el.value+'"', '%2Fusers%2Fkirill%2FGithub%2Fwljs-demos-archive%2FDemos%2FRelease%20notes%2F2.6.6.wln');
        });</script></div></li>
<li class="list-none"><div style="position:relative"><div class="rounded-md"><button id="040b5009-5e3d-4eae-ac66-c710cd3f6e79" class=" flex items-center w-full text-left rounded-md pb-0.5 pt-0.5 pl-1 gap-x-1 text-sm text-gray-700 dark:text-gray-400" type="button" aria-controls="sub-menu-1" aria-expanded="false"><svg id="svg-040b5009-5e3d-4eae-ac66-c710cd3f6e79" class="text-gray-800 dark:text-gray-400 h-5 w-5 shrink-0" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd"/></svg><svg class="h-4 w-4 shrink-0 text-gray-800 dark:text-gray-400 group-hover:text-indigo-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"/></svg>attachments</button></div><script type="module"> const el = document.getElementById('040b5009-5e3d-4eae-ac66-c710cd3f6e79');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('040b5009-5e3d-4eae-ac66-c710cd3f6e79', '"'+el.value+'"', 'Button');
        });</script><script type="module"> new UIJSScript({target: async function() { const button = document.getElementById('svg-040b5009-5e3d-4eae-ac66-c710cd3f6e79');
        this.on('Load', (data) => {
          button.classList.add('rotate-90', 'text-gray-500');
        });

        this.on('Show', (data) => {
          button.classList.add('rotate-90', 'text-gray-500');
        });        

        this.on('Hide', (data) => {
          button.classList.remove('rotate-90', 'text-gray-500');
        });}, uid: 'b5f99252-1b84-4c52-b3ef-36b5710a4cc5'})</script><div id="bffc0217-43cc-4e79-b728-b33e80e9404d" class=""></div></div></li>
<li class="list-none"><div style="position:relative"><div class="rounded-md"><button id="b89fee29-662a-4cad-a0cc-96f84d90ffc2" class=" flex items-center w-full text-left rounded-md pb-0.5 pt-0.5 pl-1 gap-x-1 text-sm text-gray-700 dark:text-gray-400" type="button" aria-controls="sub-menu-1" aria-expanded="false"><svg id="svg-b89fee29-662a-4cad-a0cc-96f84d90ffc2" class="text-gray-800 dark:text-gray-400 h-5 w-5 shrink-0" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd"/></svg><svg class="h-4 w-4 shrink-0 text-gray-800 dark:text-gray-400 group-hover:text-indigo-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"/></svg>.iconized</button></div><script type="module"> const el = document.getElementById('b89fee29-662a-4cad-a0cc-96f84d90ffc2');
        el.addEventListener('click', function (e) {
            server.kernel.emitt('b89fee29-662a-4cad-a0cc-96f84d90ffc2', '"'+el.value+'"', 'Button');
        });</script><script type="module"> new UIJSScript({target: async function() { const button = document.getElementById('svg-b89fee29-662a-4cad-a0cc-96f84d90ffc2');
        this.on('Load', (data) => {
          button.classList.add('rotate-90', 'text-gray-500');
        });

        this.on('Show', (data) => {
          button.classList.add('rotate-90', 'text-gray-500');
        });        

        this.on('Hide', (data) => {
          button.classList.remove('rotate-90', 'text-gray-500');
        });}, uid: '9b02f518-3db0-4da2-893a-bd5d2928341c'})</script><div id="1490b407-2909-4819-bea7-b464c64c1a53" class=""></div></div></li></ul></li></ul></nav>

It does support fully lazy-loading and can work on multiple levels. It is exacly the same component used in WLJS Notebook interface.

Ballon animation by Jemima (codepen)