@gjirafatech/gj-tree-select
| Install | |
|---|---|
npm install @gjirafatech/gj-tree-select |
|
| Latest Version: | 1.1.5 |
| Vue: | 2 |
| License: | MIT |
| Last Updated: | Mar 9, 2026 |
| Links: | npm |
@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
Extended multiselect dropdown component for Vue 2 with search, tagging, async op...
Vanilla JavaScript and TypeScript tree select component with nested options, sea...
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 | |
| 1.1.0 | ^2.6.0 | MIT | |
| 1.0.8 | ^2.6.0 | MIT | |
| 1.0.7 | ^2.6.0 | MIT | |
| 1.0.5 | ^2.6.0 | MIT | |
| 1.0.4 | ^2.6.0 | MIT | |
| 1.0.3 | ^2.6.0 | MIT | |
| 1.0.2 | ^2.6.0 | MIT | |
| 1.0.1 | ^2.6.0 | MIT | |
| 1.0.0 | ^2.6.0 | MIT |