Prerequisites
Proposal
Pierre trees already has a strong foundation for large-scale tree UIs: a path-first model, a performant store, virtualization, search, SSR, and a custom-element boundary. That makes it very compelling not only as a file tree, but potentially as a more general high-performance tree platform.
The main limitation today is not the engine. It is the extensibility surface around rendering, interaction, and composition.
I would like to propose evolving Pierre trees toward a more explicitly extensible architecture, while preserving the performance-oriented path-first design it already has.
At a high level, the proposal is:
1. Expose a clearer headless core
The internal state/controller/store side of Pierre trees is already strong. It would be valuable to make that a more explicit public foundation that can be used independently of the default renderer.
This would allow consumers to:
- reuse the tree engine without being forced into the built-in row renderer
- build custom renderers in Lit, React, Preact, or plain DOM
- keep UI and state fully separated while still using the same selection, focus, expansion, mutation, and search model
The goal is not to remove the current renderer, but to make it one renderer on top of a reusable core.
2. Replace the single decoration hook with a lane-based plugin model
Today the public extension surface around row rendering is still fairly narrow. It supports a header, a context menu composition surface, icons/theming, and a single decoration hook.
That works for simple badges and icons, but many advanced tree use cases need more than one decoration lane and more than one extension point.
A better model would be an ordered row-lane architecture, for example:
- leading
- icon
- content
- status
- trailing
- action
- overlay
Plugins should be able to contribute to one or more lanes without taking over the whole row.
That would allow:
- multiple independent status systems
- validation and warning markers
- execution or output indicators
- custom action affordances
- workflow-specific placeholders or insertion affordances
3. Separate row-state hooks from row-render hooks
A lot of extensions do not need custom DOM. They only need to:
- mark a row disabled
- contribute attributes or classes
- provide titles/tooltips
- expose warning or validation state
- participate in selection, focus, or interaction policy
These use cases would be much better served by pure row-state hooks.
Then row-render hooks can be reserved for visible-row rendering only.
This keeps the API cleaner and makes performance easier to reason about.
4. Support richer row contributions than icon-or-text decorations
For many applications, a row needs more than a single extra icon or text badge.
It would help if plugins could contribute richer lane content, while still fitting into a controlled and performant rendering model.
This does not need to mean arbitrary uncontrolled rendering everywhere. It could still be structured:
- path-keyed plugin state
- visible-row-only render hooks
- bounded lane render targets
- optional richer row overrides for advanced consumers
5. Add drag-and-drop extension hooks
The built-in drag-and-drop support is useful, but advanced trees often need more than standard file-tree semantics.
It would help if plugins could participate in:
- custom drop target resolution
- before / inside / after insertion semantics
- placeholder-style drop targets
- move / copy / create / insert / reorder semantics
- drag preview customization
- hover-open behavior
- cross-tree drag-and-drop policies
This would make Pierre trees much more useful for structured editors, builders, and workflow-style trees.
6. Add search and filtering provider hooks
The current search behavior is already useful, but advanced consumers often need tree search to include more than the visible path string.
It would help if plugins could contribute:
- aliases
- tags
- searchable metadata
- hidden keywords
- domain-specific filtering logic
- optional async or worker-backed search adapters for very large datasets
This would keep the default search simple while making the tree more broadly useful for application-specific data.
7. Move built-ins onto the same extensibility path
A strong way to prove the plugin model would be to migrate existing built-in renderer features onto it.
For example, built-in git status could ideally become a first-party plugin using the same public hook system that downstream consumers would use.
That would ensure the extensibility model is real and powerful enough, not just an extra compatibility layer.
8. Preserve strict performance invariants
This proposal is only valuable if it keeps the current strengths of Pierre trees intact.
Any extensibility model should preserve:
- visible-window-first rendering
- path-first state
- compatibility with virtualization
- no full-DOM scanning assumptions
- predictable row measurement
- plugin state keyed by canonical path rather than DOM identity
- pure or cacheable hooks where possible
The engine should remain fast first.
Motivation and context
Pierre trees already feels stronger internally than its current public renderer API suggests.
The underlying architecture is already doing many of the difficult things correctly:
- path-first public identity rather than DOM or numeric-ID coupling
- a store designed for large trees
- virtualization and slice-first rendering
- SSR and custom-element support
- built-in search, drag-and-drop, and mutation handling
That is exactly why this feature request seems worth making.
The gap is that the public extension model is still closer to “configuration hooks for a finished component” than “a reusable tree platform”.
That is enough for standard file-tree use cases, but it becomes limiting when a product needs:
- multiple concurrent statuses
- richer per-row structure
- domain-specific controls
- custom DnD semantics
- custom filtering/search behavior
- alternative interaction modes
- strict separation of UI from state
A good example is built-in git status support. It is helpful, but it is also a sign of the current limitation: it works as a built-in special case, not as proof that consumers can extend the tree in the same way.
For advanced applications, the desired model is usually:
- one strong state/store/controller layer
- multiple possible renderers
- multiple plugins contributing status, actions, metadata, and interaction behavior
- a renderer that remains fast because all of that still operates inside a virtualization-friendly, path-first model
That would make Pierre trees much more attractive for:
- IDE-like products
- visual builders
- workflow editors
- structured editors
- large application trees that are not purely file-system-like
In other words, this proposal is not really asking for more built-in product features.
It is asking for the renderer and extensibility model to become as strong and reusable as the engine underneath it already is.
If this direction sounds interesting, I would be happy to help refine it further into a more API-shaped proposal, for example around:
- headless controller boundaries
- row-state hooks
- lane contribution APIs
- DnD provider hooks
- search provider hooks
- plugin ordering and composition
Prerequisites
Proposal
Pierre trees already has a strong foundation for large-scale tree UIs: a path-first model, a performant store, virtualization, search, SSR, and a custom-element boundary. That makes it very compelling not only as a file tree, but potentially as a more general high-performance tree platform.
The main limitation today is not the engine. It is the extensibility surface around rendering, interaction, and composition.
I would like to propose evolving Pierre trees toward a more explicitly extensible architecture, while preserving the performance-oriented path-first design it already has.
At a high level, the proposal is:
1. Expose a clearer headless core
The internal state/controller/store side of Pierre trees is already strong. It would be valuable to make that a more explicit public foundation that can be used independently of the default renderer.
This would allow consumers to:
The goal is not to remove the current renderer, but to make it one renderer on top of a reusable core.
2. Replace the single decoration hook with a lane-based plugin model
Today the public extension surface around row rendering is still fairly narrow. It supports a header, a context menu composition surface, icons/theming, and a single decoration hook.
That works for simple badges and icons, but many advanced tree use cases need more than one decoration lane and more than one extension point.
A better model would be an ordered row-lane architecture, for example:
Plugins should be able to contribute to one or more lanes without taking over the whole row.
That would allow:
3. Separate row-state hooks from row-render hooks
A lot of extensions do not need custom DOM. They only need to:
These use cases would be much better served by pure row-state hooks.
Then row-render hooks can be reserved for visible-row rendering only.
This keeps the API cleaner and makes performance easier to reason about.
4. Support richer row contributions than icon-or-text decorations
For many applications, a row needs more than a single extra icon or text badge.
It would help if plugins could contribute richer lane content, while still fitting into a controlled and performant rendering model.
This does not need to mean arbitrary uncontrolled rendering everywhere. It could still be structured:
5. Add drag-and-drop extension hooks
The built-in drag-and-drop support is useful, but advanced trees often need more than standard file-tree semantics.
It would help if plugins could participate in:
This would make Pierre trees much more useful for structured editors, builders, and workflow-style trees.
6. Add search and filtering provider hooks
The current search behavior is already useful, but advanced consumers often need tree search to include more than the visible path string.
It would help if plugins could contribute:
This would keep the default search simple while making the tree more broadly useful for application-specific data.
7. Move built-ins onto the same extensibility path
A strong way to prove the plugin model would be to migrate existing built-in renderer features onto it.
For example, built-in git status could ideally become a first-party plugin using the same public hook system that downstream consumers would use.
That would ensure the extensibility model is real and powerful enough, not just an extra compatibility layer.
8. Preserve strict performance invariants
This proposal is only valuable if it keeps the current strengths of Pierre trees intact.
Any extensibility model should preserve:
The engine should remain fast first.
Motivation and context
Pierre trees already feels stronger internally than its current public renderer API suggests.
The underlying architecture is already doing many of the difficult things correctly:
That is exactly why this feature request seems worth making.
The gap is that the public extension model is still closer to “configuration hooks for a finished component” than “a reusable tree platform”.
That is enough for standard file-tree use cases, but it becomes limiting when a product needs:
A good example is built-in git status support. It is helpful, but it is also a sign of the current limitation: it works as a built-in special case, not as proof that consumers can extend the tree in the same way.
For advanced applications, the desired model is usually:
That would make Pierre trees much more attractive for:
In other words, this proposal is not really asking for more built-in product features.
It is asking for the renderer and extensibility model to become as strong and reusable as the engine underneath it already is.
If this direction sounds interesting, I would be happy to help refine it further into a more API-shaped proposal, for example around: