Contributing new Frameworks
Headless Tree is designed to be framework-agnostic. It provides a React integration as core framework support, but it is possible to create integrations for other frameworks as well. This document outlines how to integrate Headless Tree with custom frameworks, and also how to contribute such integrations back to the project.
The implementation of the React integration can serve as a reference for creating integrations with other frameworks.
Gist of the integration
To create a Headless Tree instance in your framework integration, you need to:
- Call
createTree
from@headless-tree/core
once and store that reference - Call
tree.setMounted(true)
once when the tree is mounted in the DOM - Call
tree.rebuildTree()
once - Call
tree.setConfig(prev => ({ ...prev, ...newConfig }))
whenever the config changes - Call
tree.setMounted(false)
once when the tree is unmounted from the DOM - Maintain a partial state of the tree for all properties that are not explicitly user-managed via their
config.state
property, and hook that up with:
const [state, setState] = useState<Partial<TreeState<T>>>({});
tree.setConfig(prev => ({
...prev,
state: {
...state,
...userConfig.state,
},
setState: (state) => {
setState(state);
userConfig.setState?.(state);
},
}))
Remapping props
All prop names generated by features are created as React-compliant prop names. You can remap them
by implementing a custom feature that overwrites prop-related methods, and rewrites their output in
a way that is compatible with your framework. In the following sample, the aria-label
prop is remapped
to data-label
for tree item instances. This can be expanded to every prop if you want.
For a new framework integration, a new custom feature needs to be implemented that remaps all props of props-generating features to the desired prop names of the new framework. Method calls that generate props include:
itemInstance.getProps()
itemInstance.getCheckboxProps()
itemInstance.getRenameInputProps()
treeInstance.getSearchInputProps()
treeInstance.getContainerProps()
Integration into the Headless Tree monorepo
The following tasks should be done to integrate a new framework into the Headless Tree monorepo:
- Create a new package in the
packages
folder, e.g.packages/vue
for a Vue integration, and implement and expose the integration hook - Write basic unit tests within that package that do a sanity check of the lifecycle and prop renaming
- Create a new package in the
packages
folder, e.g.examples/sb-vue
, that contains a storybook setup for the new framework integration which includes some sample stories of common use cases. - Create a sample app in the
examples
folder, e.g.examples/vue-app
, that can be used to manually test the integration in a real app environment.
Please discuss your integration proposal in the HT Discord or in a GitHub issue before starting the implementation. I (Lukas Bach) or other contributors can also help with individual steps of an integration if needed.