Custom prop controls for code components
You can create components with custom prop controls.
First, note that you may not need custom controls! If all you want is to show a dynamic set of options in a dropdown, or conditionally show/hide fields, you can use prop control functions.
When registering your component, specify type: ”custom”
and a React copmonent that renders the control.
A minimal example:
// A code component that just renders the propconst CodeComponent = ({ customProp, className }) => <div className={className}>{`${customProp}`}</div>;// A prop control with the value and a button to update itconst CustomProp = ({ updateValue, value }) => (<divstyle={{width: '100%',display: 'flex',justifyContent: 'space-between',padding: '0px 10px 0px 10px'}}><span>Value: {`${value}`}.</span><button onClick={() => updateValue(!value)} style={{ background: 'lightgray', padding: '0px 5px 0px 5px' }}>Change</button></div>);// RegistrationPLASMIC.registerComponent(CodeComponent, {name: 'CodeComponent',props: {customProp: {type: 'custom',control: CustomProp}}});
The props passed to the custom control component are:
componentProps
: The props that were passed to the componentcontextData
: The data fromsetControlContextData()
. See prop control functions.value
: The current value passed to the prop.updateValue
: The callback function to update the value to be passed to the prop.FullscreenModal
andSideModal
: Modal components if the control needs more space (covering either the center of the entire screen, or just the right pane—see next section).
A shorthand if the prop registration doesn’t need to specify any other metadata is to provide the component directly:
PLASMIC.registerComponent(CodeComponent, {name: 'CodeComponent',props: {customProp: CustomProp}});
Showing modals
To show a modal, use FullscreenModal
or SideModal
. These take an onClose
callback, which is fired if users click outside.
const CustomControl = ({ FullscreenModal }) => {const [open, setOpen] = useState(false);return (<divstyle={{width: '100%',display: 'flex',justifyContent: 'space-between',padding: '0px 10px 0px 10px'}}><button onClick={() => setOpen(true)} style={{ background: 'lightgray', padding: '0px 5px 0px 5px' }}>Edit</button><FullscreenModal show={open} onClose={() => setOpen(false)}><div>More UI here!</div><button onClick={() => setOpen(false)}>Close</button></FullscreenModal></div>);};
Usage notes
The controls run inside the Plasmic Studio UI, which is running in a different document/iframe than your application/your app host.
This has a few current implications:
Context from your app host won’t be there. If your components need context (e.g. for styling), for now you will need to wrap each component, like so:
function StandardContexts({ children }) {return (<ThemeProvider><SomeOtherProvider>{children}</SomeOtherProvider></ThemeProvider>);}function CustomProp1(props) {return <StandardContexts>...</StandardContexts>;}function CustomProp2(props) {return <StandardContexts>...</StandardContexts>;}
And, styling must be provided explicitly. Things will be fine if you are using a CSS-in-JS solution that dynamically injects styles into the document, but if you need external stylesheets to be loaded, then you will need to include and manage those yourself.