Skip to main content
The Toolbar component renders a row of action buttons above the Gantt chart. When connected via the api prop it automatically enables and disables built-in buttons based on the current selection and chart state.

Basic setup

<script>
  import { Gantt, Toolbar, Editor } from "@svar-ui/svelte-gantt";
  import { getData } from "./data";

  const data = getData();
  let api = $state();
</script>

<Toolbar {api} />
<div class="gtcell">
  <Gantt
    bind:this={api}
    tasks={data.tasks}
    links={data.links}
    scales={data.scales}
  />
  <Editor {api} />
</div>

<style>
  .gtcell {
    height: calc(100% - 50px);
    border-top: var(--wx-gantt-border);
  }
</style>
Place Toolbar before the Gantt element so it renders above the chart. Adjust the height of the chart container to account for the toolbar’s height.

Toolbar props

api
IApi
The Gantt API object. Connects the toolbar so built-in button states (enabled/disabled) track the chart selection.
items
IButtonConfig[]
Array of button descriptors. Overrides the default button set.

Default toolbar buttons

The defaultToolbarButtons array and the getToolbarButtons() helper give you a copy of the built-in button configuration:
<script>
  import { defaultToolbarButtons, getToolbarButtons } from "@svar-ui/svelte-gantt";

  // static reference (do not mutate)
  console.log(defaultToolbarButtons);

  // fresh copy safe to modify
  const items = getToolbarButtons();
</script>
Built-in button IDs:
IDDescription
add-taskAdd a new task
edit-taskOpen the editor for the selected task
delete-taskDelete the selected task
move-task:upMove the selected task up
move-task:downMove the selected task down
copy-taskCopy the selected task
cut-taskCut the selected task
paste-taskPaste the clipboard task
indent-task:addIndent the selected task (make it a child)
indent-task:removeOutdent the selected task
Separators between button groups use { comp: "separator" }.

Customising the button list

Call getToolbarButtons() to get a modifiable copy of the defaults, then filter or extend it before passing to Toolbar:
<script>
  import { Gantt, Toolbar, Editor, getToolbarButtons } from "@svar-ui/svelte-gantt";
  import { getContext } from "svelte";
  import { getData } from "./data";

  const helpers = getContext("wx-helpers");
  const data = getData();
  let api = $state();

  // remove the indent/outdent buttons
  const items = getToolbarButtons().filter(b => {
    return b.id?.indexOf("indent") === -1;
  });

  // add a custom icon button
  items.push({
    id: "my-action",
    comp: "icon",
    icon: "wxi-cat",
    handler: actionHandler,
  });

  function actionHandler() {
    helpers.showNotice({ text: "'My action' clicked" });
  }
</script>

<Toolbar {api} {items} />
<div class="gtcell">
  <Gantt
    bind:this={api}
    tasks={data.tasks}
    links={data.links}
    scales={data.scales}
  />
  <Editor {api} />
</div>

<style>
  .gtcell {
    height: calc(100% - 50px);
    border-top: var(--wx-gantt-border);
  }
</style>

Fully custom toolbar

You can build a completely custom toolbar by constructing the items array yourself and wiring handlers that call api.exec:
<script>
  import { Gantt, Editor } from "@svar-ui/svelte-gantt";
  import { Toolbar } from "@svar-ui/svelte-toolbar";
  import { getData } from "./data";

  const data = getData();
  let api = $state();
  let selected;

  function handleAdd() {
    api.exec("add-task", {
      task: { text: "New task" },
      target: $selected[0],
      mode: "after",
    });
  }

  function handleDelete() {
    const order = getActionOrder(true);
    order.forEach(id => api.exec("delete-task", { id }));
  }

  function handleMove(mode) {
    const changeDir = mode === "down";
    const order = getActionOrder(changeDir);
    order.forEach(id => api.exec("move-task", { id, mode }));
  }

  function getActionOrder(changeDir) {
    const tasks = $selected
      .map(id => api.getTask(id))
      .sort((a, b) => a.$level - b.$level || a.$y - b.$y);
    const idOrder = tasks.map(o => o.id);
    if (changeDir) return idOrder.reverse();
    return idOrder;
  }

  const allItems = [
    { comp: "button", type: "primary",  text: "Add task",       handler: handleAdd },
    { comp: "button",                   text: "Delete task",    handler: handleDelete },
    { comp: "button", type: "primary",  text: "Move task down", handler: () => handleMove("down") },
    { comp: "button", type: "primary",  text: "Move task up",   handler: () => handleMove("up") },
  ];

  const items = $derived.by(() => {
    if (api) {
      selected = api.getReactiveState().selected;
      return $selected.length ? allItems : [allItems[0]];
    }
    return [allItems[0]];
  });
</script>

<Toolbar {items} />
<div class="gtcell">
  <Gantt
    bind:this={api}
    tasks={data.tasks}
    links={data.links}
    scales={data.scales}
  />
  <Editor {api} />
</div>

<style>
  .gtcell {
    height: calc(100% - 50px);
    border-top: var(--wx-gantt-border);
  }
</style>
When building a custom toolbar without the api prop, use api.getReactiveState().selected to derive reactive selection state for conditional button visibility.

Button config fields

id
string
Unique identifier for the button. Used to match the action dispatched when the button is clicked.
comp
'button' | 'icon' | 'separator'
required
The control type. "button" renders a labelled button, "icon" renders an icon-only button, "separator" renders a visual divider.
text
string
Button label (for comp: "button") or keyboard shortcut hint (for comp: "icon").
icon
string
Icon class name (e.g. "wxi-plus").
type
string
Visual style variant, e.g. "primary", "secondary", "danger".
handler
() => void
Click handler for custom buttons. Built-in buttons handle their own actions automatically.
isDisabled
(task, state, target?) => boolean
Function returning true to disable the button based on the current task, state, or target.
isHidden
(task, state, target?) => boolean
Function returning true to hide the button based on the current task, state, or target.

Build docs developers (and LLMs) love