
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
More on VanJS:
π Feedback and contribution are welcome and greatly appreciated!
The library is published as NPM package vanjs-ui. Run the following command to install the package:
npm install vanjs-ui
To use the NPM package, add this line to your script:
import { <components you want to import> } from "vanjs-ui"
Alternatively, you can import VanUI from CDN via a <script type="text/javascript"> tag:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vanjs-ui@0.11.13/dist/van-ui.nomodule.min.js"></script>
https://cdn.jsdelivr.net/npm/vanjs-ui@0.11.13/dist/van-ui.nomodule.js can be used for the non-minified version.
Note that: VanJS needs to be imported via a <script type="text/javascript"> tag for VanUI to work properly.
Try on jsfiddle: Modal, MessageBoard.
To get TypeScript support for <script> tag integration, download van-ui.d.ts and add the code like following at the top of your .ts file:
import type { Modal as ModalType } from "./van-ui.d.ts"
declare const Modal: typeof ModalType
The following components have been implemented so far:
Author: @Hunter-Gu
Await is a utility component that helps you build UI components based on asynchronous data (i.e.: a JavaScript Promise object).
Await({
value, // A `Promise` object for asynchronous data
container, // The container of the result. Default `div`
Loading, // What to render when the data is being loaded
Error, // What to render when error occurs
}, children) => <The created UI element>
The children parameter (type: (data: T) => ValidChildDomValue) is a function that takes the resolved data as input and returns a valid child DOM value (Node, primitives, null or undefined), used to indicate what to render after the data is loaded.
Preview with CodeSandbox.
Example 1 (fetching the number of GitHub stars):
const Example1 = () => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
const fetchWithDelay = (url: string, waitMs: number) =>
sleep(waitMs).then(() => fetch(url)).then(r => r.json())
const fetchStar = () =>
fetchWithDelay("https://api.github.com/repos/vanjs-org/van", 1000)
.then(data => data.stargazers_count)
const data = van.state(fetchStar())
return [
() => h2(
"GitHub Stars: ",
Await({
value: data.val, container: span,
Loading: () => "π Loading...",
Error: () => "π Request failed.",
}, starNumber => `βοΈ ${starNumber}!`)
),
() => Await({
value: data.val,
Loading: () => '',
}, () => button({onclick: () => (data.val = fetchStar())}, "Refetch")),
]
}
Example 2 (parallel Await):
const Example2 = () => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
const loadNumber = () =>
sleep(Math.random() * 1000).then(() => Math.floor(Math.random() * 10))
const a = van.state(loadNumber()), b = van.state(loadNumber())
return [
h2("Parallel Await"),
() => {
const sum = van.derive(() => Promise.all([a.val, b.val]).then(([a, b]) => a + b))
return Await({
value: sum.val,
Loading: () => div(
Await({value: a.val, Loading: () => "π Loading a..."}, () => "Done"),
Await({value: b.val, Loading: () => "π Loading b..."}, () => "Done"),
),
}, sum => "a + b = " + sum)
},
p(button({onclick: () => (a.val = loadNumber(), b.val = loadNumber())}, "Reload")),
]
}
value: Type Promise. Required. The asynchronous data that the result UI element is based on.container: Type TagFunction<Element>. Default div (van.tags.div). Optional. The type of the wrapper HTML element for the result.Loading: Type () => ValidChildDomValue. Optional. If specified, indicates what to render when the asynchronous data is being loaded.Error: Type (reason: Error) => ValidChildDomValue. Optional. If specified, indicates what to render when error occurs while fetching the asynchronous data.Creates a modal window on top of the current page.
Modal({...props}, ...children) => <The created modal window>
Preview with CodeSandbox.
Example 1:
const closed = van.state(false)
van.add(document.body, Modal({closed},
p("Hello, World!"),
div({style: "display: flex; justify-content: center;"},
button({onclick: () => closed.val = true}, "Ok"),
),
))
Example 2:
const closed = van.state(false)
const formDom = form(
div(input({type: "radio", name: "lang", value: "Zig", checked: true}), "Zig"),
div(input({type: "radio", name: "lang", value: "Rust"}), "Rust"),
div(input({type: "radio", name: "lang", value: "Kotlin"}), "Kotlin"),
div(input({type: "radio", name: "lang", value: "TypeScript"}), "TypeScript"),
div(input({type: "radio", name: "lang", value: "JavaScript"}), "JavaScript"),
)
const onOk = () => {
const lang = (<HTMLInputElement>formDom.querySelector("input:checked")).value
alert(lang + " is a good language π")
closed.val = true
}
van.add(document.body, Modal({closed, blurBackground: true, clickBackgroundToClose: true},
p("What's your favorite programming language?"),
formDom,
p({style: "display: flex; justify-content: space-evenly;"},
button({onclick: onOk}, "Ok"),
button({onclick: () => closed.val = true}, "Cancel"),
)
))
closed: Type State<boolean>. Required. A State object used to close the created modal window. Basically, setting closed.val = true will close the created modal window. You can also subscribe the closing event of the modal window via van.derive.backgroundColor: Type string. Default "rgba(0,0,0,.5)". Optional. The color of the background overlay when the modal is activated.blurBackground: Type boolean. Default false. Optional. Whether to blur the background.clickBackgroundToClose: Type boolean. Default false. Optional. If true, clicking the background will close the created modal.backgroundClass: Type string. Default "". Optional. The class attribute of the background overlay. You can specify multiple CSS classes separated by " ".backgroundStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the background overlay.modalClass: Type string. Default "". Optional. The class attribute of the created modal element. You can specify multiple CSS classes separated by " ".modalStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the created modal element.Creates a tab-view for tabs specified by the user.
Tabs({...props}, tabContents) => <The created tab-view>
The tabContents parameter is an object whose keys are the titles of the tabs and values (type: ChildDom) are the DOM element(s) for the tab contents.
Preview with CodeSandbox.
van.add(document.body, Tabs(
{
style: "max-width: 500px;",
tabButtonActiveColor: "white",
tabButtonBorderStyle: "none",
tabButtonRowStyleOverrides: {
"padding-left": "12px",
},
},
{
Home: p(
"Welcome to ", b("VanJS"), " - the smallest reactive UI framework in the world.",
),
"Getting Started": [
p("To install the ", b("VanJS"), " NPM package, run the line below:"),
pre(code("npm install vanjs-core")),
],
About: p(
"The author of ", b("VanJS"), " is ",
a({href: "https://github.com/Tao-VanJS"}, " Tao Xin"), "."
),
},
))
activeTab: Type State<string>. Optional. If specified, you can activate a tab via the specified State object with activeTab.val = "<tab title>", and subscribe to the changes of active tab via van.derive.activeTabDisplay: Type string. Default "block". Optional. The display CSS property for the content of the active tab.resultClass: Type string. Default "". Optional. The class attribute of the result DOM element. You can specify multiple CSS classes separated by " ".style: Type string. Default "". Optional. The style property of the result DOM element.tabButtonRowColor: Type string. Default "#f1f1f1". Optional. The background color of the container of tab buttons.tabButtonBorderStyle: Type string. Default 1px solid #000. Optional. The style of borders between tab buttons.tabButtonHoverColor: Type string. Default "#ddd". Optional. The color when the tab button is hovered.tabButtonActiveColor: Type string. Default "#ccc". Optional. The color of the tab button for the currently active tab.transitionSec: Type number. Default 0.3. Optional. The duration of the transition when tab buttons change color.tabButtonRowClass: Type string. Default "". Optional. The class attribute of the container of tab buttons. You can specify multiple CSS classes separated by " ".tabButtonRowStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the container of tab buttons.tabButtonClass: Type string. Default "". The class attribute of tab buttons. You can specify multiple CSS classes separated by " ".tabButtonStyleOverrides: Type Record<string, string | number>. Default {}. A property bag for the styles you want to override for tab buttons. You can specify multiple CSS classes separated by " ".tabContentClass: Type string. Default "". The class attribute of tab contents. You can specify multiple CSS classes separated by " ".tabContentStyleOverrides: Type Record<string, string | number>. Default {}. A property bag for the styles you want to override for tab contents.Creates a message board to show messages on the screen.
To create a message board:
const board = new MessageBoard({...props})
Then you can show messages with show method:
board.show({...props}) => <The created DOM node for the message, which is also appended to the message board>
Optionally, you can remove the DOM node of the message board with remove method:
board.remove()
Preview with CodeSandbox.
const board = new MessageBoard({top: "20px"})
const example1 = () => board.show({message: "Hi!", durationSec: 1})
const example2 = () => board.show(
{message: ["Welcome to ", a({href: "https://vanjs.org/", style: "color: #0099FF"}, "π¦VanJS"), "!"], closer: "β"})
const closed = van.state(false)
const example3 = () => {
closed.val = false
board.show({message: "Press ESC to close this message", closed})
}
document.addEventListener("keydown", e => e.key === "Escape" && (closed.val = true))
Message board properties:
top: Type string. Optional. The top CSS property of the message board.bottom: Type string. Optional. The bottom CSS property of the message board. Exactly one of top and bottom should be specified.backgroundColor: Type string. Default "#333D". Optional. The background color of the messages shown on the message board.fontColor: Type string. Default "white". Optional. The font color of the messages shown on the message board.fadeOutSec: Type number. Default 0.3. Optional. The duration of the fade out animation when messages are being closed.boardClass: Type string. Default "". Optional. The class attribute of the message board. You can specify multiple CSS classes separated by " ".boardStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the message board.messageClass: Type string. Default "". Optional. The class attribute of the message shown on the message board. You can specify multiple CSS classes separated by " ".messageStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the message shown on the message board.closerClass: Type string. Default "". Optional. The class attribute of the message closer. You can specify multiple CSS classes separated by " ".closerStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the message closer.Message properties:
message: Type ChildDom. Required. One ChildDom or multiple ChildDom as an Array for the message we want to show.closer: Type ChildDom. Optional. If specified, we will render a closer DOM node with one ChildDom or multiple ChildDoms as an Array which can be clicked to close the shown message.durationSec: Type number. Optional. If specified, the shown message will be automatically closed after durationSec seconds.closed: Type State<boolean>. Optional. If specified, the shown message can be closed via the closed State object with closed.val = true. You can also subscribe the closing event of the message via van.derive.Creates a tooltip above a DOM node which typically shows when the DOM node is being hovered.
Tooltip({...props}) => <The created tooltip element>
Preview with CodeSandbox.
const tooltip1Show = van.state(false)
const tooltip2Show = van.state(false)
const count = van.state(0)
const tooltip2Text = van.derive(() => `Count: ${count.val}`)
const tooltip3Show = van.state(false)
van.add(document.body,
button({
style: "position: relative;",
onmouseenter: () => tooltip1Show.val = true,
onmouseleave: () => tooltip1Show.val = false,
}, "Normal Tooltip", Tooltip({text: "Hi!", show: tooltip1Show})), " ",
button({
style: "position: relative;",
onmouseenter: () => tooltip2Show.val = true,
onmouseleave: () => tooltip2Show.val = false,
onclick: () => ++count.val
}, "Increment Counter", Tooltip({text: tooltip2Text, show: tooltip2Show})), " ",
button({
style: "position: relative;",
onmouseenter: () => tooltip3Show.val = true,
onmouseleave: () => tooltip3Show.val = false,
}, "Slow Fade-in", Tooltip({text: "Hi from the sloth!", show: tooltip3Show, fadeInSec: 5})),
)
Note that the lines:
{
style: "position: relative;",
onmouseenter: () => ...Show.val = true,
onmouseleave: () => ...Show.val = false,
}
are needed for the tooltip element to be shown properly.
text: Type string | State<string>. Required. The text shown in the tooltip. If a State object is specified, you can set the text with text.val = ....show: Type State<boolean>. Required. The State object to control whether to show the tooltip or not.width: Type string. Default "200px". Optional. The width of the tooltip.backgroundColor: Type string. Default "#333D". Optional. The background color of the tooltip.fontColor: Type string. Default: "white". Optional. The font color of the tooltip.fadeInSec: Type number. Default 0.3. Optional. The duration of the fade-in animation.tooltipClass: Type string. Default "". Optional. The class attribute of the tooltip. You can specify multiple CSS classes separated by " ".tooltipStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the tooltip.triangleClass: Type string. Default "". Optional. The class attribute of the triangle in the bottom. You can specify multiple CSS classes separated by " ".triangleStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the triangle in the bottom.Creates a toggle switch that can be turned on and off.
Toggle({...props}) => <The created toggle switch>
Preview with CodeSandbox.
van.add(document.body, Toggle({
on: true,
size: 2,
onColor: "#4CAF50"
}))
on: Type boolean | State<boolean>. Default false. Optional. A boolean or a boolean-typed State object to indicate the status of the toggle. If a State object is specified, you can turn on/off the toggle via the specified State object with on.val = <true|false>, and subscribe to the status change of the toggle via van.derive.size: Type number. Default 1. Optional. The size of the toggle. 1 means the height of the toggle is 1rem.cursor: Type string. Default pointer. Optional. The cursor CSS property of the toggle.ofColor: Type string. Default "#ccc". Optional. The color of the toggle when it's off.onColor: Type string. Default "#2196F3". Optional. The color of the toggle when it's on.circleColor: Type string. Default "white". Optional. The color of the toggling circle.toggleClass: Type string. Default "". Optional. The class attribute of the toggle. You can specify multiple CSS classes separated by " ".toggleStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the toggle.sliderClass: Type string. Default "". Optional. The class attribute of the slider. You can specify multiple CSS classes separated by " ".sliderStyleOverrides. Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the slider.circleClass. Type string. Default "". Optional. The class attribute of the toggling circle. You can specify multiple CSS classes separated by " ".circleStyleOverrides. Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the toggling circle.circleWhenOnStyleOverrides. Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the toggling circle. Typically this is used to override the transform CSS property if the dimensions of the toggle is overridden.Creates a group of button-shaped options where only one option can be selected. This is functionally similar to a radio group but with a different appearance.
OptionGroup({...props}, options) => <The created option group>
The options parameter is a string[] for all the options.
Preview with CodeSandbox.
const selected = van.state("")
const options = ["Water", "Coffee", "Juice"]
van.add(document.body,
p("What would you like to drink?"),
OptionGroup({selected}, options),
p(() => options.includes(selected.val) ?
span(b("You selected:"), " ", selected) : b("You haven't selected anything.")),
)
selected: Type State<string>. Required. A State object for the currently selected option. You can change the selected option with selected.val = <option string>, and subscribe to the selection change via van.derive.normalColor: Type string. Default "#e2eef7". Optional. The color of the option when it's not selected or hovered.hoverColor: Type string. Default "#c1d4e9". Optional. The color of the option when it's hovered.selectedColor: Type string. Default "#90b6d9". Optional. The color of the option when it's selected.selectedHoverColor: Type string. Default "#7fa5c8". Optional. The color of the option when it's selected and hovered.fontColor: Type string. Default "black". Optional. The font color of the options.transitionSec: Type number. Default 0.3. Optional. The duration of the transition when the options change color.optionGroupClass: Type string. Default "". Optional. The class attribute of the entire option group. You can specify multiple CSS classes separated by " ".optionGroupStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the entire option group.optionClass: Type string. Default "". Optional. The class attribute of the options. You can specify multiple CSS classes separated by " ".optionStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the options.Creates a banner element for the current container.
Banner({...props}, ...children) => <The created banner element>
Preview with CodeSandbox.
van.add(document.body,
h2("Sticky Banner"),
div({style: "width: 300px; height: 200px; overflow-y: auto; border: 1px solid #000;"},
Banner({sticky: true}, "πHello πΊοΈWorld"),
div({style: "padding: 0 10px"}, Array.from({length: 10}).map((_, i) => p("Line ", i))),
),
h2("Non-sticky Banner"),
div({style: "width: 300px; height: 200px; overflow-y: auto; border: 1px solid #000;"},
Banner({sticky: false}, "πHello ", a({href: "https://vanjs.org/"}, "π¦VanJS")),
div({style: "padding: 0 10px"}, Array.from({length: 10}).map((_, i) => p("Line ", i))),
),
)
backgroundColor: Type string. Default #fff1a8. Optional. The background color of the banner.fontColor: Type string. Default currentcolor. Optional. The font color of the banner.sticky: Type boolean. Default false. Optional. Whether the banner is sticky on the top.bannerClass: Type string. Default "". Optional. The class attribute of the created banner element. You can specify multiple CSS classes separated by " ".bannerStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the created banner element.Author: @Duffscs
Creates a movable and resizable floating window.
FloatingWindow({...props}, ...children) => <The created floating window>
Preview with CodeSandbox.
Window with custom close button:
const closed = van.state(false)
const width = van.state(300), height = van.state(220)
van.add(document.body, FloatingWindow(
{title: "Example Window 1", closed, width, height, closeCross: null},
div({style: "display: flex; flex-direction: column; justify-content: center;"},
p("Hello, World!"),
button({onclick: () => width.val *= 2}, "Double Width"),
button({onclick: () => height.val *= 2}, "Double Height"),
button({onclick: () => closed.val = true}, "Close Window"),
),
))
Window with integrated close button:
van.add(document.body, FloatingWindow(
{title: "Example Window 2", x: 150, y: 150, headerColor: "lightblue"},
div({style: "display: flex; justify-content: center;"},
p("This is another floating window!"),
),
))
Close button with custom appearance:
van.add(document.body, FloatingWindow(
{
title: "Example Window 3", x: 175, y: 175, closeCross: "β",
crossHoverStyleOverrides: {"background-color": "white"},
},
div({style: "display: flex; justify-content: center;"},
p("This is a floating window with custom cross button!"),
),
))
Window with Tabs:
const closed = van.state(false)
van.add(document.body, FloatingWindow(
{
closed, x: 200, y: 200, width: 500, height: 300,
childrenContainerStyleOverrides: { padding: 0 },
},
div(
span({
class: "vanui-window-cross",
style: "position: absolute; top: 8px; right: 8px;cursor: pointer;",
onclick: () => closed.val = true,
}, "Γ"),
Tabs(
{
style: "width: 100%;",
tabButtonActiveColor: "white",
tabButtonBorderStyle: "none",
tabButtonRowColor: "lightblue",
tabButtonRowStyleOverrides: {height: "2.5rem"},
tabButtonStyleOverrides: {height: "100%"},
},
{
Home: p(
"Welcome to ", b("VanJS"), " - the smallest reactive UI framework in the world.",
),
"Getting Started": [
p("To install the ", b("VanJS"), " NPM package, run the line below:"),
pre(code("npm install vanjs-core")),
],
About: p(
"The author of ", b("VanJS"), " is ",
a({href: "https://github.com/Tao-VanJS"}, " Tao Xin"), "."
),
},
)
)
))
Window without header or integrated close button:
const closed = van.state(false)
van.add(document.body, FloatingWindow(
{
closed, x: 300, y: 300, width: 500, height: 300,
windowStyleOverrides: {"background-color": "lightgray"},
childrenContainerStyleOverrides: {
display: "flex",
"align-items": "center",
"justify-content": "center",
height: "100%",
}
},
button({onclick: () => closed.val = true}, "Close Window"),
))
Window showing z-index:
const zIndex = van.state(1)
van.add(document.body, FloatingWindow(
{title: ["z-index: ", zIndex], x: 200, y: 200, width: 300, height: 100, zIndex},
))
Window with custom stacking:
const zIndex = van.state(1)
van.add(document.body, FloatingWindow(
{title: "Custom stacking", x: 300, y: 300, customStacking: true, zIndex},
div({style: "display: flex; justify-content: space-between;"},
button({onclick: () => zIndex.val++}, "+"),
p("z-index: ", zIndex),
button({onclick: () => zIndex.val--}, "-"),
),
div({style: "display: flex; justify-content: center;"},
button({onclick: () => zIndex.val = topMostZIndex()}, "Bring to Front"),
),
))
Non-movable window:
van.add(document.body, FloatingWindow(
{title: "Not Movable", disableMove: true},
div({style: "display: flex; justify-content: center;"},
p("This window is not movable!"),
),
))
Non-movable window without title:
const closed = van.state(false)
van.add(document.body, FloatingWindow(
{closed, x: 150, y: 150, disableMove: true},
div(
p("This window is not movable!"),
p({style: "display: flex; justify-content: center;"},
button({onclick: () => closed.val = true}, "Close")
),
),
))
Non-resizable window:
van.add(document.body, FloatingWindow(
{title: "Not Resizable", x: 200, y: 200, disableResize: true},
div(
p({style: "display: flex; justify-content: center;"}, "This window is not resizable!"),
),
))
z-index StackingBy default, the z-index CSS property of each window comes from the sequence: 1, 2, 3, .... Whenever a new window is created or is interacted with (onmousedown event is triggered), we assign the z-index property of the window to the next number in the sequence. This way, we are making sure that newly created or interacted windows are always brought to the front.
You can override the default stacking behavior by specifying {customStacking: true} in props. This way, you can manually control the z-index of the window via a VanJS state.
title: Type ChildDom. Optional. One ChildDom or multiple ChildDom as an Array for the title of the created window. If not specified, the window won't have a title.closed: Type State<boolean>. Optional. If specified, the created window can be closed via the closed State object with closed.val = true. You can also subscribe the closing event of the created window via van.derive.x: Type number | State<number>. Default 100. Optional. The x-coordinate of the created window, in pixels.y: Type number | State<number>. Default 100. Optional. The y-coordinate of the created window, in pixels.width: Type number | State<number>. Default 300. Optional. The width of the created window, in pixels.height: Type number | State<number>. Default 200. Optional. The height of the created window, in pixels.closeCross: Type ChildDom. Default "Γ". Optional. One ChildDom or multiple ChildDom as an Array for the close button of the created window. If its value is null, there won't be a close button. If title property is not specified, this property will be ignored and there won't be a close button.customStacking: type boolean. Default false. Optional. If true, default z-index stacking rule won't be triggered. Users are expected to manually set the z-index property of the created window via the State object for z-index property below.zIndex: type number | State<number>. Optional. If a State object is specified, you can use the State object to track the change of z-index property via van.derive. If customTracking is true, you can use this property to manually set the z-index property of the created window.disableMove: type boolean. Default false. Optional. If true, the created window can't be moved.disableResize: type boolean. Default false. Optional. If true, the created window can't be resized.headerColor: type string. Default "lightgray". Optional. The background color of the window header (title bar).windowClass: Type string. Default "". Optional. The class attribute of the created window. You can specify multiple CSS classes separated by " ".windowStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the created window.headerClass: Type string. Default "". Optional. The class attribute of the window header (title bar). You can specify multiple CSS classes separated by " ".headerStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the window header (title bar).childrenContainerClass: Type string. Default "". Optional. The class attribute of the container for children DOM nodes. You can specify multiple CSS classes separated by " ".childrenContainerStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the container of children DOM nodes.crossClass: Type string. Default "". Optional. The class attribute of the close button. You can specify multiple CSS classes separated by " ".crossStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the close button.crossHoverClass: Type string. Default "". Optional. The class attribute of the close button when it's hovered over. You can specify multiple CSS classes separated by " ".crossStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the close button when it's hovered over.Creates a Modal component that lets the user choose among given options, returns a Promise that resolves when user makes the choice (resolves to the chosen string), or cancels (resolves to null).
choose({...props}) => Promise<string | null>
Preview with CodeSandbox.
Example 1:
const choice = await choose({
label: "Choose a color:",
options: ["Red", "Green", "Blue"],
})
choice && van.add(document.body, div("You chose: ", b(choice)))
Example 2:
const choice = await choose({
label: "Choose a South American country:",
options: [
"π¦π· Argentina", "π§π΄ Bolivia", "π§π· Brazil", "π¨π± Chile", "π¨π΄ Colombia", "πͺπ¨ Ecuador",
"π¬πΎ Guyana", "π΅πΎ Paraguay", "π΅πͺ Peru", "πΈπ· Suriname", "πΊπΎ Uruguay", "π»πͺ Venezuela",
],
showTextFilter: true,
selectedColor: "blue",
cyclicalNav: true,
customModalProps: {
blurBackground: true,
modalStyleOverrides: {height: "300px"},
clickBackgroundToClose: true,
},
selectedStyleOverrides: {color: "white"},
})
choice && van.add(document.body, div("You chose: ", b(choice)))
label: Type ChildDom. Required. One ChildDom or multiple ChildDom as an Array for the label you want to show.options: Type string[]. Required. The options of the choice.showTextFilter: Type boolean. Default false. Optional. Whether to show a text filter for the options.selectedColor: Type string. Default "#f5f5f5". Optional. The background color of the currently selected option.cyclicalNav: Type boolean. Default false. Optional. Whether to navigate through the options via arrow keys in a cyclical manner. That is, if cyclicalNav is on, when you reach the end of the list, pressing the down arrow key will take you back to the beginning, and vice versa for going up the list with the up arrow key.customModalProps: Type: property bags for the Modal component (except the closed field). Default {}. Optional. The custom properties for the Modal component you want to specify.textFilterClass: Type string. Default "". Optional. The class attribute of the text filter. You can specify multiple CSS classes separated by " ".textFilterStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the text filter.optionsContainerClass: Type string. Default "". Optional. The class attribute of the container of all options. You can specify multiple CSS classes separated by " ".optionsContainerStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the container of all options.optionClass: Type string. Default "". Optional. The class attribute of an individual option. You can specify multiple CSS classes separated by " ".optionStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for an individual option.selectedClass: Type string. Default "". Optional. The class attribute of the currently selected option. You can specify multiple CSS classes separated by " ".selectedStyleOverrides: Type Record<string, string | number>. Default {}. Optional. A property bag for the styles you want to override for the currently selected option.In the API of VanUI, you can specify an object as a property bag to override the styles of the created elements. The keys of the property bag are CSS property names, and the values of the property bag are CSS property values. Sample values of the property bag:
{
"z-index": 1000,
"background-color": "rgba(0,0,0,.8)",
}
{
"border-radius": "0.2rem",
padding: "0.8rem",
"background-color": "yellow",
}
FAQs
A collection of grab-n-go reusable UI components for VanJS
The npm package vanjs-ui receives a total of 43 weekly downloads. As such, vanjs-ui popularity was classified as not popular.
We found that vanjs-ui demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the projectβs GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.