@gjirafatech/gj-tree-select

Hierarchical multi-select dropdown with tree connectors for Vue 2
1,774
Install
npm install @gjirafatech/gj-tree-select
Latest Version:1.1.5
Vue:2
License:MIT
Last Updated:Mar 9, 2026
Links: npm
Maintainer: rinakasabaqi

@gjirafatech/gj-tree-select

A hierarchical multi-select dropdown with tree connector lines for Vue 2.

Works with any flat data — folders, channels, categories, departments — you provide a dataAdapter and the component builds the tree.

Install

npm install @gjirafatech/gj-tree-select

Quick Start

Global registration

import Vue from 'vue'
import GjTreeSelect from '@gjirafatech/gj-tree-select'

Vue.use(GjTreeSelect)

Local registration

import { GjTreeSelect } from '@gjirafatech/gj-tree-select'

export default {
  components: { GjTreeSelect }
}

Basic Usage

<template>
  <GjTreeSelect
    v-model="selectedIds"
    :items="folders"
    placeholder="Select folder"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedIds: [],
      folders: [
        { id: 1, parentId: 0, name: 'Sports' },
        { id: 2, parentId: 0, name: 'News' },
        { id: 3, parentId: 1, name: 'Football' },
        { id: 4, parentId: 1, name: 'Basketball' },
        { id: 5, parentId: 3, name: 'Premier League' },
      ]
    }
  }
}
</script>

Collapsible Tree

Enable expand/collapse functionality with arrow icons. Nodes are collapsed by default when collapsible is enabled:

<GjTreeSelect
  v-model="selectedIds"
  :items="folders"
  :collapsible="true"
  placeholder="Select folder"
/>

You can also customize the expand/collapse icon:

<GjTreeSelect v-model="selectedIds" :items="folders" :collapsible="true">
  <template #expand-icon="{ node, isExpanded }">
    <GjIcon
      :name="isExpanded ? 'ChevronDown' : 'ChevronRight'"
      size="16"
    />
  </template>
</GjTreeSelect>

Custom Icons (Scoped Slots)

The component renders fallback SVG icons by default. Override them with scoped slots:

<GjTreeSelect v-model="selectedIds" :items="folders" placeholder="Select folder">
  <!-- Custom node icon -->
  <template #node-icon="{ node, isSelected }">
    <GjIcon name="FolderOutline" size="20" />
  </template>

  <!-- Custom checkbox -->
  <template #check-icon="{ node, isSelected }">
    <GjIcon
      :name="isSelected ? 'CheckButtonSquareEnabledFilled' : 'CheckButtonSquareDisabled'"
      size="16"
    />
  </template>

  <!-- Custom chevron -->
  <template #chevron-icon="{ isOpen }">
    <GjIcon name="ArrowDown" size="16" />
  </template>

  <!-- Custom tag remove -->
  <template #tag-remove-icon="{ tag }">
    <GjIcon name="Close" size="16" />
  </template>
</GjTreeSelect>

Custom Tag Pills

Note: The component handles ellipsis automatically by default. You only need this if you want custom tag styling or icons.

To fully customize tag pills, override the tag slot. Important: When overriding, you must provide your own CSS for ellipsis to work correctly:

<GjTreeSelect v-model="selectedIds" :items="folders">
  <template #tag="{ tag, remove }">
    <span class="tag-content">
      <span class="tag-label">{{ tag.name }}</span>
      <button type="button" class="tag-remove-btn" @click="remove">
        <GjIcon name="Close" size="12" />
      </button>
    </span>
  </template>
</GjTreeSelect>

<style scoped>
.tag-content {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: 1;
}

.tag-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.tag-remove-btn {
  flex-shrink: 0;
  margin-left: 4px;
}
</style>

Different Data Shapes (dataAdapter)

Your API returns channelId, parentChannelId, title? No problem:

<GjTreeSelect
  v-model="selectedChannels"
  :items="channels"
  :data-adapter="{
    idKey: 'channelId',
    parentIdKey: 'parentChannelId',
    nameKey: 'title',
    rootParentId: null,
  }"
  placeholder="Select channel"
>
  <template #node-icon>
    <GjIcon name="Broadcast" size="20" />
  </template>
</GjTreeSelect>

Props

