guppy icon indicating copy to clipboard operation
guppy copied to clipboard

Long-term layout idea: panels!

Open joshwcomeau opened this issue 5 years ago • 6 comments

Oh boy, here we go.

So, yesterday I had a bit of an epiphany: I designed Guppy like a webpage, not a desktop app.

It's meant to be used in a relatively small window, and is meant to be scrolled vertically. Nothing is rearrangeable or moveable. It's essentially a website in a desktop-app wrapper.

I had this realization when I started learning AfterEffects. While its interface is complex, it's undeniably powerful:

aae

Like other Adobe products, it's comprised of a bunch of panels. Each panel is resizable, and can be toggled on/off.

Another example is a program I use for audio stuff, Ableton Live:

ableton-live

This program is still too complicated-looking, but it's a bit more whimsical/colourful/fun. It too has resizable panels, and panels have different tabs.

Even Spotify has some of this; a resizable sidebar on the left, and a persistent bottom bar:

screen shot 2018-08-24 at 9 33 41 am

I think Guppy could be much more powerful if we leverage some of the ideas. I'm imagining something like this:

img_3395

I imagine it would share much of the same aesthetic / wouldn't look that different from how it does now. The big thing would be that each section would be a panel, and would be movable / toggleable / resizable. That way you can adjust your view of things, kill the "eject" window if you don't need it, swap "dev server" and "build" when you're focused on bundling, etc. It feels so much more powerful.

