Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Add documentation on how to create controlled properties #3444

Merged
merged 3 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions docs/data/toolpad/studio/concepts/custom-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,48 @@ To use a custom component, drag it from the Component Library into the canvas. T

{{"component": "modules/components/DocsImage.tsx", "src": "/static/toolpad/docs/studio/concepts/custom-components/library.png", "alt": "Custom components ", "caption": "Custom components in the library"}}

## Manipulate external state

As shown in the previous section, properties can act as input to the component. But it doesn't have to stop there, You can define certain properties as input/output and have their value synced automatically with page state. This is how for example the built-in [TextField](/toolpad/studio/components/text-field/) component works.

To write back changes to a property you'll have to define a secondary property on your component that acts as an `onChange` handler. You then add the `onChangeProp` property in the argument type to connect both properties as an input/output.

```jsx
import * as React from 'react';
import { createComponent } from '@toolpad/studio/browser';

export interface HelloWorldProps {
msg: string;
onMsgChange: (newMsg: string) => void
}

function HelloWorld({ msg, onMsgChange }: HelloWorldProps) {
return <input value={msg} onChange={event => onMsgChange(event.target.value)} />;
}

export default createComponent(HelloWorld, {
argTypes: {
msg: {
type: 'string',
default: 'Hello world!',
onChangeProp: 'onMsgChange'
},
},
});
```

This component, when dragged to the canvas, has a **msg** property that you can't bind to. But you can now bind to this property from other components.

<video controls width="auto" height="100%" style="contain" alt="custom-component-creation">
<source src="/static/toolpad/docs/studio/concepts/custom-components/controlled-prop.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>

:::info
You can look at more detailed guides of creating custom components in the how-to guides section:

- [Map](/toolpad/studio/how-to-guides/map-display/)
- [Cube](/toolpad/studio/how-to-guides/cube-component/)

:::

:::info
Detailed documentation on the API is available in the reference section for [`createComponent`](/toolpad/studio/reference/api/create-component/).
:::
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,6 @@ export default function ExplorerHeader({
<SearchIcon fontSize="small" sx={{ mt: '-4px' }} />
</InputAdornment>
) : null,
// endAdornment: searchTerm ? (
// <InputAdornment position="end">
// <IconButton onClick={handleClearSearch} edge="end">
// <ClearIcon fontSize="small" />
// </IconButton>
// </InputAdornment>
// ) : null,
sx: {
fontSize: 14,
borderRadius: 0,
Expand Down Expand Up @@ -126,7 +119,7 @@ export default function ExplorerHeader({
) : null}
{onCreate && createLabelText ? (
<Tooltip title={createLabelText}>
<IconButton aria-label={createLabelText} size="medium" onClick={onCreate}>
<IconButton aria-label={createLabelText} size="small" onClick={onCreate}>
<AddIcon />
</IconButton>
</Tooltip>
Expand Down
4 changes: 2 additions & 2 deletions packages/toolpad-studio/src/toolpad/AppEditor/PagePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ export default function PagePanel({ className, sx }: ComponentPanelProps) {
<Divider />

<PanelGroup autoSaveId="toolpad-page-panel" direction="vertical">
<Panel id="pages-explorer" order={1} minSize={10} defaultSize={30}>
<Panel id="pages-explorer" order={1} minSize={10} defaultSize={25}>
<PagesExplorer />
</Panel>
{currentPageNode && !appDom.isCodePage(currentPageNode) ? (
<React.Fragment>
<PanelResizeHandle />
<Panel id="hierarchy-explorer" order={2} minSize={25} maxSize={90}>
<Panel id="hierarchy-explorer" order={2} minSize={10} defaultSize={25} maxSize={90}>
<PageHierarchyExplorer />
</Panel>
<PanelResizeHandle />
Expand Down
Loading