Prop Type Default Description
value (v-model) Array [] Selected IDs.
items Array [] Flat array of items (any shape).
data-adapter Object { idKey: 'id', parentIdKey: 'parentId', nameKey: 'name', rootParentId: 0 } Maps your data fields.
placeholder String 'Select...' Placeholder text.
max-visible-tags Number 2 Tags before +N overflow.
searchable Boolean true Enable search filtering.
disabled Boolean false Disable the component.
collapsible Boolean false Enable expand/collapse icons for parent nodes.
show-select-all Boolean true "Select all" on parent nodes with children.
select-all-label String 'Select all' Label for select-all.
deselect-all-label String 'Deselect' Label for deselect-all.
empty-text String 'No items available' Empty state text.
connector-geometry Object See below SVG connector pixel constants.
theme Object {} CSS custom-property overrides.

Default Connector Geometry

{
  laneWidth: 22,
  rowHeight: 32,
  rowCenterY: 16,
  elbowRadius: 8,
  horizontalEndGap: 2,
  verticalOverflow: 10,
  parentEntryOverflow: 8
}

Events

Event Payload Description
input Array<id> Selection changed (v-model).
open — Dropdown opened.
close — Dropdown closed.

Scoped Slots

Slot Props Description
node-icon { node, isSelected } Icon before label in each row.
check-icon { node, isSelected } Checkbox icon on the right.
expand-icon { node, isExpanded } Expand/collapse icon (when collapsible: true).
chevron-icon { isOpen } Chevron in the control bar.
tag-remove-icon { tag } Remove button inside tag pills.
tag { tag, remove } Full override of a tag pill.

Theming (CSS Custom Properties)

Pass a theme object to override any CSS variable:

<GjTreeSelect
  :theme="{
    '--gj-ts-control-border-active': '#3A81F6',
    '--gj-ts-row-selected-bg': '#ECF3FF',
    '--gj-ts-select-all-color': '#3A81F6',
    '--gj-ts-check-active-color': '#3A81F6',
  }"
/>

Available CSS Variables

Variable Default What it styles
--gj-ts-control-bg #ffffff Control background
--gj-ts-control-border #EDEFF3 Control border
--gj-ts-control-border-active #F4B261 Control border when open
--gj-ts-control-radius 0.25rem Control border radius
--gj-ts-control-min-height 35px Control min height
--gj-ts-tag-bg #F6F8F9 Tag pill background
--gj-ts-tag-color #030F28 Tag pill text
--gj-ts-tag-radius 20px Tag pill radius
--gj-ts-tag-max-width 140px Tag pill max width
--gj-ts-placeholder-color #B5C0CE Placeholder text
--gj-ts-menu-border #DADFE7 Dropdown border
--gj-ts-menu-radius 6px Dropdown radius
--gj-ts-menu-shadow 0 4px 12px ... Dropdown shadow
--gj-ts-menu-max-height 340px Dropdown max height
--gj-ts-menu-bg #ffffff Dropdown background
--gj-ts-row-height 32px Tree row height
--gj-ts-row-radius 6px Tree row radius
--gj-ts-row-hover-bg #F6F8F9 Row hover background
--gj-ts-row-selected-bg #FDE9D3 Row selected background
--gj-ts-row-gap 8px Gap between rows
--gj-ts-label-color #030F28 Label text color
--gj-ts-label-font-size 0.875rem Label font size
--gj-ts-expand-color #A3B0C2 Expand/collapse icon color
--gj-ts-expand-hover-color #030F28 Expand/collapse icon hover color
--gj-ts-select-all-color #F4B261 "Select all" button color
--gj-ts-check-color #A3B0C2 Unchecked checkbox color
--gj-ts-check-active-color #F4B261 Checked checkbox color
--gj-ts-connector-color #C9CDD3 Connector line color
--gj-ts-connector-width 1 Connector line width

License

MIT

Related Packages

vue-pick

Select, multiselect, and tree select for Vue 2.7 and Vue 3, from one codebase

8,448 2
vue-jstree

a tree plugin for vue2

137,015 630
vue-extended-multiselect

Extended multiselect dropdown component for Vue 2 with search, tagging, async op...

1,593 1
treeselectjs

Vanilla JavaScript and TypeScript tree select component with nested options, sea...

110,815 110
vue-treeselect

a tree select plugin for vue2

15,534 43

Version History

Version Released Vue License
1.1.5 ^2.6.0 MIT
1.1.4 ^2.6.0 MIT
1.1.3 ^2.6.0 MIT
1.1.2 ^2.6.0 MIT
1.1.1 ^2.6.0 MIT