Skip to content

Commit 501e016

Browse files
J-SekKaelWD
andauthored
feat(VTreeview): indent lines (#21675)
resolves #11506 Co-authored-by: Kael <[email protected]>
1 parent 0772bc1 commit 501e016

File tree

12 files changed

+582
-34
lines changed

12 files changed

+582
-34
lines changed

packages/api-generator/src/locale/en/VTreeview.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"hoverable": "Applies a hover class when mousing over nodes.",
1010
"filter": "Custom item filtering function. By default it will use case-insensitive search in item's label.",
1111
"fluid": "Removes indentation from nested items.",
12+
"hideActions": "Hide the expand icon and loading indicator next to each item title.",
1213
"indeterminateIcon": "Icon used when node is in an indeterminate state. Only visible when `selectable` is `true`.",
1314
"itemChildren": "Property on supplied `items` that contains its children.",
1415
"itemDisabled": "Property on supplied `items` that contains the disabled state of the item.",
@@ -30,7 +31,9 @@
3031
"selectable": "Will render a checkbox next to each node allowing them to be selected. Additionally, the **[openOnClick](/api/v-treeview/#props-open-on-click)** property will be applied internally.",
3132
"selectedColor": "The color of the selection checkbox.",
3233
"selectionType": "Controls how the treeview selects nodes. There are two modes available: 'leaf' and 'independent'.",
34+
"separateRoots": "Applies to `default` variant of `indent-lines`. Prevents showing lines between root-level nodes.",
3335
"shaped": "Provides an alternative active style for `v-treeview` node. Only visible when `activatable` is `true` and should not be used in conjunction with the `rounded` prop.",
36+
"indentLines": "Controls visibility and variant of the indent lines.",
3437
"transition": "Applies a transition when nodes are opened and closed.",
3538
"value": "Allows one to control which nodes are selected. The array consists of the `item-key` of each selected item. Is used with `@input` event to allow for `v-model` binding.",
3639
"collapseIcon": "Icon to display when the list item is expanded."

packages/api-generator/src/locale/en/VTreeviewItem.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"props": {
3-
"lines": "The line declaration specifies the minimum height of the item and can also be controlled from v-list with the same prop.",
3+
"hideActions": "Hide the expand icon and loading indicator next to each item title.",
4+
"indentLines": "Array of indent lines to render next to the item.",
45
"loading": "Places the v-treeview-item into a loading state.",
56
"nav": "Reduces the width of v-list-item takes and adds a border radius.",
67
"slim": "Reduces the vertical padding or height of the v-treeview-item, making it more compact.",

packages/docs/src/data/new-in.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@
147147
"text": "3.2.0"
148148
}
149149
},
150+
"VTreeview": {
151+
"props": {
152+
"hideActions": "3.10.0",
153+
"separateRoots": "3.10.0",
154+
"showLines": "3.10.0"
155+
}
156+
},
157+
"VTreeviewItem": {
158+
"props": {
159+
"hideActions": "3.10.0",
160+
"indentLines": "3.10.0"
161+
}
162+
},
150163
"VTooltip": {
151164
"props": {
152165
"eager": "3.2.0",
Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
<template>
2+
<div>
3+
<v-sheet class="px-6 py-2 border-b" color="surface">
4+
<div class="d-flex gx-3 flex-wrap">
5+
<div class="d-flex align-center ga-3">
6+
<span class="mr-3">Lines:</span>
7+
<v-chip-group v-model="indentLines">
8+
<v-chip :value="false" text="none" filter label></v-chip>
9+
<v-chip :value="true" text="default" filter label></v-chip>
10+
<v-chip text="simple" value="simple" filter label></v-chip>
11+
</v-chip-group>
12+
</div>
13+
<v-spacer></v-spacer>
14+
<div class="d-flex align-center ga-6 text-no-wrap">
15+
<v-switch
16+
v-model="actionIcons"
17+
color="success"
18+
density="comfortable"
19+
label="action icons"
20+
hide-details
21+
></v-switch>
22+
<v-switch
23+
v-model="prependIcons"
24+
color="success"
25+
density="comfortable"
26+
label="prepend icons"
27+
hide-details
28+
></v-switch>
29+
<v-switch
30+
v-model="separateRoots"
31+
:disabled="indentLines !== true"
32+
color="success"
33+
density="comfortable"
34+
label="separate roots"
35+
hide-details
36+
></v-switch>
37+
</div>
38+
</div>
39+
</v-sheet>
40+
<v-container class="d-flex ga-8 justify-center flex-wrap" fluid>
41+
42+
<v-sheet width="400">
43+
<v-treeview
44+
:hide-actions="!actionIcons"
45+
:indent-lines="indentLines"
46+
:items="items1"
47+
:separate-roots="separateRoots"
48+
density="compact"
49+
item-value="id"
50+
max-width="400"
51+
open-all
52+
open-on-click
53+
>
54+
<template v-if="prependIcons" v-slot:prepend="{ item, isOpen }">
55+
<v-icon :icon="getIcon(item, isOpen)"></v-icon>
56+
</template>
57+
</v-treeview>
58+
</v-sheet>
59+
60+
<v-sheet width="400">
61+
<v-treeview
62+
:hide-actions="!actionIcons"
63+
:indent-lines="indentLines"
64+
:items="items2"
65+
:separate-roots="separateRoots"
66+
density="compact"
67+
item-value="id"
68+
open-all
69+
open-on-click
70+
>
71+
<template v-if="prependIcons" v-slot:prepend="{ item, isOpen }">
72+
<v-icon :icon="getIcon(item, isOpen)"></v-icon>
73+
</template>
74+
</v-treeview>
75+
</v-sheet>
76+
</v-container>
77+
</div>
78+
</template>
79+
80+
<script setup>
81+
import { shallowRef } from 'vue'
82+
83+
const separateRoots = shallowRef(false)
84+
const actionIcons = shallowRef(true)
85+
const prependIcons = shallowRef(true)
86+
const indentLines = shallowRef(true)
87+
88+
const files = {
89+
html: 'mdi-language-html5',
90+
js: 'mdi-nodejs',
91+
pdf: 'mdi-file-pdf-box',
92+
png: 'mdi-file-image',
93+
mov: 'mdi-video-outline',
94+
mp4: 'mdi-video-outline',
95+
}
96+
97+
function getIcon (item, isOpen) {
98+
if (item.children) return isOpen ? 'mdi-folder-open' : 'mdi-folder'
99+
return files[item.title.split('.').at(-1)] ?? 'mdi-file-outline'
100+
}
101+
102+
const items1 = [
103+
{
104+
id: 5,
105+
title: 'Documents',
106+
children: [
107+
{
108+
id: 6,
109+
title: 'vuetify',
110+
children: [
111+
{
112+
id: 7,
113+
title: 'src',
114+
children: [{ id: 8, title: 'index.js' }],
115+
},
116+
],
117+
},
118+
{
119+
id: 101,
120+
title: 'material1',
121+
children: [
122+
{
123+
id: 111,
124+
title: 'src',
125+
children: [
126+
{ id: 112, title: 'v-chip.js' },
127+
{ id: 113, title: 'v-slider.js' },
128+
],
129+
},
130+
],
131+
},
132+
{
133+
id: 10,
134+
title: 'material2',
135+
children: [
136+
{
137+
id: 11,
138+
title: 'src',
139+
children: [
140+
{ id: 12, title: 'v-btn.js' },
141+
{ id: 13, title: 'v-card.js' },
142+
{ id: 14, title: 'v-window.js' },
143+
],
144+
},
145+
],
146+
},
147+
],
148+
},
149+
]
150+
151+
const items2 = [
152+
{
153+
id: 115,
154+
title: 'Documents',
155+
children: [
156+
{
157+
id: 116,
158+
title: 'Financial',
159+
children: [
160+
{ id: 17, title: 'November.pdf' },
161+
],
162+
},
163+
{
164+
id: 117,
165+
title: 'Taxes',
166+
children: [
167+
{ id: 118, title: 'December.pdf' },
168+
{ id: 119, title: 'January.pdf' },
169+
],
170+
},
171+
{
172+
id: 120,
173+
title: 'Later',
174+
children: [
175+
{ id: 121, title: 'Company logo.png' },
176+
],
177+
},
178+
],
179+
},
180+
{
181+
id: 15,
182+
title: 'Downloads',
183+
children: [
184+
{ id: 16, title: '2022-03-01 Report.pdf' },
185+
{ id: 18, title: 'Tutorial.html' },
186+
],
187+
},
188+
{
189+
id: 19,
190+
title: 'Videos',
191+
children: [
192+
{
193+
id: 20,
194+
title: 'Tutorials',
195+
children: [
196+
{ id: 21, title: 'Basic layouts.mp4' },
197+
{ id: 23, title: 'Empty folder', children: [] },
198+
{ id: 22, title: 'Advanced techniques.mp4' },
199+
],
200+
},
201+
{ id: 24, title: 'Intro.mov' },
202+
{ id: 25, title: 'Conference introduction.mov' },
203+
],
204+
},
205+
]
206+
</script>
207+
208+
<script>
209+
export default {
210+
data: () => ({
211+
separateRoots: false,
212+
actionIcons: true,
213+
prependIcons: true,
214+
files: {
215+
html: 'mdi-language-html5',
216+
js: 'mdi-nodejs',
217+
pdf: 'mdi-file-pdf-box',
218+
png: 'mdi-file-image',
219+
mov: 'mdi-file-video-outline',
220+
mp4: 'mdi-video-outline',
221+
},
222+
items1: [
223+
{
224+
id: 5,
225+
title: 'Documents',
226+
children: [
227+
{
228+
id: 6,
229+
title: 'vuetify',
230+
children: [
231+
{
232+
id: 7,
233+
title: 'src',
234+
children: [{ id: 8, title: 'index.js' }],
235+
},
236+
],
237+
},
238+
{
239+
id: 101,
240+
title: 'material1',
241+
children: [
242+
{
243+
id: 111,
244+
title: 'src',
245+
children: [
246+
{ id: 112, title: 'v-chip.js' },
247+
{ id: 113, title: 'v-slider.js' },
248+
],
249+
},
250+
],
251+
},
252+
{
253+
id: 10,
254+
title: 'material2',
255+
children: [
256+
{
257+
id: 11,
258+
title: 'src',
259+
children: [
260+
{ id: 12, title: 'v-btn.js' },
261+
{ id: 13, title: 'v-card.js' },
262+
{ id: 14, title: 'v-window.js' },
263+
],
264+
},
265+
],
266+
},
267+
],
268+
},
269+
],
270+
items2: [
271+
{
272+
id: 115,
273+
title: 'Documents',
274+
children: [
275+
{
276+
id: 116,
277+
title: 'Financial',
278+
children: [
279+
{ id: 17, title: 'November.pdf' },
280+
],
281+
},
282+
{
283+
id: 117,
284+
title: 'Taxes',
285+
children: [
286+
{ id: 118, title: 'December.pdf' },
287+
{ id: 119, title: 'January.pdf' },
288+
],
289+
},
290+
{
291+
id: 120,
292+
title: 'Later',
293+
children: [
294+
{ id: 121, title: 'Company logo.png' },
295+
],
296+
},
297+
],
298+
},
299+
{
300+
id: 15,
301+
title: 'Downloads',
302+
children: [
303+
{ id: 16, title: '2022-03-01 Report.pdf' },
304+
{ id: 18, title: 'Tutorial.html' },
305+
],
306+
},
307+
{
308+
id: 19,
309+
title: 'Videos',
310+
children: [
311+
{
312+
id: 20,
313+
title: 'Tutorials',
314+
children: [
315+
{ id: 21, title: 'Basic layouts.mp4' },
316+
{ id: 23, title: 'Empty folder', children: [] },
317+
{ id: 22, title: 'Advanced techniques.mp4' },
318+
],
319+
},
320+
{ id: 24, title: 'Intro.mov' },
321+
{ id: 25, title: 'Conference introduction.mov' },
322+
],
323+
},
324+
],
325+
}),
326+
methods: {
327+
getIcon (item, isOpen) {
328+
if (item.children) return isOpen ? 'mdi-folder-open' : 'mdi-folder'
329+
return this.files[item.title.split('.').at(-1)] ?? 'mdi-file-outline'
330+
},
331+
},
332+
}
333+
</script>

packages/docs/src/pages/en/components/treeview.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,9 @@ Easily filter your treeview by using the **search** prop. You can easily apply y
158158
Customize the **on**, **off** and **indeterminate** icons for your selectable tree. Combine with other advanced functionality like API loaded items.
159159

160160
<ExamplesExample file="v-treeview/misc-selectable-icons" />
161+
162+
### Indent lines
163+
164+
The `v-treeview` component can be configured to show indent lines. The `indent-lines` prop controls lines visibility and the variant.
165+
166+
<ExamplesExample file="v-treeview/misc-indent-lines" />

0 commit comments

Comments
 (0)