New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Responsive Cosmos #539
Responsive Cosmos #539
Conversation
@xavcz looks cool thanks, definitely some great ideas in there even if we don't want to directly adapt their product. I'd like to circle back to a UX/UI discussion once @skidding confirms that this proof of concept PR is 'workable' (/fixable!). Would also be great to know how hard it would be to have Cosmos render to multiple iFrames at once for that Sizzy style 'multiple devices at once' layout. |
This is great! 😍 I'll only answer the burning questions for now and leave the UX for later.
The
Yes. It ties into #383 and we definitely want to start rendering multiple Loader iframes at once. I've been talking with @xavcz about this and about the idea of porting the |
Thanks @skidding. Is there currently active work on the multiple iFrame system? On a related note, I think as part of the 3.0 release you wanted to write some sort of roadmap? Other quick question; in the current master, the ComponentPlayground fixtures show a "Cannot GET /mock/loader/index.html", is this intentional? I'll circle back with a UX discussion for this PR later. |
Aaaand.. it's here #546 |
Forgot to answer this. Yes. We might be able to use the real Loader path in the loaded Playground, but then we'd get an infinite loop of Playground in Playground in Playground. Which would actually pretty cool, but I remembered why it isn't possible at the moment. Because Loader communication is global, the Playground in Playground in Playground would send events to the root level Playground and confuse it. Once we have |
Hi all, I've added a few updates to this. Feel free to pull the branch and fire up From a personal perspective with regards to my available time to work on this, I'd like to publish small, iterative updates to this feature, rather than try to do everything possible in one massive PR. What I've pushed so far is a basic version of "level 1". No need for code review or UI review at this stage, please let's look at the API and the UX. I'll polish up the code and UI once that's stabilised. The user can specify in their cosmos config their desired list of responsive devices under the key
Any suggestions on a better list of defaults? Is there a standardised list of Android devices we can add? Bare in mind that the user can supply their own list, so our defaults don't have to be perfect. We add a button to toggle the responsive loader: If you click on this, you will then see a new menu bar where the component normally shows up: Here we show all your specified devices. Clicking on these shows your component inside an appropriately sized iFrame. If the desired size does not fit on your screen, we scale the iFrame but keep the exact pixel dimensions. As part of "level 2", we will enable toggling scaled or not, but for now, it always makes the device size fit into your screen. Any desired UX (not UI) changes to this new menu bar? If you click on "Custom", you can then enter a custom dimension for your iFrame: One issue here is that we need to default Custom to some specific dimensions (showing 0 x 0 when you click on Custom isn't a nice UX). However, if the value that we default to actually exists in the We actually store the desired dimensions in the fixture, and update this when you click on a button in the responsive menu bar:
Any requests for a different key name than This means you can also save your desired dimensions in your fixture source code. For example, you might have a component that shows two different things based on css media queries. This way you could save a "Component Desktop" and "Component Mobile" fixture that automatically set the desired window dimensions for you. One outstanding issue is that the Responsive toggle button (the phone icon next to the full screen icon) stops working once your fixture has the I think getting these basic issues cleaned up would be a great 'first release' of a responsive mode. @skidding would you agree, or would you want some other features? In terms of future features:
Thanks all. |
@@ -40,7 +41,8 @@ type Props = { | |||
component?: string, | |||
fixture?: string, | |||
editor?: boolean, | |||
fullScreen?: boolean | |||
fullScreen?: boolean, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@skidding trailingComma: true in Prettier will prevent lines like this showing up in diffs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to make a PR ¯_(ツ)_/¯
Great, this is preferable. 👍
How about PS. It would be great if this property could also work in Jest/jsdom as well, somehow overriding window.width/height. I've done this once but I'm not sure how reliable it is, especially since the latest jsdom in Jest 22 seems breaking because it doesn't allow us to override stuff like window location anymore. Anyway, no need to worry about this, just something to consider. It's not uncommon to render different stuff based on viewport size so it would be useful to work in headless tests as well.
Maybe an apply button? It seems weird to change as I type. Eg. if the value is
The apply button could fix this. A state flag that isn't part of the fixture could show/hide the custom options, but once you click apply the width/height gets applied to the fixture and the corresponding button will be highlighted, be it the custom option or a specific resolution.
I think this can be solved. The playground knows the serializable parts of the current fixture (and width/height are just numbers, so they will be received). The partial fixture body is received after fixture is selected and after every fixture update. Via
I agree. All other features are great but they can be added incrementally. Plus we'll gather more feedback once we start using it so we'll know what to focus on next. |
Two details to consider:
|
Done.
It's a bit messy as we have to nest 4 divs to get the layout correct for the responsive mode, but this is now fixed. I still see some occasional flicker with some of the more complex fixtures (but I get this in
Not sure I follow. At the moment, in order to decide whether to render the responsive tool, we check if the url has If we purely have the 'show responsive layout' be a function of the
I actually quite like the 'change as you type' style. Are you strongly against it? If not, then I can fix the 'can't delete 0' bug separately. |
This is a classic multiple source of truth problem. If we want
But this raises some questions:
|
@maxsalven OK, I published this branch under the |
Hello :) Any update on this topic ? This looks super useful, but maintaining a fork of this branch is a bit overkill. What is needed to merge with master ? Thanks ! |
Hi @eltonio450, I'm planning a bigger overhaul of the Cosmos UI which will surely include this feature, but I'm not sure if this branch will ever get merged or the code from it cherry picked instead. However, it's part of a bigger plan and the best estimation I can give is some time this summer. |
@skidding, @maxsalven I think I can drop my five cents about this functionality. Personally I can't get the idea of re-implementing something which already was solved by web devtools, and it was solved perfectly. Storybook for example offers lots of re-implemented functionality of chromes/firefox devtools and I don't get it, and I believe root of the problem is in its addons system. Instead of thoughtful and careful steps towards DX (which is the main concern of discussed kind of tools), people start doing something in hope this 'something' will be used by others. Please look at the main reason of creating Sizzy:
This is not devtools re-implementation, this is multiple-screens-problem elimination. This is the main reason this tool was created. I strongly believe that if we should have such functionality in react-cosmos, then it needs to be multiple-screens-problem elimination. For specific resolutions development browsers devtools already matches ideally. |
@mpachin You're right. Rendering multiple loaders with different resolutions at the same time is the end game, and I'm confident it will be part of Cosmos in the future. In the meantime, however, we can't rely on the browser dev tools' responsive capabilities because they only apply to the top frame and even in full screen mode Cosmos loads the component inside an iframe. We could fix this by tweaking the current full screen mode. Instead of rendering a chromeless playground with the loader iframe in full screen mode, we can instead render the loader iframe contents directly: Wdyt? |
Hi all, great to have some discussion on this PR! A few thoughts: My personal workflow isn't one where I care about multiple screens at once. I'm typically in a 'mobile' context or a 'desktop' context whilst developing, and prefer to be focused purely on one version at a time. Having the two dimensions on screen at the same time, on my laptop along with the Cosmos file directory on the left (I'm very frequently switching between fixtures) would render the desktop view so small as to not be usable (or if it wasn't scaled to fit, I'd have to scroll all the time). Instead, I personally want to see just one view at a time. Just my personal use case, of course others may flow differently!
I think switching between fixtures might be a bit clunky in this situation? Exit full screen, exit Chrome responsive mode, pick new fixture, enter full screen, enter Chrome responsive mode. I've actually been using this 'responsive cosmos' fork exclusively for the past few months, and it's worked really well for me. I have full access to the file list, and I can toggle into and out of mobile mode with a single click, and very easily switch between device sizes too. @skidding if I updated this PR to match the latest master branch, would it still be considered for inclusion? I've got one remaining TODO which is to make a toggle for the 'scaled' mode setting. Full disclosure, there is also one bug, which I will try to fix: Occasionally, upon restarting Cosmos and only if you were in the responsive mode already, then it starts up showing your component in a tiny viewport and upside-down. Reloading the window will immediately fix this. It's a bit of a niche scenario, as I don't think the latest cosmos ever needs to be restarted anymore (as opposed to the older release, which needed a manual restart when adding a brand new component fixture). |
Good point. I guess Sizzy covers another use case, which is a birds eye view post CSS changes, especially useful for small sized presentational components. But I agree this would be a secondary use case and the primary one is likely focused around a single resolution at a time.
Correct. This would be an escape hatch.
Definitely.
I remember experiencing a bug where the viewport would become 0x0 until hard refresh. There might be more than one bug to fix, but I'm happy to help debug and maybe more people want to help beta test once the branch is brought up to date. |
Indeed, sorry I should have been clearer, 'one bug that I've encountered' :)
Great, I'll find some time next week to freshen things up, and take a look at the testing side, which hasn't happened yet. |
I've managed to get this up and running on the latest |
@skidding, as discussed on Slack, if you could take a look at the scaling bug that would be great! To reproduce, simply open a new Chrome window, go to http://localhost:8090 and then select |
I think I found the issue with the tiny viewport. Here's a few logical steps that lead me to my conclusion:
Haven't explored in depth, but here's a possible solution: Only send the |
Conflicts: packages/react-cosmos/src/server/web/playground-opts.js
Branch is looking good! Here are my thoughts. Responsive modes can cause overflow to the entire Cosmos UI: Solution ideas:
Here's a weird glitch: After UI territory:
Other notes:
The last thought I have is related to the design of the Here's a sample of code that makes me uncomfortable: react-cosmos/packages/react-cosmos-playground/src/components/ComponentPlayground/index.js Lines 383 to 395 in 38e8fa7
I get it after reading it a few times, but it's not quick to understand and the mixed boolean/string value definitely adds to the confusion. Again, this might just make the current solution more clear in my head, but I'd like to explore an alternative solution and see if it at least matches the current functionality. Here's the gist:
How do you think the current approach compares to the existing one? Thanks! |
Conflicts: packages/react-cosmos-playground/src/components/ComponentPlayground/index.js
The UI should default to scaled, which should never overflow the UI. Only if you explicitly untoggle scaling will we should a component bigger than the available screen space. Is this acceptable?
I have now changed
to
Which equated to 254. LMK if you prefer different multipliers.
Have moved it to the middle.
Done.
I'd like to explore this, but the first hurdle is that |
@maxsalven Thanks for all the effort! Merged six months later 🎉 I'll make some tweaks starting from latest master and then publish a new pre release. |
As far as I can see, Cosmos really struggles to be useful when working with responsive layouts / media queries. In Chrome, the only way I can get a media query to trigger is to go full screen and make my window small. Using the device toolbar in Dev Tools doesn't work, even in full screen mode.
Does anyone have any better 'no work required' solutions? I'd love to delete this PR!
I've whipped up a very quick proof of concept PR for adding responsive development tools to Cosmos:
The UX is very much a placeholder, but the rough idea is that users can define their own list of dimensions and labels (perhaps via their cosmos.config), which we show on the top. I'll also add support for an adhoc dimension option directly in the UX. You can trigger the responsive layout directly from a fixture with a specific dimension, or you can toggle it with the new responsive button next to the full screen button. I'd also like to add support for setting the background color, but perhaps that's better done in a proxy?
If a dimension is too big to fit in your window, we faithfully reproduce it and scale the contents, so you can still see exactly what your content might look like on e.g. a 1080p screen.
Credits due to https://docs.catalog.style/specimens/react#display-all-defined-screen-sizes-1 where I got some of the ideas (and CSS!) for this.
This originally started off as a proxy, but a brief chat with @skidding a couple weeks ago suggested this will be better both in terms of the development side and the user experience side if it's a core feature.
However, I need some help from @skidding please. If you load a fixture that has props, and change the screen size, it crashes. Hopefully it's something obvious, any thoughts?
I didn't want to put too much effort in yet until there's no 'major' blockers in terms of getting the cosmos fundamentals to work with this model.