{"data":{"prismicDocsCategory":{"data":{"pages":[{"page":{"uid":"merge-start","document":[{"data":{"title":{"text":"Start"},"visible_in_table_of_content":"true"}}]}},{"page":{"uid":"merge-connect-your-library","document":[{"data":{"title":{"text":"Connect your library"},"visible_in_table_of_content":"true"}}]}},{"page":{"uid":"for-developers","document":[{"data":{"title":{"text":"For Developers"},"visible_in_table_of_content":"true"}}]}},{"page":{"uid":"merge-use-in-the-editor","document":[{"data":{"title":{"text":"Use in the Editor"},"visible_in_table_of_content":"true"}}]}},{"page":{"uid":"merge-publish-and-maintain","document":[{"data":{"title":{"text":"Publish and maintain"},"visible_in_table_of_content":"true"}}]}},{"page":{"uid":"merge-faq","document":[{"data":{"title":{"text":"Frequently Asked Questions"},"visible_in_table_of_content":"true"}}]}}]}},"prismicDocsPage":{"data":{"title":{"text":"For Developers"},"isVisibleForRobots":"true","body":[{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":"Adjusting Components"},"content":{"html":"<p>Sometimes Merge needs a hint from your code to display a component correctly in UXPin. You give these hints with JSDoc comments that start with @uxpin, placed right before the component or property. This page covers the cases where you need them:</p>"}}},{"__typename":"PrismicDocsPageBodyTable","slice_type":"table","primary":{"table_first_title":{"text":"Tag"},"table_second_title":{"text":"What it does"}},"items":[{"col1":{"html":"<p>@uxpinuseportal</p>"},"col2":{"html":"<p>Renders the component in a portal, so toasts and modals appear where they should in Preview.</p>"}},{"col1":{"html":"<p>@uxpincomponent</p>"},"col2":{"html":"<p>Tells Merge which component to read when the default export is wrapped by another function.</p>"}},{"col1":{"html":"<p>@uxpinnamespace</p>"},"col2":{"html":"<p>Declares the parent of a nested component, such as Autocomplete.ComboBox.</p>"}},{"col1":{"html":"<p>@uxpinwrappers</p>"},"col2":{"html":"<p>Adjusts how the bounding box behaves: SkipContainerWrapper and NonResizableWrapper.</p>"}},{"col1":{"html":"<p>@uxpinbind</p>"},"col2":{"html":"<p>Lets the designer trigger an interaction when a property changes.</p>"}}]},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Portal components</h3><p>When you need to display chosen components outside the UXPin canvas, at a specific position on the screen, portal components enable that.</p><p>For example, notification components (often called “toast” or “snack”) appear at the top or the bottom of the screen. Another common pattern is a “modal” (or “dialog”) that covers the whole screen. To display them correctly, render them in a <a target=\"_blank\" rel=\"noopener\" href=\"https://reactjs.org/docs/portals.html\">portal</a>, as in React.</p><p>Use the JSDoc comment @uxpinuseportal to enable this behavior in UXPin Preview mode:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpinuseportal\n */\nfunction Dialog(props) {\n}"}]},"language":null}},{"__typename":"PrismicDocsPageBodyTip","slice_type":"tip","primary":{"tip_type":"Info tip","tip_title":null,"tip":{"html":"<p>Portal components can be dropped anywhere on the canvas, no matter their position in the UXPin Editor.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Mark components by comment</h3><p>Merge reads component properties from the default export of a class or function. If the export is not a function or class that exposes its own props, but is wrapped by another function, Merge can’t read the properties. In that case it also can’t display the Properties panel.</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"export default withAppProvider<Props>()(Button);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>To solve this, add the JSDoc comment @uxpincomponent before the class or function that declares the component:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpincomponent\n */\nexport class Button extends React.PureComponent {\n  // ...\n}"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Namespaced components</h3><p>You can use nested components in your library. It means a component contains another component, as in this example:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import Autocomplete from '../Autocomplete';\n \nconst textField = (\n  <Autocomplete.ComboBox.TextField\n    onChange={this.updateText}\n    label=\"Tags\"\n    value={this.state.inputText}\n    placeholder=\"Vintage, cotton, summer\"\n  />\n);\n \nexport default (\n  <Autocomplete\n    allowMultiple\n    textField={textField}\n    listTitle=\"Suggested Tags\"\n  />\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>There are 3 levels of components here: the top-level Autocomplete, the second-level ComboBox and the third-level TextField. To handle this, declare the namespace in your components.</p><h4>Declare namespaced components</h4><p>Use the JSDoc comment @uxpinnamespace and declare the name of the parent component. In our example, declare the namespaces in the ComboBox and TextField components:</p><p><strong>ComboBox.jsx</strong></p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpinnamespace Autocomplete\n */\nexport class ComboBox extends React.PureComponent {\n  // ...\n}"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p><strong>TextField.jsx</strong></p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpinnamespace Autocomplete.ComboBox\n */\nexport class TextField extends React.PureComponent {\n  // ...\n}"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>The namespace for ComboBox is Autocomplete, because it’s a direct child of Autocomplete. The namespace for TextField is Autocomplete.ComboBox, because it’s on the third level from the top and its parent is ComboBox. This is how Merge supports multilevel nesting.</p><h4>Use namespaced components in a preset</h4><p>After adding @uxpinnamespace, you can use the components in presets the same way as in your application code. Import the top-level component and use the nested ones through it, as in the example above. You can also import TextField directly:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import Autocomplete from '../Autocomplete';\nimport TextField from '../components/ComboBox/components/TextField';\n\nconst textField = (\n  <TextField\n    onChange={this.updateText}\n    label=\"Tags\"\n    value={this.state.inputText}\n    placeholder=\"Vintage, cotton, summer\"\n  />\n);\n\nexport default (\n  <Autocomplete\n    allowMultiple\n    textField={textField}\n    listTitle=\"Suggested Tags\"\n  />\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<h4>Use namespaced components in a JSX property</h4><p>Components declared this way can be used in the Properties panel as a value of node or element properties.</p>"}}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2F55c99856-f8d6-45fe-b7bf-c4494ab18a95_props-panel.png?w=752&h=1766?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2F55c99856-f8d6-45fe-b7bf-c4494ab18a95_props-panel.png?w=1504&h=3532"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<h4>Namespaced components in the library</h4><p>Namespaced components in the library panel display with their full namespace name.</p>"}}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2F178a4166-dcc1-442f-af71-e35fbb20d5d6_library.png?w=752&h=554?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2F178a4166-dcc1-442f-af71-e35fbb20d5d6_library.png?w=1504&h=1108"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Resizing components</h3><p>The presentation of code components in UXPin may need adjusting, especially their size. Sometimes the bounding box of a code component is larger than the element itself (skip container). In other cases, you want to block resizing (non-resizable). Or you need both at the same time.</p>"}}},{"__typename":"PrismicDocsPageBodyVideo","slice_type":"video","primary":{"video_link":{"url":"https://uxpincommunity.cdn.prismic.io/uxpincommunity%2F16ecec01-3093-4a3b-ba50-ff85f49328ca_wrapper.mp4"},"video_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h4>Skip container</h4><p>In some cases the bounding box of the code component in UXPin doesn’t match the real size of the element. To solve this, point Merge at a specific HTML node. By default Merge uses the root node of the component. Pass the uxpinRef property, which Merge sends to the component along with the regular props, to the React ref attribute:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpinwrappers\n * SkipContainerWrapper\n */\nconst Button = ({ greeting = 'Hello', uxpinRef }) => (\n  <div>\n    <button className=\"btn\" ref={uxpinRef}>{greeting} 👋</button>\n  </div>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<h4>Non-resizable component</h4><p>Some code components aren’t resizable. Mark such a component as non-resizable, and the resize handles won’t appear in the UXPin Editor.</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpinwrappers\n * NonResizableWrapper\n */\nconst Button = ({ greeting = 'Hello' }) => (\n  <div>\n    <button className=\"btn\">{greeting} 👋</button>\n  </div>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<h4>Combined cases</h4><p>You can use both actions for the same component:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpinwrappers\n * SkipContainerWrapper, NonResizableWrapper\n */"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Interaction triggered on property change</h3><p>In many cases, the designer wants to use a value from the prototype to update its content. So there has to be a way to bind, store and use values between components and UXPin.</p><p>@uxpinbind binds an interaction to a specific property of the component. In the Editor, every property with a defined binding is available as an interaction trigger for the selected code component. It allows the designer to:</p><ul><li>trigger interactions based on the user’s input,</li><li>get the value the user provided and store it as a property,</li><li>create conditional interactions.</li></ul><p>Example of a bound interaction:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"Checkbox.propTypes = {\n  onChange: PropTypes.func,\n  /**\n   * @uxpinbind onChange 0.target.checked\n   */\n  isChecked: PropTypes.bool,\n};"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<h4>Example: replace content based on the active tab</h4><p>In Material UI there’s a component named Tabs, which creates navigation based on tabs. It contains other components as children: Tab. A designer may want to show specific content, say a Card, based on the selected Tab. By default UXPin can’t get the value of the selected tab from Tabs, so you use @uxpinbind.</p><p>First, check the component’s documentation. Here you bind two properties: onChange and value. The goal is an interaction in UXPin that triggers on onChange once the value changes. Next, add the @uxpinbind annotation to the property that triggers the interaction. It needs the parameter to bind. For Tabs you want the value of the property, so use the second parameter of onChange:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"Tabs.propTypes = {\n  onChange: PropTypes.func,\n  /**\n   * @uxpinbind onChange 1\n   */\n  value: PropTypes.any,\n};"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyVideo","slice_type":"video","primary":{"video_link":{"url":"https://uxpincommunity.cdn.prismic.io/uxpincommunity/4351a33c-d5c4-45a7-986f-4175c74ab79d_add_bind.mp4"},"video_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>Once @uxpinbind is defined, the designer can create an interaction that uses the value as a trigger for the onChange interaction.</p>"}}},{"__typename":"PrismicDocsPageBodyVideo","slice_type":"video","primary":{"video_link":{"url":"https://uxpincommunity.cdn.prismic.io/uxpincommunity/5aa0c407-054f-473a-852b-e5284984e292_bind.mp4"},"video_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":"Configuring the Properties Panel"},"content":{"html":"<p>When a React component is integrated with UXPin using Merge, Merge reads all its properties with their names from the code. As a result, the Properties panel can be hard to read and show many properties that a designer doesn’t need. You can clean it up with JSDoc comments in your code. Hide properties, give them friendlier names and descriptions, and choose the right control for each.</p>"}}},{"__typename":"PrismicDocsPageBodyTable","slice_type":"table","primary":{"table_first_title":{"text":"Tag"},"table_second_title":{"text":"What it does"}},"items":[{"col1":{"html":"<p>@uxpinignoreprop</p>"},"col2":{"html":"<p>Hides a property from the Properties panel.</p>"}},{"col1":{"html":"<p>@uxpinpropname</p>"},"col2":{"html":"<p>Shows an alternative name for a property.</p>"}},{"col1":{"html":"<p>@uxpindescription</p>"},"col2":{"html":"<p>Shows an alternative description for a property, or a description of the component.</p>"}},{"col1":{"html":"<p>@uxpincontroltype</p>"},"col2":{"html":"<p>Changes the control used to edit a property.</p>"}},{"col1":{"html":"<p>@uxpindocurl</p>"},"col2":{"html":"<p>Adds a link to the component’s documentation.</p>"}}]},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Excluding properties</h3><p>You can exclude a property from the Properties panel, so it won’t be visible in the controls mode. Use the @uxpinignoreprop comment before the property you want to exclude:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"BarChart.propTypes = {\n  width: PropTypes.number,\n  height: PropTypes.number,\n  /** @uxpinignoreprop */\n  onSeriesMouseOver: PropTypes.func,\n};"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>Thanks to this comment, onSeriesMouseOver isn’t displayed in the Properties panel in either mode, controls or code.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Alternative names</h3><p>Sometimes a property has a very technical name. You can set an alternative name that displays in the controls mode of the Properties panel. Use the @uxpinpropname comment before the property:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"Button.propTypes = {\n  /**\n   * Icon that goes after the children\n   * @uxpinpropname right icon\n   */\n  iconEnd: PropTypes.element,\n  /**\n   * Icon that goes before the children\n   * @uxpinpropname left icon\n   */\n  iconStart: PropTypes.element,\n};"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2Fac8a777e-0b1f-451a-8dbf-268c35237b26_screenshot+2019-06-17+15.52.31.png?w=752&h=610?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2Fac8a777e-0b1f-451a-8dbf-268c35237b26_screenshot+2019-06-17+15.52.31.png?w=1504&h=1219"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Alternative descriptions</h3><p>You can also overwrite a property description to make it more user friendly. Set an alternative description for the property in the controls mode of the Properties panel with the @uxpindescription comment before the property:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"BarChart.propTypes = {\n  /**\n   * Width of the Chart in px. Accepts only numbers.\n   * @uxpindescription width of the chart\n   */\n  width: PropTypes.number,\n  /**\n   * Height of the Chart in px. Accepts only numbers.\n   * @uxpindescription height of the chart\n   */\n  height: PropTypes.number,\n};"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2Fd1e84c2a-5b74-41d2-8e1a-8f7125d73a31_screen-crop.png?rect=0%2C0%2C924%2C606&w=752&h=493?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2Fd1e84c2a-5b74-41d2-8e1a-8f7125d73a31_screen-crop.png?w=1504&h=985"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Component description and documentation link</h3><p>You can also describe the whole component. Use @uxpindescription and @uxpindocurl in the comment before the component:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * @uxpindescription A button that triggers an action.\n * @uxpindocurl https://example.com/docs/button\n */\nfunction Button(props) {\n  // ...\n}"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>The component description, including the library and branch name, is visible in the Properties panel, together with the documentation link.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Control types</h3><p>UXPin offers controls to handle a component’s properties. They are displayed in the Properties panel.</p>"}}},{"__typename":"PrismicDocsPageBodyTable","slice_type":"table","primary":{"table_first_title":{"text":"Control"},"table_second_title":{"text":"What it displays"}},"items":[{"col1":{"html":"<p>codeeditor</p>"},"col2":{"html":"<p>The code editor.</p>"}},{"col1":{"html":"<p>input</p>"},"col2":{"html":"<p>A single-line input.</p>"}},{"col1":{"html":"<p>interactions</p>"},"col2":{"html":"<p>A button to add a new interaction, or a list of interactions.</p>"}},{"col1":{"html":"<p>number</p>"},"col2":{"html":"<p>A short input that accepts only numbers.</p>"}},{"col1":{"html":"<p>select</p>"},"col2":{"html":"<p>A select list with options.</p>"}},{"col1":{"html":"<p>switcher</p>"},"col2":{"html":"<p>A checkbox.</p>"}},{"col1":{"html":"<p>textfield(x)</p>"},"col2":{"html":"<p>A textarea with multiple lines, where x is the line count. You don’t have to pass x: the control has 3 rows by default.</p>"}},{"col1":{"html":"<p>color</p>"},"col2":{"html":"<p>A color picker.</p>"}},{"col1":{"html":"<p>image</p>"},"col2":{"html":"<p>An upload button for selecting an image from your device and an input for an image URL.</p>"}},{"col1":{"html":"<p>css</p>"},"col2":{"html":"<p>Controls for adjusting a component’s visual styling through CSS properties.</p>"}},{"col1":{"html":"<p>materialicons</p>"},"col2":{"html":"<p>A control for Material icons.</p>"}},{"col1":{"html":"<p>tailwindclassname()</p>"},"col2":{"html":"<p>A control for Tailwind class names.</p>"}},{"col1":{"html":"<p>returningfunction()</p>"},"col2":{"html":"<p>A control for properties that are functions returning a value.</p>"}}]},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>Each property type has a specific default control:</p>"}}},{"__typename":"PrismicDocsPageBodyTable","slice_type":"table","primary":{"table_first_title":{"text":"Property type"},"table_second_title":{"text":"Default control"}},"items":[{"col1":{"html":"<p>Boolean</p>"},"col2":{"html":"<p>switcher</p>"}},{"col1":{"html":"<p>Children</p>"},"col2":{"html":"<p>textfield(4)</p>"}},{"col1":{"html":"<p>Node or element</p>"},"col2":{"html":"<p>textfield(3)</p>"}},{"col1":{"html":"<p>Text</p>"},"col2":{"html":"<p>input</p>"}},{"col1":{"html":"<p>Number</p>"},"col2":{"html":"<p>number</p>"}},{"col1":{"html":"<p>oneOf</p>"},"col2":{"html":"<p>select</p>"}},{"col1":{"html":"<p>Array, shape</p>"},"col2":{"html":"<p>codeeditor</p>"}},{"col1":{"html":"<p>Function</p>"},"col2":{"html":"<p>interactions</p>"}}]},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>Sometimes the default control doesn’t fit the property, or the usability is poor. Use the @uxpincontroltype comment where you declare the property to change its control. If the control type matches the property type, the new control is displayed in the Properties panel:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"Link.propTypes = {\n  /**\n   * Content of the Link\n   * @uxpinpropname label\n   * @uxpincontroltype input\n   */\n  children: PropTypes.node,\n  /**\n   * A URL or URL fragment to which the Link points\n   * @uxpinpropname url\n   * @uxpincontroltype textfield(2)\n   */\n  href: PropTypes.string,\n  /** Available variants */\n  variant: PropTypes.oneOf(['danger', 'success', 'warning']),\n};"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2F83f189f7-c4c3-4d61-b3a0-c67907cf4e20_declare+property+control+type.png?w=752&h=316?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2F83f189f7-c4c3-4d61-b3a0-c67907cf4e20_declare+property+control+type.png?w=1504&h=633"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Example: a cleaner panel</h3><p>With JSDoc annotations you can make the Properties panel cleaner and more designer-friendly: hide properties that only developers need, rename others and make controls more usable. Here’s an excerpt from a Select component. Without annotations, the panel would show a long list of properties, most of them unnecessary. With the annotations, only the ones the designer needs are shown:</p>"}}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2F7c4bdd95-c16e-4f86-89ab-0874d8e635da_example-1.png?w=752&h=844?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2F7c4bdd95-c16e-4f86-89ab-0874d8e635da_example-1.png?w=1504&h=1689"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyImageWithCaption","slice_type":"image_with_caption","primary":{"image":{"url":"https://images.prismic.io/uxpincommunity%2F44e793fb-3c0e-4387-b10a-46198b9c038d_example-2.png?w=752&h=608?auto=compress,format","Retina__2x_":{"url":"https://prismic-io.s3.amazonaws.com/uxpincommunity%2F44e793fb-3c0e-4387-b10a-46198b9c038d_example-2.png?w=1504&h=1215"}},"image_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"/**\n * Open the Select upon initialization. Primarily for use with uncontrolled components.\n * @uxpinignoreprop\n */\ndefaultIsOpen?: boolean,\n/** Disables the control */\ndisabled?: boolean,\n/**\n * Determines whether the Select is open. For use with controlled components.\n * @uxpinpropname opened\n * @uxpindescription Open options list\n */\nisOpen?: boolean,\n/** Text displayed when there is no item selected */\nplaceholder?: string,\n/** Available sizes */\nsize?: 'small' | 'medium' | 'large' | 'jumbo',"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":"Authoring and Managing JSX Presets"},"content":{"html":"<p>A preset tells Merge how to render a component the first time. Merge needs to know which combination of properties, including children, should be displayed by default. That composition appears whenever you, or anyone on your team, drag and drop the component onto the canvas in the UXPin Editor. A preset is a JSX file stored with the component.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Where presets live</h3><p>Store presets in a presets subdirectory of the component’s directory, as you can see in the <a target=\"_blank\" rel=\"noopener\" href=\"https://github.com/uxpin-merge/uxpin-merge-boilerplate\">boilerplate repository</a>. A preset file name is a number, a dash and a name, such as 0-default.jsx.</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"src/components/Button/\n  Button.jsx\n  presets/\n    0-default.jsx"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>A basic preset</h3><p>A typical preset looks like this:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport Button from '../Button';\nimport Icon from '../../Icon/Icon';\n\nexport default (\n  <Button\n    uxpId=\"button1\"\n    icon={<Icon icon=\"TickerSvg\" size=\"s\" />}\n    mode=\"filled\"\n    size=\"s\"\n    stretched\n    type=\"error\"\n  >\n    Merge!\n  </Button>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>At the top of the file, import React and all the components you want to represent in the preset. In export default(), place the JSX that represents the default composition of your component. Every component in the JSX, apart from its usual properties, must have a unique UXPin ID attribute, uxpId. The uxpId lets Merge render every component properly and track overrides of components.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>IDs and nested components</h3><p>Presets can represent complex, nested structures of components. All uxpId attributes must hold unique values: in one preset, two components can’t have the same uxpId. Beyond that, creating presets for nested structures works like composing JSX in React components. Import all the components and create the full structure in the export default() directive:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport SelectItem from '../../SelectItem/SelectItem';\nimport Select from '../Select';\n\nexport default (\n  <Select uxpId=\"select1\">\n    <SelectItem uxpId=\"select.item.1\">Option 1</SelectItem>\n    <SelectItem uxpId=\"select.item.2\">Option 2</SelectItem>\n    <SelectItem uxpId=\"select.item.3\">Option 3</SelectItem>\n  </Select>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>When you choose a uxpId, think about the role the component plays. If you later replace one nested component with another, say a Button is deprecated and replaced with ButtonNew, keeping the same uxpId lets Merge automatically update all designs with the new component.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Multiple presets for one component</h3><p>A component can have more than one preset. Add more files to the presets directory. The number sets the order, and the part after the dash is the preset name:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"presets/\n  0-default.jsx\n  1-secondary.jsx"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Another way to store presets</h3><p>Instead of the presets directory, you can put one preset in a file named after the component in a uxpin-presets directory, for example uxpin-presets/Button.jsx. If that file exists, Merge uses it.</p><p>To create preset files automatically, run npx uxpin-merge generate-presets. It reads your config file and generates a preset file for each component. Add --component-path &lt;path&gt; to generate one for a single component.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Overrides</h3><p>A change in a preset’s code is automatically reflected in the design systems library in the UXPin Editor. Merge modifies all properties, unless a user changed a property of a given component in the UXPin Editor. Such a change is treated as an override and stays intact. Take this example.</p>"}}},{"__typename":"PrismicDocsPageBodyVideo","slice_type":"video","primary":{"video_link":{"url":"https://uxpincommunity.cdn.prismic.io/uxpincommunity%2F5e8714e6-881b-4e02-b89a-eac64f19519b_merge_button_comparison.mp4"},"video_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>At first, the default preset for a button looked like this:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport Button from '../Button';\n\nexport default (\n  <Button\n    uxpId=\"action1\"\n    size=\"small\"\n    variant=\"contained\"\n    color=\"primary\"\n    fullWidth\n  >\n    Click me\n  </Button>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>A user dragged this element to the canvas in UXPin and, in the Editor, changed the property size to large and the color to secondary. Then, say by the decision of the design systems team, the default preset for Button was modified to:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport Button from '../Button';\n\nexport default (\n  <Button\n    uxpId=\"action1\"\n    size=\"medium\"\n    variant=\"contained\"\n    color=\"primary\"\n    fullWidth\n  >\n    Click me\n  </Button>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>What happened to the design the user created in the UXPin Editor with this React button? Nothing. The properties that were changed had been overridden by the user, and Merge preserved those changes to keep the design intact.</p><p>Now say the default label changed as well. The user hasn’t overridden this property. Merge updates the user’s project:</p>"}}},{"__typename":"PrismicDocsPageBodyVideo","slice_type":"video","primary":{"video_link":{"url":"https://images.prismic.io/uxpincommunity%2Fb3f17202-9694-4d0a-b318-bc0125de4637_merge_label_update.gif?auto=compress,format"},"video_description":{"text":null}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>Merge always compares changes in the code of JSX presets with the implementation, to determine whether the user’s design needs an update.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>Property requirements</h3><p>The content of all properties in JSX presets must be serializable as JSON. You can write custom functions and manipulate data in the preset file, but the end result must be serializable. JSX passed in object and array properties is also supported.</p><p>This JSX preset is valid:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport Button from '../Button';\n\nconst customFunction = () => 'HelloWorld';\n\nexport default (\n  <Button uxpId=\"signup1\" size=\"large\" custom={customFunction()}>\n    Signup Now!\n  </Button>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>This one is incorrect, because passing a function through props is currently unsupported:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport Button from '../Button';\n\nconst customFunction = () => 'HelloWorld';\n\nexport default (\n  <Button uxpId=\"signup1\" size=\"large\" custom={customFunction}>\n    Signup Now!\n  </Button>\n);"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>In preset files you can import and modify data sets used by your component:</p>"}}},{"__typename":"PrismicDocsPageBodyCode","slice_type":"code","primary":{"code":{"raw":[{"text":"import React from 'react';\nimport Table from '../Table';\n\nconst tableData = {\n  header: ['band', 'singer', 'lead guitar'],\n  body: [\n    { band: 'metallica', singer: 'james hetfield', 'lead guitar': 'kirk hammet' },\n    { band: 'queen', singer: 'freddy mercury', 'lead guitar': 'brian may' },\n  ],\n};\n\nexport default <Table data={tableData} uxpId=\"table1\" width=\"stretched\" />;"}]},"language":"JavaScript"}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":null},"content":{"html":"<p>This is a valid JSX preset. You can also import the data from an external JS or JSON file.</p>"}}},{"__typename":"PrismicDocsPageBodyContent","slice_type":"content","primary":{"content_title":{"text":""},"content":{"html":"<h3>A word of caution</h3><p>Merge presets are powerful, and with that power comes responsibility. Remember that changes in a preset update designs, unless the properties were overridden in a particular project in UXPin.</p>"}}}]}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"categoryUid":"merge","pageUid":"for-developers","meta_description":"UXPin's merge Docs, for developers for new and advanced users","meta_image":"https://images.prismic.io/uxpincommunity/fa3875f8df8606e6405ba46165becc1ea6ed3d34.png?auto=compress,format","meta_title":"For Developers | Merge","page_title":"For Developers | Merge"}}