Utopia is an integrated design and development environment for React.

Last update: Jul 29, 2022

All Contributors

Welcome to Utopia 🏝

Utopia is an integrated design and development environment for React. It uses React code as the source of truth, and lets you make real time changes to components by editing it and using a suite of design tools. It's early software, but you can try it today, look at an example project, or read about it on our blog!

Try Utopia Now!

screenshot of utopia

Start the editor

For contributors: Installing Utopia on your machine

Utopia is browser-based. To run it locally, clone the repo, and then set up the server and webpack by following these instructions.

⚠️ We're looking into M1 related issues for some folks, but have it running successfully on three machine

Prerequisites

  • If using Windows you'll first need to set up the Windows Subsystem for Linux (wsl). All following steps and commands will assume you are using the wsl.
  • On macOS you need brew and must run brew install gmp first. On new M1 Macbooks please follow these steps to install brew and run the server the first time.
  • nix-shell. If you are on macOS Catalina or later, you will be prompted to include an extra flag in the install script. If using Windows follow this guide. If you don't want to use nix, we have instructions here
  • Recommended: direnv. If you don't have direnv installed, you'll need to run nix-shell before any of the start commands, and switching to nix will be a bit slower.

Contributing and Bug Reporting

We welcome contributions. Utopia is a big project, but we're here to help, and are happy to pair up with you. The easiest way is to file an issue, or reach out on Discord. Please read our contributing doc to get started

Run the Editor

The first time running the editor, run the following script:

start-full

Subsequently it should be possible to just run, unless either changes have been made to VS Code or something like the dependencies have changed in the editor project:

start-minimal

Both of these scripts result in a tmux session with all of the various servers running and watching for changes. You can see all of the active sessions in the bar along the bottom, prefixed by the "window" number that they are running in. You should be able to click on each of those to switch to viewing that session, or if that doesn't work you can use the key combo cmd+b (macOS) or ctrl+b (Linux or Windows), followed by the number for that session. (see here for the relevant tmux docs)

To shut them down, in the "Scratchpad" tab of the session run the following command:

stop-dev

Finally, loading the running application

Now the editor should load on localhost:8000/p, or localhost:8000 when developing the website itself.

Pull request bundle support.

When a series of environment variables are set (see Branches.hs), the editor supports the ability to get a bundle of editor code from S3 that was created from a PR, and load that instead of the code currently held locally. Which means that changes can be tested without spinning up multiple environments.

To use this if the URL currently is https://utopia.pizza/p/e976df60-phase-rutabaga/, the branch name would be added on in a query parameter like so: https://utopia.pizza/p/e976df60-phase-rutabaga/?branch_name=my-test-branch.

Limitations:

  • Doesn't currently support Monaco because of the way that builds the workers in a special webpack plugin, so changes to the version of Monaco in that branch may fail in unusual ways.
  • Anything that isn't editor code will not be changed by this, such as the website code or the server endpoints.

Troubleshooting

M1 Macbook

There are some extra steps to build server files, steps 11-14 are also needed when there are dependency changes for the server.

  1. Open Applications, locate the Terminal within the Utilities folder
  2. Select Terminal.app and right-click on it then “Duplicate”
  3. Rename the duplicated Terminal app to ‘Rosetta Terminal’
  4. Now select the new renamed ‘Rosetta Terminal’, right-click and choose “Get Info”
  5. Check the box for “Open using Rosetta”, then close the Get Info window
  6. Run the Rosetta Terminal
  7. Type arch first to make sure your terminal is good, this should show i386 in the Rosetta Terminal
  8. Install homebrew there, please add arch -x86_64 before pasting the install script
  9. Install gmp with arch -x86_64 /usr/local/bin/brew install gmp
  10. Close with cmd+q, open a normal Terminal and install direnv and nix-shell as the description, then come back for the final 4 steps
  11. Run the Rosetta Terminal again
  12. Enter the utopia folder, direnv and run the start-website-server to build the server files here
  13. After you see a message about Startup Processes Completed exit terminal with cmd+q
  14. Open a normal Terminal, run the start script in the utopia folder.

