Skip to content

feat(Tree): flat item structure #4552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

J-Michalek
Copy link
Collaborator

πŸ”— Linked issue

Resolves: #4508

❓ Type of change

Render Tree items in inline structure without any nesting allowing for drag and drop and virtualization implementation.

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@J-Michalek
Copy link
Collaborator Author

@benjamincanac So the implementation of this sounds easy, but there is one thing I'm not sure we will be able to keep and that is the nested level indication (border on the ul element):
image
Any ideas on how to implement it or if it can be removed? I have tried looking up solutions in other component libraries, but found none that uses such line for level indication while also allowing for drag and drop and/or virtualization.

@benjamincanac
Copy link
Member

@J-Michalek I'm aware, this is why I implemented it this way πŸ˜…

@J-Michalek
Copy link
Collaborator Author

I think we have to choose which way to go from here, I for one am for functionality (DnD, virtualization) over design, but many people might feel different and sudden change could be annoying.

There is also an option to support both structures, but I feel like it would complicate the component and make maintenance harder, thoughts?

@caiotarifa
Copy link

@J-Michalek

+1 for support DnD and virtualization.

About the borders, could we calculate each item’s level in the flat list (so virtualization still works) and adding a ::before pseudo-element in the TreeItem component to draw a border-left at the appropriate indentation?

Something like this:

.tree-item {
  padding-left: calc(var(--indent) * var(--level));
  position: relative;
}

.tree-item::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc((var(--indent) * var(--level)) - 1px);
  border-left: 1px solid var(--ui-border);
}

@J-Michalek
Copy link
Collaborator Author

@caiotarifa Sadly it does not work when there are multiple nested levels as the border will break at some point:

border on ul element (current implementation):
level 1
  |  level 2
  | |  level 3
  |  level 2

border on individual li elements:
level 1
  |  level 2
    |  level 3
  |  level 2

We would have to do some nasty stuff with auxiliary elements to match the borders of each level, but that would be a nightmare to maintain and not a very good thing to do in general.

@caiotarifa
Copy link

caiotarifa commented Jul 22, 2025

@J-Michalek Got it.

I'm not proud of this suggestion, but we could try using repeating-linear-gradient with repeat-y instead of border-left. It might be a bit tricky, but it works.

https://codepen.io/caio/pen/myePREV

<ul>
  <li data-level="1">Level 1</li>
  <li data-level="2">Level 2</li>
  <li data-level="3">Level 3</li>
  <li data-level="2">Level 2</li>
</ul>
:root {
  --indent: 16px;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

li {
  padding-left: calc(var(--indent) * var(--level));
  position: relative;
}

li::before {
  background-image: repeating-linear-gradient(
    to right,
    #ccc 0,
    #ccc 1px,
    transparent 1px,
    transparent var(--indent)
  );
  background-repeat: repeat-y;
  
  top: 0;
  left: 0;
  bottom: 0;

  content: '';
  position: absolute;
  width: calc(var(--indent) * var(--level));
}

/* Replace by Vue. */
li[data-level="1"] { --level: 1; }
li[data-level="2"] { --level: 2; }
li[data-level="3"] { --level: 3; }

@rdjanuar
Copy link
Contributor

Hi, i`m already working this issue like 1 week ago but i forget to push it. #4583, feel free to discus @J-Michalek

@J-Michalek
Copy link
Collaborator Author

@rdjanuar Looks promising, I think we need to know, if the functionality should be preserved or not.

Also I saw that you are using a CSS class to make this work, but I don't think that is something we want to do, would you be able to implement it using Tailwind?

@rdjanuar
Copy link
Contributor

@J-Michalek Yes i can, i already update the code

@J-Michalek
Copy link
Collaborator Author

I'm gonna close this PR as @rdjanuar has made more progress on this feature already.

@J-Michalek J-Michalek closed this Jul 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

UTree: drag-and-drop
4 participants