Like in Photoshop, we could have a "Window" application menu to toggle specific panels (the drawing doesn't include a way to create new tasks, for example; maybe that could be a disabled-by-default panel).

I also imagined having a persistent bottom bar that could be used for statuses / notifications. A quick way to track tasks, and clicking on one of them would focus that project/panel or something.

I think that we could still make it very friendly for absolute beginners (by having a sensible default layout, so that nothing has to be toggled for most beginner usecases), and it means it could scale with the user as they learn more. Maybe one panel could even just be a terminal, as a way of transitioning users to a terminal / supporting things that absolutely need a terminal.

I think this is a problem we're going to have to face, one way or another; as Guppy gets more powerful, how do we ensure that it remains easy to grasp for beginners, while still being powerful for intermediate/advanced users?

I'm really excited about this idea, although I don't foresee having the time to work on it anytime soon. It would be a big task, and something I'm thinking of as like a long-term, 2019ish vision.

What do y'all think?

joshwcomeau avatar Aug 24 '18 13:08 joshwcomeau

Blender has a similar layout system, although it goes a bit farther — there’s a dropdown available in one of the window types (the application menu/log viewer, which typically appears at the top of the window), that allows you to select different layouts and even create your own. The UI is fully resizable and any pane can be split into two or changed to show different content.

j-f1 avatar Aug 24 '18 13:08 j-f1

@joshwcomeau I've added my WIP panels-setup it is using react-grid-layout for the panels. I've seen the branch panels but yarn start wasn't working there - so I decided to create a new branch for the basic panel setup.

At the moment, the basic setup is working but there is a lot todo. But I think we need to discuss the details and I need some help for the styling & UI concept.

Summary of the setup

  • [x] Added react-grid-layout
  • [x] Created PanelsManager component for rendering & switching to simpleMode
  • [x] Created a Panel type - x,y for the position in grid where 0 = first position in 12th grid, minW & maxW = panel width resize boundaries.
    export type Panel = {
      key: string,
      Component: React$Node,
      grid: {
        x: number,
        y: number,
        w: number,
        h: number,
        minW: ?number,
        maxW: ?number,
      },
    };
    
  • [x] Created defaultPanels array with type Panel for each component of ProjectPage.
  • Changes to the panel won't be persisted - it will always reset to defaultPanels. Saving not added yet.

The following points I've hit during creating the setup

Business logic

  • The prop simpleMode={true} disables the panels and it should display everything like it is in the current app. Rendering is OK. But I'm not sure where we could toggle the mode. This would be great for app settings which we don't have but we could add it to a right click menu if the project page space is clicked or to the application menu (see below).
  • Should we create a Saga for managing the panels per project? I think this is required to persist the panels.
  • How to add new panels (e.g. the Storybook panel or Flow panel)?
    • I'm thinking of a dropdown button at the position of the Add Panel button - so the user sees the available panels. The dropdown will update with each add because each panel should be added only once.
    • Also if nothing is remaining we should remove the add button.
  • How to remove panels? Maybe with a close button + an application menu entry.
    • Do we need to check if any tasks are pending in the panel?
    • Is a confirmation dialog required? I think it's OK to hide the panel with-out confirm as it should be easy to re-add the panel.
  • Application Menu needs some controls for the panels - should this be a new top-level entry or can we add it to View? I think a submenu in View would be OK. With the following items:
    • Reset to default panels (so resetting is easy)
    • Maybe we could also toggle between simpleMode and the panel mode there.
    • Remaining panels (so we can also add panels from the menu)
    • Remove panels

UI

  • Panel resizing needs to be optimized
  • Panel arrangement should be improved - e.g. enlarging one panel should affect the neighbor size until it's size is too small then wrap to next row with previous size - Maybe to complicated but this would be nice. I don't like the free movement.
  • Changing styling of panel - adding a light border + a closing button in top right corner. There is only a small corner mark in the lower right (see screenshot below).
  • Add dynamic panel resize depending on screen width/height. I've started with fixed sizes to keep things easier - I would add this later. There is a Responsive Grid component & a widthProvider and several breakpoints to adjust the layout.

Screenshot of the add button grafik

Screen recording panels screenrecording_panels

AWolf81 avatar Sep 17 '18 22:09 AWolf81

If you like the branch I can create a WIP PR for tracking the changes of basic setup.

I've noticed that this is a large task & I think we should split into smaller pieces:

  • basic setup (panels + basic redux actions)
  • persistence (setup panels.reducer & migration)
  • UI design (styling of the panel & the components)
  • UI controls add & remove panels
  • UX improvements for panel drag & resize

AWolf81 avatar Sep 18 '18 07:09 AWolf81

Hi @AWolf81,

Thanks for giving this a shot. I've been working on this myself, and I don't think we can use react-grid-layout for this :/

It's close to what I'm imagining, but the layout model is different. Specifically, I'm imagining it as a series of columns; each column can have 1 or more module, and critically, each column can be resized.

With react-grid-layout, there's no idea of columns. When you resize one module, the others move out of the way, instead of shrinking:

resize

In my Panels branch, I have it as a series of rows and columns that can be resized:

cols

In this model, even the Sidebar could be a panel:

sidebar

(obviously styles need to be fixed)

I couldn't find any third-party tool that did exactly what I want (react-mosaic was closest, but still not quite), so I think this might be something we have to build ourselves. Well, I think we'll be able to use react-beautiful-dnd for actually swapping panels around, but the actual panelling logic.

The good news is that I have it mostly working already in my panels branch. I just pushed the latest changes to github, so it should work for you now?

Totally agree it makes sense as multiple PRs. I haven't been able to give this very much attention (speaking at React Boston in a week and a half so a lot of my time recently has been going towards that), but I do plan to get back on top of this shortly =) here are what I see as the next steps:

  • Tidy up the Panels implementation, open a PR with just the panels
  • Integrate the sidebar as a panel, make it look nice
  • Move the existing modules to panels, create a two-column layout by default
  • Look into having a dnd solution to move panels around
  • Make panels closeable with an x somewhere, and openable from the window ApplicationMenu

If you're interested in helping, maybe you could look at integrating react-beautiful-dnd? Feel free to create a new branch from my panels branch and poke around with it (while I think we should open PRs in roughly the above order, we can still do some prep ahead of time and test out different solutions).

Lemme know what you think. Also lemme know if you think react-grid-layout can do the stuff I'm thinking of, maybe I just haven't dug deep enough into its API?

joshwcomeau avatar Sep 18 '18 12:09 joshwcomeau

@joshwcomeau I played a bit with react-beautiful-dnd in a codesandbox here. Code not added to branch panels-dnd yet.

Sure styling needs to be improved. I also think we could have one panel for adding & removing modules from the panels at a fixed position. I think we could show a trash bin on dragStart and if the module is dropped on the trash symbol we can remove it. The position fixing is not working properly yet. If you're moving other columns around the fixed column is moving during drag but not persisting on mouse release as it's not tracked in the data.

I think it would be good to have panel control icons on right sidebar. So we could have the following things in the menu:

  • add new empty panel
  • add available project specific module
  • remove modules
  • reset panels to default

In my panels-dnd branch I have the dnd for modules working - with-out panel sizing. The panel dnd is not added there yet.

Do you think the drag & drop panel concept like in the Codesandbox could work? If yes, I'll add it to the branch.

OK, I think I leave the panels for now and we can work on it later. Later today I'm back on debugging electron auto updating feature. I think I need to temporarily disable minification for production build so I can understand the error message in the terminal.

AWolf81 avatar Sep 25 '18 23:09 AWolf81

I also think we could have one panel for adding & removing modules from the panels at a fixed position. I think we could show a trash bin on dragStart and if the module is dropped on the trash symbol we can remove it.

Hm, I'm not sure that I want an always-present panel for panel management. I think it's something that most users won't actually need very often, and might confuse newcomers. I'm a fan of keeping the UI as minimal as we can.

I think the norm for desktop apps is to have the menu deal with that, like a top-level "Window" menu. I think it can do everything we need

Let's look at the concerns 1 by 1:

add available project specific module

I imagine a menu like:

Window
  - Reset to Default Layout
  - Modules
    - [x] Development Server
    - [ ] Tests
    - [ ] Build

So yeah, you'd just toggle the one you want to add.

For placement, I imagine us working it out automatically, based on sizes. Each panel will have a minHeight and a maxHeight, and so it can just try to find the first available spot, or create a new column if none is found.

Let's say this is your layout:

____________________________
|             |            |
|    Dev      |    Tests   |
|   Server    |____________|
|             |            |
|_____________|   Format   |
|             |            |
|_____________|____________|

Let's say the window is 1000px tall, and DevServer currently takes up 750px, but has an acceptable range of 500px - 1000px.

If we want to add a new module which has a min-height of 400px, it'll add it to the first column (it can resize DevServer to be 600px, which is still bigger than its min).

If we want to add a new module which has a min-height of 600px, though, it won't fit in the first column, and the second column is already full, so it'll create a new third column.

add new empty panel

I don't think we have a concept of an "empty" panel, unless you mean columns?

For columns, I think we can let the process I described above take care of columns most of the time, but maybe we can also add a menu item, "Add new column", which'll just add a new empty column on the right side of the screen?

remove modules

I imagine that each module has a title bar, and so we could add a little X to close it in that. But yeah you can also "untick" it from the menu, by clicking an already-ticked menu item

We could also maybe fade in a trashcan in the bottom left corner when you start dragging it... although that feels like the kind of detail we can decide to add at the end, once all the other concerns are figured out.

reset panels to default

I think this is definitely a menu item, that's where I'd look for that kind of functionality.


But yeah, there's still a lot of this stuff that's in my head, I haven't had the chance to get it out. I'm working on a proper mockup for this stuff in Figma, but it's a bit of a new process for me and I've been busy with other stuff. Hopefully once I have that, it'll be helpful to clarify what I'm imagining.

Later today I'm back on debugging electron auto updating feature. I think I need to temporarily disable minification for production build so I can understand the error message in the terminal.

Awesome! Yeah, this remains the most pressing issue. Once that's worked out, I'll start working on adding code signing, and we can broadcast the release :D

joshwcomeau avatar Sep 26 '18 12:09 joshwcomeau