diff --git a/packages/playground/admin/app/components/navigation.tsx b/packages/playground/admin/app/components/navigation.tsx
index 39080ce63..ad3658645 100644
--- a/packages/playground/admin/app/components/navigation.tsx
+++ b/packages/playground/admin/app/components/navigation.tsx
@@ -61,6 +61,9 @@ export const Navigation = () => {
+ } label={'Custom components'}>
+
+
)
diff --git a/packages/playground/admin/app/pages/custom.tsx b/packages/playground/admin/app/pages/custom.tsx
new file mode 100644
index 000000000..90b342239
--- /dev/null
+++ b/packages/playground/admin/app/pages/custom.tsx
@@ -0,0 +1,41 @@
+import { Component, EntitySubTree, Field, SugaredRelativeSingleField, useField } from '@contember/interface'
+import { Binding, PersistButton } from '../../lib/components/binding'
+import * as React from 'react'
+import { Slots } from '../../lib/components/slots'
+import { Button } from '../../lib/components/ui/button'
+
+export const input = () => (
+
+
+
+
+
+
+)
+
+type MyComponentProps = {
+ field: SugaredRelativeSingleField['field']
+}
+
+const UseFieldComponent = Component(
+ ({ field }) => {
+ // The `useField` hook is used to get and update the field value from data-binding.
+ const { value, updateValue } = useField(field)
+ const increment = () => updateValue((value ?? 0) + 1)
+ const decrement = () => updateValue((value ?? 0) - 1)
+
+ return (
+
+
+
+
{value}
+
+
+
+ )
+ },
+ // When using hooks in the render function above, specify `staticRender` as the second argument to `Component` to ensure all data is properly registered.
+ ({ field }) => (
+
+ ),
+)
diff --git a/packages/playground/admin/app/pages/grid.tsx b/packages/playground/admin/app/pages/grid.tsx
index 297b487f9..985986973 100644
--- a/packages/playground/admin/app/pages/grid.tsx
+++ b/packages/playground/admin/app/pages/grid.tsx
@@ -279,7 +279,7 @@ const CustomGridRow = Component(() => (