You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+67-29Lines changed: 67 additions & 29 deletions
Original file line number
Diff line number
Diff line change
@@ -15,11 +15,32 @@ Perfect for building landing pages, email templates, forms, admin dashboards, or
15
15
🛠 Extend it. 🎨 Style it. 🚀 Own it.
16
16
17
17
18
-
See the [demo](https://uibuilder.app/demo) to get an idea of how it works.
19
-
Read the [docs](https://uibuilder.app/) to get started.
18
+
See the [demo](https://uibuilder.app/) to get an idea of how it works.
20
19
21
20

22
21
22
+
## How it Works
23
+
24
+
UI Builder empowers you to visually construct and modify user interfaces by leveraging your own React components. Here's a breakdown of its core principles:
25
+
26
+
***Component-Driven Foundation**: At its heart, UI Builder operates on your existing React components. You provide a `componentRegistry` detailing the components you want to make available in the editor. This registry includes the component itself, its Zod schema for props, its import path for code generation, and optional UI customizations for the editor.
27
+
28
+
***Layer-Based Canvas**: The user interface is constructed as a tree of "layers." Each layer represents an instance of a component from your registry. Users can visually add, remove, reorder, and nest these layers on an interactive canvas, offering a direct manipulation experience. Any component type, like `div`, `main`, or custom containers, can serve as the root page layer.
29
+
30
+
***Dynamic Props Editing**: Each component in the registry is defined with a Zod schema that outlines its props, their types, and default values. UI Builder utilizes this schema to automatically generate a properties panel (using [Auto-Form](https://github.com/vantezzen/autoform/tree/pure-shadcn)). This allows users to configure component instances in real-time, with changes immediately reflected on the canvas. Default values in the Zod schema are crucial for ensuring components render correctly when first added.
31
+
32
+
***Centralized `componentRegistry`**: The `componentRegistry` prop passed to the `UIBuilder` component is central to its operation. It's a JavaScript object where you map a unique string identifier (e.g., "Button", "FancyComponent") to each component's detailed definition.
33
+
34
+
***Flexible State Management**: By default, the editor's state (the arrangement and configuration of layers) is persisted in the browser's local storage for convenience across sessions. For more robust or backend-integrated solutions, you can provide `initialLayers` to seed the editor (e.g., from a database) and use the `onChange` callback to capture state changes and persist them as needed.
35
+
36
+
***React Code Generation**: A key feature is the ability to export the visually designed page structure as clean, readable React code. This process uses the import paths (`from` property) specified in your component registry, ensuring the generated code correctly references your components.
37
+
38
+
***Extensibility and Customization**: The system is designed for deep integration with your project:
39
+
* Customize the properties form for each component using `fieldOverrides` to enhance the editing experience (e.g., custom labels, input types, or conditional visibility).
40
+
* Provide custom React components via the `panelConfig` prop to provide custom components for the editor panels.
41
+
* If you only need to display a UI Builder page without the editor, the `LayerRenderer` component can render it using the same `componentRegistry` and page data.
42
+
43
+
This section aims to give a clearer picture of the UI Builder's architecture and how its different parts interact.
23
44
24
45
## Installation
25
46
@@ -59,20 +80,19 @@ To use the UI Builder, you need to provide a component registry and a form compo
type: "div", //Any component type can be a page root
124
+
type: "div", //Ensure div is in your componentRegistry
106
125
name: "Page 1",
107
126
props: {
108
127
className: "p-4 flex flex-col gap-2",
109
-
// You might include theme/styling props here if your pagePropsForm handles them
110
128
},
111
129
children: [
112
130
{
@@ -157,7 +175,6 @@ const App = () => {
157
175
initialLayers={initialLayers}
158
176
onChange={handleLayersChange}
159
177
componentRegistry={myComponentRegistry}
160
-
pagePropsForm={<ThemePanel />}
161
178
/>
162
179
</div>
163
180
);
@@ -167,11 +184,12 @@ export default App;
167
184
168
185
```
169
186
187
+
### UIBuilder Props
170
188
-`componentRegistry`: **Required**. An object mapping component type names to their definitions (component, schema, import path, etc.).
171
-
-`pagePropsForm`: **Required**. A React component used as the form to edit properties of the root page layer.
172
189
-`initialLayers`: Optional prop to set up initial pages and layers. Useful for setting the initial state of the builder, from a database for example.
173
190
-`onChange`: Optional callback triggered when the editor state changes, providing the updated pages. Can be used to persist the state to a database.
174
-
-`useCanvas`: Optional prop to disable the interactive canvas. Defaults to true.
191
+
-`panelConfig`: Optional. An object to customize the different panels of the UI Builder (e.g., nav bar, editor panel, props panel). If not provided, a default configuration is used. This allows for fine-grained control over the editor's appearance and layout.
192
+
-`persistLayerStore`: Optional boolean (defaults to `true`). Determines whether the editor's state (layers and their configurations) is persisted in the browser's local storage across sessions. Set to `false` to disable local storage persistence, useful if you are managing state entirely through `initialLayers` and `onChange`.
175
193
176
194
177
195
You can also render the page layer without editor functionality by using the LayerRenderer component:
@@ -205,10 +223,10 @@ Here is an example of how to define a custom component within the registry objec
-`component`: **Required**. The React component function or class.
261
274
-`schema`: **Required**. A Zod schema defining the component's props, their types, and validation rules.
262
275
- This schema powers the automatic generation of a properties form in the editor using [Auto-Form](https://github.com/vantezzen/autoform/tree/pure-shadcn).
263
-
- Props intended to be configurable in the UI Builder **MUST** have a default value specified in the schema (using `.default(...)`). This allows the UI Builder to render the component correctly when it's first added, before the user configures it.
264
276
- Currently supported Zod types for auto-form generation include: `boolean`, `date`, `number`, `string`, `enum` (of supported types), `object` (with supported property types), and `array` (of objects with supported property types).
265
-
-`from`: **Required**. The source import path for the component. This is used when exporting the page structure as React code.
277
+
-`from`: **Required**. The source import path for the component. This is used when generating React code.
266
278
-`fieldOverrides`: Optional. An object to customize the auto-generated form fields for the component's properties in the editor's sidebar.
267
279
- The keys of this object correspond to the prop names defined in the Zod schema.
268
280
- The values are typically functions that receive the current `layer` object and return configuration options for the `AutoForm` field. These options can control the field's label, input type (`fieldType`), visibility (`isHidden`), placeholder text, render logic, and more. See the AutoForm documentation for available options.
* Using specific input components (e.g., a color picker, a custom slider).
272
284
* Hiding props that shouldn't be user-editable (like internal state).
273
285
* Implementing conditional logic (e.g., showing/hiding a field based on another prop's value).
274
-
- The example uses `classNameFieldOverrides` and `childrenFieldOverrides` from `@/lib/ui-builder/registry/form-field-overrides` to provide standardized handling for common props like `className` (using a textarea) and `children` (often hidden or handled specially). You can create your own override functions or objects.
286
+
- The example uses `classNameFieldOverrides` and `childrenFieldOverrides` from `@/lib/ui-builder/registry/form-field-overrides` to provide standardized handling for common props like `className` (using a auto suggest text input) and `children` (using a custom component). You can create your own override functions or objects.
287
+
-`defaultChildren`: Optional. Default children to use when a new instance of this component is added to the canvas. For example setting initial text on a span component.
288
+
-`isFromDefaultExport`: Optional. If true, indicates the component should be imported as a default export when generating React code.
289
+
290
+
291
+
### Customizing the Page Config Panel Tabs
292
+
293
+
You can customize the tabs in the left "Page Config" panel (by default, "Layers" and "Appearance") by providing a `pageConfigPanelTabsContent` property inside the `panelConfig` prop. This allows you to change the tab titles or provide custom content for each tab.
If you do not provide this, the default tabs ("Layers" and "Appearance") will be used.
276
314
277
315
---
278
316
For more detailed documentation read the [docs](https://uibuilder.app/)
@@ -285,7 +323,7 @@ For more detailed documentation read the [docs](https://uibuilder.app/)
285
323
- Removed _page_ layer type in favor of using any component type (like `div`, `main`, or custom containers) as the root page layer. This enhances flexibility, enabling use cases like building react-email templates directly. You should migrate any layers stored in the database to use a standard component type as the root. The [migrateV2ToV3](lib/ui-builder/store/layer-utils.ts) function in `layer-utils.ts` can assist with this migration.
286
324
- The `componentRegistry` is now passed as a prop to the `UIBuilder` component instead of being defined in a standalone file.
287
325
- Removed the script used to generate component schema definitions. This approach proved problematic to maintain and didn't function correctly for complex components or varying project setups. Component schema definitions should now be manually created or generated using project-specific tooling if desired.
288
-
-`pagePropsForm` prop added to `UIBuilder` to allow customization of the form used for editing page-level (root layer) properties.
326
+
-`panelConfig` prop added to `UIBuilder` to allow customization of the page config panel tabs.
289
327
- Made `layer-store` local storage persistence optional and configurable via props.
0 commit comments