Let's look at how easy it is to integrate a React-based library into Merge to design with code on a day-to-day basis. All that without designers learning how to code!
UXPin Merge lets designers import developerās existing custom React components in a seamless fashion to create interactive prototypes using real code, which is unlike anything else traditional design tools offer.
This eliminates the need for designers to manually maintain a āsecondā design system within their design tool and instead provides the entire team with a single source of truth. The result? The disconnect between designers and developers is gone when building digital products.Ā
We want to save you time so weāve designed this tutorial to integrate Mozillaās React Todo App exampleĀ with Merge. After the integration, youāll be able to use the appās components to design an interactive Todo list prototype within UXPin!
Remember to start by requesting access to Merge ā you canĀ do it here. After the verification process and the setup, youāll be ready to design with code! Also, donāt worry about integrating with GitHub ā we donāt have any requirement of where the codebase should be located, so you can use whatever you want!
The components
The Todo app has three React components:
- FormĀ ā create a todo item.
- FilterButtonĀ ā filter todos by their current state.
- TodoĀ ā a todo list item.
These components are in the `src/components` directory and are outlined in the screenshot below:
When this tutorial is completed, a designer will be able to create a prototype with these components. Your real-world custom design system (DS) likely has many more than three components. However, the concepts weāll illustrate in this tutorial should apply to your DS as well.
Setup UXPin Merge
To begin, fork then clones the following linkĀ https://github.com/mdn/todo-react. Then install our UXPin Merge NodeJS package, which includes our CLI.
- NavigateĀ into your project folder cd todo-react
- InstallĀ UXPin Merge and Itās CLI NodeJS bundle with:Ā yarn add @uxpin/merge-cliādev
- IgnoreĀ the UXPin Merge build directory with:Ā echo ā/.uxpin-mergeā >> .gitignore
A custom design system requires two additional config files:
- uxpin.webpack.config.js
- uxpin.config.js
UXPin typically doesnāt need to use your entire existing Webpack build process. Weāll use a more minimal and default build for UXPin. Create a uxpin.webpack.config.js file and paste the following code into it:
const path = require("path");
const webpack = require("webpack");
module.exports = {
output: {
path: path.resolve(__dirname, "build"),
filename: "bundle.js",
publicPath: "/"
},
resolve: {
modules: [__dirname, "node_modules"],
extensions: ["*", ".js", ".jsx"]
},
devtool: "source-map",
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
]
},
{
loader: "babel-loader",
test: /\.js?$/,
exclude: /node_modules/,
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
}
},
]
}
}
For components you want to use in UXPin merge, you must specify their file directory in the uxpin.config.js file at the top of the directory of the repo. As you can see in the code snippet below, weāve only added the āFormā component src/components/Form.jsĀ for now and will add the other components later in the tutorial.Ā
Create a uxpin.config.js and paste the following content into the file:
module.exports = {
components: {
categories: [
{
name: 'General',
include: [
'src/components/Form.js',
]
}
],
webpackConfig: 'uxpin.webpack.config.js',
},
name: 'Learn UXPin Merge - React Todo list tutorial'
};
ļ»æ
Lastly, Babel-loader will be used by Webpack to create the app bundle. To install babel use the following commands:Ā yarn add babel-loader ādev thenĀ yarn installĀ .
CONGRATULATIONSš Youāre all good to go and have the minimum configuration required to view the Form component.
Experimental Mode
Experimental Mode lets us prototype with our local components to verify their behavior before pushing to UXPin. Now, to open UXPin Merge Experimental mode to preview the Form component, runĀ ./node_modules/@uxpin/merge-cli/bin/uxpin-merge ādisable-tunneling. In Experimental Mode, usingĀ ādisableātunnelingĀ makes requests go directly to your localhost web server. Quick note: UXPin withĀ ādisable-tunnelingĀ option works only in Chrome .Ā
Using the settings provided in `uxpin.webpack.config.js`, Experimental mode bundles your components and opens a browser window. You can lay out components in a similar fashion as the UXPin Editor. After Experimental Mode loads, drag and drop the Form component from the sidebar onto the project canvas:
Using a Global Wrapper Component to apply CSS styles
Just like your custom design system, this Todo app contains global styles. These are specified in the `src/index.css` file. All of our components need the styles specified in this file. We can load this file via a Global Wrapper Component. This component will wrap around every component we drag onto the UXPin canvas.
Create a wrapper file:
mkdir src/wrapper/Ā
touch src/wrapper/uxpinwrapper.js
Copy and paste the following into `UXPinWrapper.js`:
import React from "react";
import '../index.css';
export default function UXPinWrapper({ children }) {
return children;
}
The `import ā../index.cssā;` line ensures our CSS styles are loaded prior to rendering each component.
We need to tell UXPin to use this wrapper file. Add the following to uxpin.config.js:
wrapper: 'src/wrapper/UXPinWrapper.js',
In your terminal, restart UXPin Experimental mode usingĀ ./node_modules/@uxpin/merge-cli/bin/uxpin-merge ādisable-tunneling.Ā A restart is required when updating the config file. A browser reload is only required when updating components.
Experimental mode should open a new browser window with a styled Form component:
Adding the FilterButton with a customizable name
Now weāll work on adding the FilterButton to UXPin Merge. These buttons are displayed below the Form component:
Adding this component will be similar to the Form component. However, Iād also like to give designers the ability to specify the text that is displayed within the button. Weāll do that via the `prop-types` package.
Component propTypes are mapped to the UXPin properties panel when editing a component. The existing FilterButton component doesnāt use prop-types so letās add this to `FilterButton.js`:
import React from "react";
+ import PropTypes from 'prop-types';
function FilterButton(props) {
return (
@@ -15,4 +16,9 @@ function FilterButton(props) {
);
}
+ FilterButton.propTypes = {
+ name: PropTypes.string
+ }
+FilterButton.defaultProps = {
+ name: 'Button Name'
+};
export default FilterButton;
Add `āsrc/components/FilterButton.jsā` to `uxpin.config.js` and restart usingĀ ./node_modules/@uxpin/merge-cli/bin/uxpin-merge ādisable-tunneling. A restart is required as weāve updated the config file. When Experimental Mode starts, you should see a new āFilterButtonā component listed in the sidebar. Click and drag this onto the canvas.
Two of our three components are now working with UXPin Merge. We have one component remaining: the Todo component.
Adding the Todo component with a wrapper
Weāre moving on to our final component: the Todo. These are displayed within the list of todo items in the UI:
When adding the FilterButton, we edited the FilterButton.js file to add propTypes. What if you want to isolate your Merge-specific changes and donāt want to modify the source code of your components? We can create a wrapper that is specific to the Todo component for this. Itās similar in concept to the Global wrapper component we used to apply CSS styles but will be specific to the Todo component.
Type the following:
mkdir -p src/components/merge/todoĀ
touch src/components/merge/todo/Todo.js
Copy and paste the following code into Todo.js.Ā
import React from 'react';
import PropTypes from 'prop-types';
// Import the original component
import TodoM from '../../Todo';
function Todo(props) {
return <TodoM {...props}/>
}
Todo.propTypes = {
/**
* If `true`, the todo will be marked as completed.
*/
completed: PropTypes.bool,
/**
* The name of the todo.
*/
name: PropTypes.string,
toggleTaskCompleted: PropTypes.func,
}
Todo.defaultProps = {
name: 'Do Laundry'
};
export default Todo;
Weāre importing the original Todo component as `TodoM` and returning this component in our newly defined `Todo` function. We specify propTypes just like we did with the FilterButton component on our newly defined `Todo` wrapper function.
Add āsrc/components/merge/todo/Todo.jsā to uxpin.config.js and restart usingĀ ./node_modules/@uxpin/merge-cli/bin/uxpin-merge ādisable-tunneling. After Experimental launches a new window, click-and-drag the Todo component onto the canvas:
Youāll see the Todo component along with the default āDo Laundryā todo name. This default name is only applied when using Merge.
Pushing to UXPin
Until you push your design system to UXPin the components are only visible to you. To let your design team use these components we need to push the component bundle to UXPin. Creating and pushing a Merge design library requires two steps:
1. Create the library within the UXPin UI
a. Go to your UXPin account
b. Enter the UXPin Editor
c. Create a new library
d. Select the option import React components
e. Copy the Auth token (donāt share it with anyone and do not place it in any files checked into git repository. This token provides direct access to the library on your account.) The process looks like this:
2. Push the library via the uxpin-merge CLI
Using the token created from the previous stop, run the following from within the project repo:
./node_modules/@uxpin/merge-cli/bin/uxpin-merge push ātoken YOUR TOKENĀ
Your design team can now access the Merge library.
Using the Merge library within UXPin
Now that the Merge design library has been pushed its time to test it out within the UXPin editor:
- Reload the UXPin Editor in your browser.
- Select the āLearn UXPin Mergeā design system in the bottom left corner of the editor.
- Click and drag the components from the sidebar to the canvas.
You should have a solid looking prototype:
How does a designer hand off a prototype back to a developer?
Previewing and exporting
Now that weāve built a quick prototype in UXPin weāre ready to export it back to our app. We can preview the output and then useĀ Spec modeĀ to copy and paste the JSX code for our components.
Click the play button in the upper right corner of the editor. Once the preview loads click the āSpecā link at the top. You can now click on the components and view the JSX code to generate them in the right panel:
Itās great to push an initial version of our design system. However, youāll likely need to push out quite a few updates over time.
Pushing an update
The FilterButton has a āpressedā state to indicate the currently active filter. Looking at the live React app, hereās the difference between the pressed and not-pressed state:
Letās add support for this state. Make the following change to `src/components/FilterButton.js`:
FilterButton.propTypes = {
- name: PropTypes.string
+ name: PropTypes.string,
+ isPressed: PropTypes.bool
}
Commit the change to git and push to UXPin:
git add.Ā
git commit -m āAdded isPressed prop to buttonāĀ
./node_modules/@uxpin/merge-cli/bin/uxpin-merge push ātoken YOUR TOKEN
Merge components are automatically synced to the most recently pushed code. To show the latest, reload the tab showing the UXPin editor. Select a FilterButton. In the right panel of the editor you should see a new āisPressedā property. Select it to activate this state:
Follow this same flow (git commit + uxpin-push) when you make future changes. Prototypes will automatically use the latest pushed version of components.
Summary
Youāve taken a React app and pushed its components to UXPin Merge. Youāve also learned how to push updates when you modify components or add new ones. Now your design team can use these components to create high-fidelity prototypes within the UXPin editor.
You can browse the source code for this project onĀ GitHub. To learn more advanced Merge techniques see ourĀ Merge docsĀ or reach out to us at [email protected].
Donāt have UXPin Merge yet? First, remember to go through the process of requesting access to make the most of designing with code!
Previously published at https://www.uxpin.com/studio/blog/design-with-code-tutorial/