Use when UI of app requires Toolbar, configuring, or modifying SVAR Svelte Toolbar / @wx/svelte-toolbar components
Package
import { Toolbar, registerToolbarItem } from "@wx/svelte-toolbar";
Supported functionality
Events
- item
handler, toolbaronclick, toolbaronchange
Value binding
valuesbag of properties bound to inputs in toolbar byitem.key, changes tracked byonchange
Overflow modes
default is overflow="menu"
menu: when items no longer fit, trailing top-level items move into a dots menumenuTextreplacestextonly inside the overflow menu
wrap: wraps to new rowscollapse: never creates a dots menu; it collapses the rightmost open top-level group first, only affects top-level items that have nesteditems; plain buttons do not collapse
Item's properties
comp- component name, built in arebutton,icon,label,item,separator,spacerkey- bind to values by this keytext,menuText- content of button in normal and menu modescollapsed,layout,items- used to organise groups of buttons ( like ribbons )handler- per item click handlercss- css class to the button's containerspacer- addsflex:1to the button (it takes all space)- all extra properties passthrough to the Svelte components
Common elements
Button configurations:
{ comp: "button", text: "Save" }
{ comp: "button", icon: "wxi-search" }
{ comp: "button", icon: "wxi-file", text: "Load" }
{ comp: "button", text: "Apply", type: "primary" }
{ comp: "button", icon: "wxi-delete-outline", disabled: true }
{ comp: "button", icon: "wxi-content-copy", text: "Ctrl+C", menuText: "Copy" }
Icon configurations:
{ comp: "icon", icon: "wxi-search" }
{ comp: "icon", icon: "wxi-information-outline", text: "Info" }
{ comp: "icon", icon: "wxi-content-copy", text: "Ctrl+C", menuText: "Copy" }
{ comp: "icon", icon: "wxi-delete-outline", disabled: true }
Label, item, separator, spacer configurations:
{ comp: "label", text: "Toolbar title" }
{ comp: "label", key: "name" }
{ comp: "label", key: "name", spacer: true }
{ comp: "item", id: "done", text: "Mark as finished task" }
{ comp: "item", id: "delete", icon: "wxi-delete-outline", text: "Delete item", css: "danger" }
{ comp: "separator" }
{ comp: "spacer" }
item is a simple clickable row, not a core button, use it for menu/list-style actions, especially inside collapsed groups/header menus.
Widgets from @wx/svelte-core which can be used as components: Slider, Text, CheckboxGroup, RichSelect, DatePicker, ColorPicker, ColorSelect, Checkbox, Tabs, Pager, Segmented, Switch, TwoState, Combo, MultiCombo.
Public Types
import type { Component } from "svelte";
export interface IToolbarItem {
id?: string | number;
comp?: string | Component<any>;
icon?: string;
css?: string;
text?: string;
menuText?: string;
key?: string;
spacer?: boolean;
collapsed?: boolean;
handler?: (item: IToolbarItem, value?: any) => void;
layout?: "column";
items?: IToolbarItem[];
[key: string]: any;
}
export declare const Toolbar: Component<{
items?: IToolbarItem[];
menuCss?: string;
css?: string;
values?: { [key: string]: any };
overflow?: "collapse" | "wrap" | "menu";
onclick?: (ev: { item: IToolbarItem }) => void;
onchange?: (ev: { value: any; item: IToolbarItem }) => void;
}>;
export declare function registerToolbarItem(
type: string,
handler: Component<any>
): void;
Styling
toolbar
cssis appended to.wx-toolbar; use it as the parent styling hookmenu
menuCssis appended to the overflow.wx-menu; itemcssis appended to.wx-tb-elementor group.wx-tb-grouptoolbar container:
.wx-toolbartop-level item wrapper:
.wx-tb-elementgroup wrapper:
.wx-tb-group, group body:.wx-tb-bodyoverflow menu container in the toolbar row
.wx-menucontent wrapper inside the opened dropdown
wx-drop-menuseparator
.wx-separatorand.wx-separator-menulayout="column"on Toolbar makes.wx-toolbar.wx-columnlayout: "column"on a group makes.wx-column > .wx-tb-bodycomp: "spacer"renders flex filler;spacer: trueon normal item makes its wrapperflex: 1
/*Gap between toolbar items*/
.my-toolbar .wx-tb-element {
padding: 2px;
}
/*padding around the whole toolbar*/
.my-toolbar {
padding: 8px 12px; /* default is 4px */
}
/*padding for groups*/
.my-toolbar .wx-tb-body {
gap: 4px;
}
Recipes
Basic Toolbar
<script>
let message = $state("");
function onClick(item) {
message = `Button '${item.id}' clicked`;
}
const items = [
{ id: "label", text: "Toolbar with icon buttons" },
{ comp: "separator" },
{ id: "search", comp: "button", icon: "wxi-search", handler: onClick },
{ comp: "spacer" },
{
id: "copy",
comp: "icon",
icon: "wxi-content-copy",
handler: onClick,
},
];
</script>
<Toolbar {items} />
Per-Item Handler
function onClick(item) {
console.log(item.id);
}
const items = [
{ id: "edit", comp: "button", icon: "wxi-edit-outline", handler: onClick },
];
Toolbar Click Handler
<Toolbar
items={[
{ id: "edit", comp: "button", icon: "wxi-edit-outline" },
{ id: "delete", comp: "button", icon: "wxi-delete-outline" },
]}
=> console.log(ev.item.id)}
/>
Keyed Values
<script>
// component must support `value` handler and `onchange` callback to be bound, most svelte-core controls fit
import { Slider } from "@wx/svelte-core";
let values = $state({ size: 15 });
</script>
<Toolbar
items={[{ comp: Slider, min: 0, max: 100, key: "size" }]}
bind:values
=> console.log(ev.item.key, ev.value)}
/>
Common core controls
<script>
import { Slider, Segmented, Switch } from "@wx/svelte-core";
const options = [
{ id: 1, label: "One" },
{ id: 2, label: "Two" },
];
</script>
<Toolbar
css="demo-toolbar"
values={{ size: 14, mode: 1, enabled: true }}
items={[
{ text: "Controls" },
{ comp: "spacer" },
{ comp: Slider, min: 0, max: 100, key: "size" },
{ comp: Segmented, options, key: "mode" },
{ comp: Switch, key: "enabled" },
]}
/>
Custom Component Contract
<!-- CustomToolbarItem.svelte -->
<script>
let {
value,
onchange,
onclick,
menu,
text = "",
disabled = false,
} = $props();
</script>
<button
class:in-menu={menu}
{disabled}
=> {
onclick?.();
onchange?.({ value: !value });
}}
>
{text}
</button>
import CustomToolbarItem from "./CustomToolbarItem.svelte";
const items = [{ comp: CustomToolbarItem, key: "flag", text: "Toggle" }];
const values = { flag: false };
Group
const items = [
{
text: "Align",
items: [
{ id: "align-left", comp: "button", icon: "wxo-align-left" },
{ id: "align-center", comp: "button", icon: "wxo-align-center" },
{ id: "align-right", comp: "button", icon: "wxo-align-right" },
],
},
];
Column Group
const items = [
{
layout: "column",
text: "Font",
items: [
{
items: [
{
key: "font-family",
comp: "richselect",
options: fontFamilyData,
},
{
key: "font-size",
comp: "richselect",
options: fontSizeData,
},
],
},
{
items: [
{ id: "font-bold", comp: "button", icon: "wxo-bold" },
{ id: "font-italic", comp: "button", icon: "wxo-italic" },
{
id: "font-underline",
comp: "button",
icon: "wxo-underline",
},
],
},
],
},
];
Ribbon Layout
const items = [
{
items: [
{
layout: "column",
items: [
{
id: "load",
css: "bigButton",
comp: "button",
icon: "wxi-file",
text: "Load",
},
],
},
{
layout: "column",
items: [
{ id: "undo", comp: "button", icon: "wxo-undo" },
{ id: "redo", comp: "button", icon: "wxo-redo" },
],
},
],
},
{ comp: "separator" },
{
layout: "column",
items: [
{
items: [
{
key: "font-family",
comp: "richselect",
options: fontFamilyData,
},
],
},
{ items: [{ id: "font-bold", comp: "button", icon: "wxo-bold" }] },
],
},
];
Initially-Collapsed Group
const items = [
{
text: "Data",
icon: "wxi-dots-v",
collapsed: true,
layout: "column",
items: [{ id: "load" }, { id: "delete" }],
},
];
Header Menu
<Toolbar
values={{ name: "Item X12-A" }}
items={[
{ comp: "label", spacer: true, key: "name" },
{ comp: "separator" },
{
icon: "wxi-dots-v",
collapsed: true,
layout: "column",
items: [
{ id: "done", comp: "item", text: "Mark as finished task" },
{
id: "delete",
comp: "item",
css: "danger",
text: "Delete item",
},
],
},
]}
/>
Vertical Toolbar
<Toolbar
layout="column"
items={[
{ id: "new", comp: "button", icon: "wxi-plus" },
{ id: "edit", comp: "button", icon: "wxi-edit-outline" },
{ comp: "separator" },
{ id: "delete", comp: "button", icon: "wxi-delete-outline" },
]}
/>
Source: svar-widgets/toolbar — distributed by TomeVault.