fsevents

If you notice that 1 or more CPU cores are running 100% because of node processes, it is probably webpack-dev-server having trouble with fsevents on MacOS. To fix it, run npm install fsevents in the utopia/editor directory. see https://github.com/webpack/webpack/issues/701#issuecomment-216082726

Running this without Nix

You'll need four things running concurrently:

editor/npm run webpack
editor/npx tsc --watch
Website/npm start
server/cabal new-run --disable-optimization --disable-profiling --disable-documentation --disable-library-coverage --disable-benchmarks utopia-web -- +RTS -N

Using direnv to make your life easier

Since a lot of this requires using nix-shell everywhere, you can just use direnv to make that a lot simpler. Not only will this automatically use a nix shell whenever you cd into the project folder, but it also adds caching to vastly speed up the opening of that shell. You can install direnv by using brew:

brew install direnv

To actually run direnv you need to hook it into your shell by following the instructions here.

Then to configure it, in your $HOME directory add a file .direnvrc with the following contents (copied from https://github.com/direnv/direnv/wiki/Nix#using-a-global-use_nix-with-garbage-collection-prevention):

"$cache" update_drv=1 else log_status using cached derivation fi local term_backup=$TERM path_backup=$PATH if [ -n ${TMPDIR+x} ]; then local tmp_backup=$TMPDIR fi eval "$(< $cache)" export PATH=$PATH:$path_backup TERM=$term_backup TMPDIR=$tmp_backup if [ -n ${tmp_backup+x} ]; then export TMPDIR=${tmp_backup} else unset TMPDIR fi # `nix-shell --pure` sets invalid ssl certificate paths if [ "${SSL_CERT_FILE:-}" = /no-cert-file.crt ]; then unset SSL_CERT_FILE fi if [ "${NIX_SSL_CERT_FILE:-}" = /no-cert-file.crt ]; then unset NIX_SSL_CERT_FILE fi # This part is based on https://discourse.nixos.org/t/what-is-the-best-dev-workflow-around-nix-shell/418/4 if [ "$out" ] && (( $update_drv )); then local drv_link=".direnv/drv" local drv="$(nix show-derivation $out | grep -E -o -m1 '/nix/store/.*.drv')" local stripped_pwd=${PWD/\//} local escaped_pwd=${stripped_pwd//-/--} local escaped_pwd=${escaped_pwd//\//-} ln -fs "$drv" "$drv_link" ln -fs "$PWD/$drv_link" "/nix/var/nix/gcroots/per-user/$LOGNAME/$escaped_pwd" log_status renewed cache and derivation link fi if [[ $# = 0 ]]; then watch_file default.nix watch_file shell.nix fi } ">
use_nix() {
  local path="$(nix-instantiate --find-file nixpkgs)"

  if [ -f "${path}/.version-suffix" ]; then
    local version="$(< $path/.version-suffix)"
  elif [ -f "${path}/.git" ]; then
    local version="$(< $(< ${path}/.git/HEAD))"
  fi

  local cache=".direnv/cache-${version:-unknown}"

  local update_drv=0
  if [[ ! -e "$cache" ]] || \
    [[ "$HOME/.direnvrc" -nt "$cache" ]] || \
    [[ .envrc -nt "$cache" ]] || \
    [[ default.nix -nt "$cache" ]] || \
    [[ shell.nix -nt "$cache" ]];
  then
    [ -d .direnv ] || mkdir .direnv
    nix-shell --show-trace --pure "[email protected]" --run "\"$direnv\" dump bash" > "$cache"
    update_drv=1
  else
    log_status using cached derivation
  fi
  local term_backup=$TERM path_backup=$PATH
  if [ -n ${TMPDIR+x} ]; then
    local tmp_backup=$TMPDIR
  fi

  eval "$(< $cache)"
  export PATH=$PATH:$path_backup TERM=$term_backup TMPDIR=$tmp_backup
  if [ -n ${tmp_backup+x} ]; then
    export TMPDIR=${tmp_backup}
  else
    unset TMPDIR
  fi

  # `nix-shell --pure` sets invalid ssl certificate paths
  if [ "${SSL_CERT_FILE:-}" = /no-cert-file.crt ]; then
    unset SSL_CERT_FILE
  fi
  if [ "${NIX_SSL_CERT_FILE:-}" = /no-cert-file.crt ]; then
    unset NIX_SSL_CERT_FILE
  fi

  # This part is based on https://discourse.nixos.org/t/what-is-the-best-dev-workflow-around-nix-shell/418/4
  if [ "$out" ] && (( $update_drv )); then
    local drv_link=".direnv/drv"
    local drv="$(nix show-derivation $out | grep -E -o -m1 '/nix/store/.*.drv')"
    local stripped_pwd=${PWD/\//}
    local escaped_pwd=${stripped_pwd//-/--}
    local escaped_pwd=${escaped_pwd//\//-}
    ln -fs "$drv" "$drv_link"
    ln -fs "$PWD/$drv_link" "/nix/var/nix/gcroots/per-user/$LOGNAME/$escaped_pwd"
    log_status renewed cache and derivation link
  fi

  if [[ $# = 0 ]]; then
    watch_file default.nix
    watch_file shell.nix
  fi
}

And add a .envrc file to the root folder of the project with the following contents:

use nix

(This file is deliberately contained in the .gitignore because it is supposed to be personal to you - it allows you to add custom environment variables that will always be in scope whenever you're in this directory)

Please update your .zshrc (or .bashrc) to hook it into the shell, for example for zsh add this line:

eval "$(direnv hook zsh)"

After this step open a new shell window and enter the utopia directory. Direnv should be activated as soon as you enter, you can use the start and start-performance scripts without manually running nix-shell.

Unit Tests with Jest

One-off test run:

npm run test

Continuous mode:

npm run test-watch

On macOS, when trying to watch, you might run into an error message about number of open files. In that case, install watchman:

brew install watchman

VSCode linting, formatting with prettier etc

To enable format-on-save, you should install the VSCode plugin esbenp.prettier-vscode, and dbaeumer.vscode-eslint and then in your workspace settings, enable format on save, and tell prettier to use the eslint integration mode:

  "eslint.workingDirectories": ["./editor", "./utopia-api"],
  "editor.formatOnSave": true,
  "prettier.useEditorConfig": false,
  "prettier.requireConfig": true,
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }

Select prettier as the default formatter in your settings; VSCode may prompt you to do so. The last four line items, starting with [typescript] reflect this. You should restart VSCode after this.

Deploying

All pushes to the master branch will immediately trigger this workflow that runs the tests and then triggers a deploy to our Staging environment.

To deploy to the Production environment, somebody needs to manually trigger our tag-release.yml workflow, giving either a specific commit hash or branch name (defaulting to master), and optionally a tag name (the default behaviour is to increment the patch version). This can be triggered via the "Run Workflow" button here
Note: in the "Use workflow from" dropdown you have to select "Branch: master" - this is specifying which workflow to run, not which branch to cut the release from.

GitHub

https://github.com/concrete-utopia/utopia
Comments
  • 1. Feature/component button

    Problems

    • we need a prominent way to indicate if something you're editing is (or can be) "focused" (per terminology of the spike), even if the navigator is hidden
    • we have component-related functionality that's currently buried in the UI in the header section, but that - in a component-centric world - becomes more important; notably being able to change what a component is being "rendered as" (e.g. swapping out a FlexRow for a FlexColumn, a div for a Button ...)

    Solution: The Component Unibutton.

    image

    • introduces a prominent button atop the canvas, next to the formula bar
    • The button (a) indicates whether you're editing is an element, a component instance, or an "isolated" / "focused" component child of a component instance, (b) lets you isolate / focus a component - similar to the context menu entry in the spike
    • The button also shows a drop-down menu with the breadcrumb trail, and the option to change the component to another component (the "Render as" capability formerly shown in the inspector)

    Other changes

    • clean up inspector remove the header-section that formerly housed these
    • introduces element icons in an orange colorway for children-of-focused-components (to align with Sketch's treatment of these)
    • UX improvements to the PopupList used here (was using wrong mouse pointers, and not opening when clicking on the label)
    • Clean up the formula bar and container, since they didn't behave well with siblings / having > 1 child respectively

    NB: the button currently does not "do anything", since that will require functionality provided by the spike. Plus, the button has a nice background animation.

    Reviewed by OmarDaSilva at 2021-03-10 16:12
  • 2. Feature/inspector component section

    Added feature to the component section. Depending on the currently selected component, it will display different kinds of information on the inspector depending if it is an NPM imported component, focusable component, or non-focusable component. Non-npm components have an icon button to toggle focus.

    Screenshot 2021-04-26 at 14 01 59

    Screenshot 2021-05-12 at 15 49 30

    Screenshot 2021-05-12 at 15 50 11

    Reviewed by OmarDaSilva at 2021-04-21 17:08
  • 3. Introducing pnpm

    Problem: I couldn't bump us to Jest 27 because there were symlinks in the monorepo between packages and Jest were trying to resolve internal dependencies at the wrong place. This was a last straw kind of situation, we've been eyeing with pnpm before, as it promises to solve a lot of monorepo-related pains.

    The main promise of pnpm is that it gives us much more control about versions of packages in node_modules. It gives a much better understanding of transitive dependencies and conflicting transitive dependencies too.

    Here's an overview of how it works https://pnpm.io/symlinked-node-modules-structure

    PNPM TLDR

    the main difference between npm and pnpm is that npm tries to flatten the node_modules. This means that npm will try to put transitive dependencies in the node_modules/ root as well. In case of conflicting transitive dependencies, it will put them into sub-modules inside node_modules, such as node_modules/package-a/node_modules/transitive-package. This can then lead to npm doppelgangers https://rushjs.io/pages/advanced/npm_doppelgangers/

    Instead of this, what PNPM does is that it creates a pnpm repo at ~/.pnpm and installs every package there. in the specific node_modules folders, it only uses symlinks to point to the main repo. The benefit is that the node_modules folder doesn't need to be flattened in order to save space / install size. The structure can be a deep tree with every specific transitive dependency placed where it is linked in a package.json. So if a package has any transitive dependency, it will be installed as node_modules/package-a/node_modules/transitive-package but transitive-package will just be a symlink to ~/.pnpm/[email protected]<version-number>.

    In my opinion this is a best of both worlds kind of solution. It saves space, and makes the node_modules structure easier to debug. It also means that the node_modules structure is "strict": if you try to import/require a package that is not listed in your dependencies or devDependencies, it will fail because the node module resolution will not find it. If you are using npm, by accident in the flattened npm-type node_modules will contain a thousand transitive dependencies that can be required and will resolve, and you will never know that you are using something that is not listed as a direct dependency.

    Fix: Throw out npm and use pnpm

    Commit Details:

    • Use pnpm in shell.nix instead of npm
    • Add "preinstall": "npx only-allow pnpm" which throws a helpful error message if someone tries to use npm because of muscle memory
    • Fix a conflicting type issue with emotion/serialize
    • Delete package-lock.json's and add pnpm-lock.yaml instead
    Reviewed by balazsbajorics at 2021-09-23 10:49
  • 4. Testing a pair of baseline values for scaling performance tests

    This PR was used to try to find a baseline metric to give us a picture of the overall performance of the machine running the tests, with the idea being that this baseline would strongly correlate to the other measurements enough that we could then use it to scale all other performance tests (thereby offsetting the high variance across runs of the performance tests).

    I went with two proposals for this baseline metric: a simple calculation (calculating Pi); and a series of consecutive empty dispatches (since a single empty dispatch is too quick). I have tweaked these two tests a number of times and found that unfortunately they appear to be not very well correlated with the other tests (in many cases the baselines dropped whilst the other values rose, or vice versa).

    Still, for the sake of completeness, I've added the tests to the chart, so that we can monitor them over time, tweaking them both so that they'll roughly result in values around the 30ms mark (in the case of the empty dispatch this is required so that it won't run faster than a frame takes to render).

    This PR has also updated the other tests to actually gather 100 measurements (in each case they are run 101 times, since the tests will use the deltas between measurements to capture actual frame times, meaning we need 1 extra run).

    Reviewed by Rheeseyb at 2021-05-14 15:33
  • 5. Feature/fast refresh canvas

    This PR introduces Vite HMR for development while keeping webpack bundling.

    • Splitting the utopia-api to 2 parts. The utopia-api contains the components, and utopia-api/core has all the utility functions and non-components. The reason for this that importing module containing a React Component inside a worker triggers the react fast refresh and error layer, which is not working in a worker environment.
    • The workers are using different imports and constructors for vite and webpack, so alias is added to use 2 different files for the different modes. (and jest mock)
    • There are changes to the html variables and the html file structures to load them with vite and webpack too without maintaining duplicates of the files. The HtmlWebpackPlugin and Vite html plugin is using the same syntax for template variables.

    The existing start- scripts are changed to use Vite, development with webpack can be run with start-minimal-webpack or start-full-webpack

    Reviewed by enidemi at 2022-01-05 09:41
  • 6. Spike: canvas controls clean

    How to add a strategy

    In components/canvas/canvas-strategies/canvas-strategies.ts there's a const RegisteredCanvasStrategies where you can add a new strategy.

    A strategy has the following type:

    export interface CanvasStrategy {
      name: string
      updateFn: CanvasStrategyUpdateFn
      fitnessFn: CanvasStrategyFitnessFn
    }
    

    The fitnessFn returns a number, the "fitness" of the strategy for the given editorState and session state. You can determine fitness for example based on "there is a single selected view", "the parent of the selected view is Flex", "the selected view has absolute positioning", etc.

    the updateFn is the main part of the strategy.:

    type CanvasStrategyUpdateFn = (
      lifecycle: 'transient' | 'final',
      editorState: EditorState,
      currentSession: SelectModeCanvasSession,
    
    ) => {
      newSessionState: SelectModeCanvasSession
      transientFilesState: TransientFilesState
      editorStatePatch: EditorStatePatch
    }
    

    It takes the editorState, the currentSession, and returns a new session state, a transientFilesState, and an editorStatePatch. The filesState is the same as the DragState's old filesState: you can specify a file by path and a new array of topLevelElements and imports. The transientFilesState is respected by the navigator/canvas/inspector.

    The editorStatePatch is applied as the last step of the editor dispatch function. You can patch any part of the editor state. For the syntax, I picked Spec from immutability-helper. For example if we want to clear the highlighted views during an interaction, you can write this in your strategy update function:

    const editorStatePatch = {
      highlightedViews: { $set: [] }
    }
    

    Aside: How the state patching is implemented: The editor dispatch function updates the new unpatchedEditorState. All the action update functions see the old unpatchedEditorState and operate on it and return a new one. As the last step of the dispatch, we call immutability-helper's update on the unpatchedEditorState, generating the editorState all of the application code will see. All this is to ensure that the patched editor state is a pure function of the unpatched editor state and the active Strategy.

    Add visual controls

    Once the strategy is added, we might also want to show new controls for it! I made a simple example control called FlexAlignControls in components/canvas/controls/select-mode/flex-align-controls.tsx. I added a new object to the EditorState, at EditorState.canvas.controls: I intend this to be a place to put the state of controls and a point of communication between the Strategy update function and the visual controls. How my example control works: the FlexAlignStrategy patches EditorState.canvas.controls.flexAlignDropTargets, and fills it with a bunch of rectangle coordinates. flexAlignDropTargets is then read and rendered by FlexAlignControls to the canvas. In my example, I tried to keep all logic code in the FlexAlignStrategy update function, and keep FlexAlignControls as simple as possible. My thinking was that the controls should only focus on the visual display of visual controls, logic and the complicated code of a strategy should live in the strategy update function. If we can stick to this concept, I think that would provide us a nice place to put the "messy" code, and keep the canvas controls clean, and prevent leaking too much implementation detail into the react components. We might as well experiment with putting the Strategy and the canvas control react component into the same file: that way, a single strategy plus its drawing function would be in the same place, which might make it easier in the future to read the code and understand the original intentions.

    Reviewed by balazsbajorics at 2022-01-03 19:37
  • 7. run the performance step in a separate job, on a self-hosted runner

    Problem The puppeteer performance test were executed on GithubActions along with all the rest of the jobs. A few months ago something changed, and the test results became incredibly unreliable, seemingly the test runner loosing CPU allocation during the test run.

    Solution Move the puppeteer test (and only the puppeteer test) to a Linode dedicated CPU instance.

    This PR is already showing performance tests that are executed on the Linode instance.

    I picked the cheapest dedicated CPU instance, 2 cores, $30 / month + $5 for backup

    Details

    • created a new linode instance github-actions-1 https://cloud.linode.com/linodes/32420665
    • I have no idea who can see this, I think Malte and Balazs are the ones who are in the Utopia Linode origanization
    • this instance runs the github action runner as a systemd process

    Notes

    • The node has manually installed nix and the github actions runner. There's no setup script or Dockerfile to instantly recreate it
    • I did manage to make a "Backup Snapshot" of the moment it all started working. that should be a stopgap for now
    • We should run this for a couple of days and observe reliabilty
    • If it is unreliable, consider other options and possibly a solution which lets us make easy to reproduce setups (Docker or nixos or otherwise)
    Reviewed by balazsbajorics at 2021-12-02 09:34
  • 8. Fix/change font size editor

    (edit MN) This PR introduces a feature to change the font size of the code editor, as a relatively straightforward feature (and a showcase for our redux-y architecture)

    Reviewed by OmarDaSilva at 2020-12-30 12:46
  • 9. Feature/karma snapshot tests

    Problem: The electron browser tests are not supporting the latest jest, it's time to use an alternative solution.

    Fix: Switching the browser tests to use karma.

    Commit Details:

    • added pretty format from jest
    • added karma-viewport to set size
    • introduced internal inline snapshot test
    • switched prettier import to use prettier/standalone in browser tests
    • removing setElectronWindow
    • changed dom-walker tests to use inline snapshots
    • test case called: dragging a scene child’s root view sets the root view position is temporarly removed as it takes longer than 10 seconds to complete
    Reviewed by enidemi at 2021-09-28 15:15
  • 10. Fix the UID of changed code

    Problem: The UIDs are no longer printed to the code. When we are parsing a code file, we generate UIDs by hashing the jsx elements. The solution is overall pretty elegant and it makes the editor feel like magic. However, there is a big downside: if the user types in the code editor to update an element, that element will also be automatically selected on the Canvas and Navigator and Inspector. But when the selected element's code changes, its hash will change too. And that means its UID will change as well. And that means all the template paths pointing to the selected element, the highlighted element, the spy and dom-walker metadata etc will refer to a nonexistent element. We had an earlier mitigation in place that would salvage the selected view, but it would not save the metadata. Which means that as the user was typing in the code editor, the inspector would flash as it got a new template path with no metadata, and flash again as fresh metadata arrived a frame later.

    Fix: I basically took the same mitigation we had before, but moved it to the end of parseCode: We zip the old projectFile and new projectFile contents, and we try to match up UIDs by their index among their siblings. If we find a single mismatched UID, (to prevent accidentally matching the wrong element after a delete or insertion or copy-paste or code duplication) we assume that we found the same element but a different hash. We then update the uid to the old one, and also fix the highlightBounds map.

    Details:

    • parseCode now takes an oldParseResultForUIDComparison: ParsedTextFile | null parameter. I made it explicit instead of optional, so I could breeze through all the places using parseCode and decide if I should provide null or a real oldParseResult
    • I made a new function fixParseSuccessUIDs that runs at the end of parseCode. It zips the old parsed file and the new parsed file against each other, and tries to find matching UIDs based on the element's indexes inside their parent.
    • Gutted removeNonExistingViewReferencesFromState so now it really only removes nonexisting references and does not try to salvage paths
    • Moved applyUtopiaJSXComponentsChanges from editor-state to project-file-utils to prevent the parser-printer-worker from bombing out (the dependency cruiser actually caught this issue, nice job, dependency cruiser!)
    Reviewed by balazsbajorics at 2021-04-19 08:52
  • 11. Test/select mode test 1

    This is a new test that codifies a desired behavior: image

    if the user keeps double clicking on an element that sticks out of its parents' bounds, eventually we want to successfully select the element.

    previously this was only possible with cmd-clicking, the dom-based select mode makes sure that you can achieve this by repeated double clicking.

    Reviewed by balazsbajorics at 2021-01-21 13:13
  • 12. For absolute moves and resizes, check that the target supports style property.

    Problem: Components which don't pass through the style property in any way means that those cannot be repositioned/resized by changing the style props assigned to an instance of that component.

    Fix: The absolute strategies now have an additional filter to their isApplicable check which is that the underlying components use the style property.

    Commit Details:

    • Added supportsStyle utility function to make it convenient to check for supporting the style prop in canvas strategies.
    • Slightly refactored some code to create the targetUsesProperty function in MetadataUtils.
    • Added a supportsStyle invocation to all the absolute canvas strategies.
    • Added a test case that confirms that resize is disabled for the absolute cases.
    Reviewed by seanparsons at 2022-08-05 17:16
  • 13. Spike: fragment support in navigator without selection

    This spike is an evaluation of an idea for a first step of fragment support: it turned out the biggest challenge of fragment support is selection: we have a huge bunch of features which manipulate the selected views: navigator, inspector, context menu, keyboard shortcuts, etc. If we allow fragments to be addressed by ElementPaths and we allow fragments to be selected, then we have to make sure all these features are already fragment ready (to be more precise most of these features should be disabled for fragments, because they just don't make sense for fragments, e.g. setting style props). So to reduce the scope, in this spike I introduced the fragments in the navigator, but I don't allow fragments to be selected.

    The simplest solution was to filter out fragments in the SELECT_COMPONENTS action implementation. However, this has some negative side effects: e.g. when you go upwards in the parent hierarchy with ESC, it gets deselected on a fragment.

    But as a spike I think this is good enough to play with it.

    Reviewed by gbalint at 2022-08-05 15:41
  • 14. Check if Chrome 59 HandleMouseMove is still needed

    hmmm, I wonder if we can now safely delete this whole chrome workaround... we should create a ticket to check if it's still needed

    Originally posted by @balazsbajorics in https://github.com/concrete-utopia/utopia/pull/2454#discussion_r936639114

    Reviewed by balazsbajorics at 2022-08-03 13:06
  • 15. Investigate and fix emotion/styled support

    Describe the bug Adding and using the @emotion/styled dependency results in an error, but works elsewhere: https://codesandbox.io/s/styledcompoments-emotion-cwx650?file=/src/App.js, implementing the example from the emotion docs: https://emotion.sh/docs/@emotion/styled

    Screenshot image

    image
    Reviewed by maltenuhn at 2022-07-29 11:17
Isolated React component development environment with a living style guide
Isolated React component development environment with a living style guide

Isolated React component development environment with a living style guide React Styleguidist is a component development environment with hot reloaded

Aug 8, 2022
Isolated React component development environment with a living style guide
Isolated React component development environment with a living style guide

Isolated React component development environment with a living style guide React Styleguidist is a component development environment with hot reloaded

Aug 7, 2022
Isolated React component development environment with a living style guide
Isolated React component development environment with a living style guide

Isolated React component development environment with a living style guide React Styleguidist is a component development environment with hot reloaded

Oct 28, 2021
Dev environment for building scalable, high-quality user interfaces
Dev environment for building scalable, high-quality user interfaces

React Cosmos A dev environment for building scalable, high-quality user interfaces. Visual TDD. Develop one component at a time. Isolate the UI you're

Jul 29, 2022
Dev environment for building scalable, high-quality user interfaces
Dev environment for building scalable, high-quality user interfaces

React Cosmos A dev environment for building scalable, high-quality user interfaces. Visual TDD. Develop one component at a time. Isolate the UI you're

Aug 1, 2022
A set of tools to facilitate react-redux development and decouple logic from compontents
A set of tools to facilitate react-redux development and decouple logic from compontents

react-redux-api-tools This project provides a middleware and a request helper to streamline react-redux data fetching. Installing Just run npm install

Mar 14, 2022
A 'heatpack' command for quick React development with webpack hot reloading
A 'heatpack' command for quick React development with webpack hot reloading

DEPRECATED If you want to quickly prototype React apps without setting up a project, try nwb's react command instead. If you want something to tweak a

Jul 19, 2022
The reactive library for the spreadsheet driven development

Sunrise Spreadsheet-like dataflow programming in TypeScript Example import { cell, formula, swap, deref } from '@snapview/sunrise' const inc = (a) =>

Jul 20, 2022
Test-new-app - Next.js + Tailwind CSS + TypeScript starter packed with useful development features
Test-new-app - Next.js + Tailwind CSS + TypeScript starter packed with useful development features

?? ts-nextjs-tailwind-starter Next.js + Tailwind CSS + TypeScript starter packed

May 14, 2022
Bit is a toolchain for composable software development
Bit is a toolchain for composable software development

Bit is a toolchain for composable software development. With Bit, you can build anything in components.

Jun 1, 2022
This is a functional front-end project not a front-end design project. How to implement logic in react js project It's has been shown in this project.

Expense Tracker App react React is a JavaScript library for creating user interfaces. The react package contains only the functionality necessary to d

Mar 20, 2022
Smarter layout components. Based on css flexbox. Support responsive design, Typescript, server side render. 3 KB gzipped.
Smarter layout components. Based on css flexbox. Support responsive design, Typescript, server side render. 3 KB gzipped.

react-colrow English | 中文 Smarter layout components. Based on css flexbox. Support responsive design, Typescript, server side render. 3 KB gzipped. 更智

May 22, 2022
A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.
A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.

Join our Community Slack Quick Installation Guide What is Reactotron? Reactotron is a macOS, Windows, and Linux app for inspecting your React JS and R

Aug 1, 2022
A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.
A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.

Join our Community Slack Quick Installation Guide What is Reactotron? Reactotron is a macOS, Windows, and Linux app for inspecting your React JS and R

Jul 30, 2022
A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.
A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.

Join our Community Slack Quick Installation Guide What is Reactotron? Reactotron is a macOS, Windows, and Linux app for inspecting your React JS and R

Aug 6, 2022
Chrome extension for improving and optimizing performance in React applications (Gatsby and Next.js compatible).
Chrome extension for improving and optimizing performance in React applications (Gatsby and Next.js compatible).

React Performance Tool Nominated for React Open Source Awards 2020 Reactime is a performance and debugging tool for React developers (Beta version for

Aug 6, 2022
fflow is a free, open-source developer tool to create React applications rapidly and with minimal effort using the simple drag and drop UI
fflow is a free, open-source developer tool to create React applications rapidly and with minimal effort using the simple drag and drop UI

fflow Supercharge your React development process Explore the docs » View Demo · Report Bug · Request Feature Give a ⭐️ if our project helped or intere

Aug 1, 2022
An upgradable boilerplate for Progressive web applications (PWA) with server side rendering, build with SEO in mind and achieving max page speed and optimized user experience.
An upgradable boilerplate for Progressive web applications (PWA) with server side rendering, build with SEO in mind and achieving max page speed and optimized user experience.

React PWA v2 A highly scalable, Progressive Web Application foundation,boilerplate, with the best Developer Experience. Demo: https://demo.reactpwa.co

Aug 1, 2022
🎭A simple and effective Text Input with mask for ReactNative on iOS and Android. Includes obfuscation characters feature.
🎭A simple and effective Text Input with mask for ReactNative on iOS and Android. Includes obfuscation characters feature.

React Native Mask Input A simple and effective Text Input with mask for ReactNative on iOS, Android, and Web. No fancy stuff, it's basically a JavaScr

Aug 6, 2022