diff --git a/packages/js/components/changelog/add-35851-tree-control b/packages/js/components/changelog/add-35851-tree-control
new file mode 100644
index 00000000000..24395c6622b
--- /dev/null
+++ b/packages/js/components/changelog/add-35851-tree-control
@@ -0,0 +1,4 @@
+Significance: minor
+Type: dev
+
+Create tree-control component
diff --git a/packages/js/components/src/experimental-tree-control/hooks/use-linked-tree.ts b/packages/js/components/src/experimental-tree-control/hooks/use-linked-tree.ts
new file mode 100644
index 00000000000..94ff95706b8
--- /dev/null
+++ b/packages/js/components/src/experimental-tree-control/hooks/use-linked-tree.ts
@@ -0,0 +1,50 @@
+/**
+ * External dependencies
+ */
+import { useMemo } from 'react';
+
+/**
+ * Internal dependencies
+ */
+import { Item, LinkedTree } from '../types';
+
+type MemoItems = {
+ [ value: Item[ 'value' ] ]: LinkedTree;
+};
+
+function findChildren(
+ items: Item[],
+ parent?: Item[ 'parent' ],
+ memo: MemoItems = {}
+): LinkedTree[] {
+ const children: Item[] = [];
+ const others: Item[] = [];
+
+ items.forEach( ( item ) => {
+ if ( item.parent === parent ) {
+ children.push( item );
+ } else {
+ others.push( item );
+ }
+ memo[ item.value ] = {
+ parent: undefined,
+ data: item,
+ children: [],
+ };
+ } );
+
+ return children.map( ( child ) => {
+ const linkedTree = memo[ child.value ];
+ linkedTree.parent = child.parent ? memo[ child.parent ] : undefined;
+ linkedTree.children = findChildren( others, child.value, memo );
+ return linkedTree;
+ } );
+}
+
+export function useLinkedTree( items: Item[] ): LinkedTree[] {
+ const linkedTree = useMemo( () => {
+ return findChildren( items, undefined, {} );
+ }, [ items ] );
+
+ return linkedTree;
+}
diff --git a/packages/js/components/src/experimental-tree-control/hooks/use-tree-item.ts b/packages/js/components/src/experimental-tree-control/hooks/use-tree-item.ts
new file mode 100644
index 00000000000..9043fe00f69
--- /dev/null
+++ b/packages/js/components/src/experimental-tree-control/hooks/use-tree-item.ts
@@ -0,0 +1,30 @@
+/**
+ * External dependencies
+ */
+
+/**
+ * Internal dependencies
+ */
+import { TreeItemProps } from '../types';
+
+export function useTreeItem( { item, level, ...props }: TreeItemProps ) {
+ const nextLevel = level + 1;
+ const nextHeadingPaddingLeft = ( level - 1 ) * 28 + 12;
+
+ return {
+ item,
+ level: nextLevel,
+ treeItemProps: {
+ ...props,
+ },
+ headingProps: {
+ style: {
+ paddingLeft: nextHeadingPaddingLeft,
+ },
+ },
+ treeProps: {
+ items: item.children,
+ level: nextLevel,
+ },
+ };
+}
diff --git a/packages/js/components/src/experimental-tree-control/hooks/use-tree.ts b/packages/js/components/src/experimental-tree-control/hooks/use-tree.ts
new file mode 100644
index 00000000000..2ab6b889c58
--- /dev/null
+++ b/packages/js/components/src/experimental-tree-control/hooks/use-tree.ts
@@ -0,0 +1,21 @@
+/**
+ * External dependencies
+ */
+
+/**
+ * Internal dependencies
+ */
+import { TreeProps } from '../types';
+
+export function useTree( { ref, items, level = 1, ...props }: TreeProps ) {
+ return {
+ level,
+ items,
+ treeProps: {
+ ...props,
+ },
+ treeItemProps: {
+ level,
+ },
+ };
+}
diff --git a/packages/js/components/src/experimental-tree-control/index.ts b/packages/js/components/src/experimental-tree-control/index.ts
new file mode 100644
index 00000000000..bf4fdd7d970
--- /dev/null
+++ b/packages/js/components/src/experimental-tree-control/index.ts
@@ -0,0 +1,4 @@
+export * from './tree';
+export * from './tree-control';
+export * from './tree-item';
+export * from './types';
diff --git a/packages/js/components/src/experimental-tree-control/stories/index.tsx b/packages/js/components/src/experimental-tree-control/stories/index.tsx
new file mode 100644
index 00000000000..d62a8ed1964
--- /dev/null
+++ b/packages/js/components/src/experimental-tree-control/stories/index.tsx
@@ -0,0 +1,42 @@
+/**
+ * External dependencies
+ */
+import { BaseControl } from '@wordpress/components';
+import React, { createElement } from 'react';
+
+/**
+ * Internal dependencies
+ */
+import { TreeControl } from '../tree-control';
+import { Item } from '../types';
+
+const listItems: Item[] = [
+ { value: '1', label: 'Technology' },
+ { value: '1.1', label: 'Notebooks', parent: '1' },
+ { value: '1.2', label: 'Phones', parent: '1' },
+ { value: '1.2.1', label: 'iPhone', parent: '1.2' },
+ { value: '1.2.1.1', label: 'iPhone 14 Pro', parent: '1.2.1' },
+ { value: '1.2.1.2', label: 'iPhone 14 Pro Max', parent: '1.2.1' },
+ { value: '1.2.2', label: 'Samsung', parent: '1.2' },
+ { value: '1.2.2.1', label: 'Samsung Galaxy 22 Plus', parent: '1.2.2' },
+ { value: '1.2.2.2', label: 'Samsung Galaxy 22 Ultra', parent: '1.2.2' },
+ { value: '1.3', label: 'Wearables', parent: '1' },
+ { value: '2', label: 'Hardware' },
+ { value: '2.1', label: 'CPU', parent: '2' },
+ { value: '2.2', label: 'GPU', parent: '2' },
+ { value: '2.3', label: 'Memory RAM', parent: '2' },
+ { value: '3', label: 'Other' },
+];
+
+export const SimpleTree: React.FC = () => {
+ return (
+