Closed anderssonjohan closed 3 years ago
Using 100% width removes the modal feeling so having 100% - 0.5rem compared to today's 2rem it still makes the dialog to feel like a modal without wasting pixels.
fullscreen={true} should mean 100% of the viewport width and height max-width/max-height should be 100% to support fullscreen
For the records, this will create a serious usability problems. We have had this before in the CRM, and removed it. And this was the story:
When a user opens an object, the "related view" (as well as many modals) got opened in fullscreen.
Let's say user goes to global table view, does some search and filtering, and taps an object in the list to see it. Then a "modal" (related view) opens in fullscreen. For a user which is using a mobile device, the experience looks like that they have navigate to a completely new page. In technical terms, the URL has changed. So when they want to go back, they would instinctively press the browsers's "back" button or swipe from the left edge of the screen to go back to the table again. What they would see was a completely reset table. None of their filters was there.
But the reality was so that the URL only changed when they tweaked the filters, or searched for something; but the URL never changed when a pop-up opened. Users won't understand in their wildest fantasy what is going on. For them, it looks like we have a bug.
You may say, well, can't we just change the URL when a modal is opened? Quick and dirty answer is: No. That creates other usability problems because it interferes with browser's back button. Imagine you have clicked a few objects to preview them. Now you wanna go back from the global table view to wherever you were before. There will be other problems with this approach that takes too much time, and also we can't solve it from Lime Elements.
Anyhow, as you said @anderssonjohan,
Using 100% width removes the modal feeling
But important to make sure that below…
so having 100% - 0.5rem compared to today's 2rem it still makes the dialog to feel like a modal without wasting pixels.
…applies only to the width
of the modal (which is what I see in the pictures too). Since this only leaves 4px
on each side of the modal. If we also do the same for the height
, then we will face the same story which I was telling in the beginning. We must make sure we have a modal that clearly tells to the users that it is a modal –a contextual and temporary layer on top of the current context– and can be closed with a (x) button.
Two tips :)
100% - 1rem
, leaving 8px
on each side.fullscreen={true} should mean 100% of the viewport width and height max-width/max-height should be 100% to support fullscreen
For the records, this will create a serious usability problems. We have had this before in the CRM, and removed it. And this was the story:
When a user opens an object, the "related view" (as well as many modals) got opened in fullscreen.
Thanks for the elaborate reply @Kiarokh and sorry for not being super clear with my intention here. My point here is that I think we should not have a fullscreen property that doesn't mean that. Full-screen is something in the browser for showing a video etc. Full viewport is 100% width & height.
Perhaps remove the option?
you're welcome @anderssonjohan :)
Perhaps remove the option?
remove = rename? :)
Do you mean we should rename what we call "fullscreen" and call it something else? Something like "full-width" or "no-width-limit", "screen-wide", "edge-to-edge" or similar.
you're welcome @anderssonjohan :)
Perhaps remove the option?
remove = rename? :)
Do you mean we should rename what we call "fullscreen" and call it something else? Something like "full-width" or "no-width-limit", "screen-wide", "edge-to-edge" or similar.
I think we should remove it and provide good defaults instead.
In our current mobile apps we are using fullscreen dialogs and normal views. Fullscreen dialogs are useful to use all the pixels available to do fullscreen pickers and such, while still not tampering with the browser history. This means you won't use the device back button to exit that screen.
Then we have the normal views which does affect the browser history using various techniques (in our legacy we use SammyJS as the router to map a url pattern to a view component, and there's the history pushstate api).
A rather naive visual summary of what I'm writing here.
Although we isolate this as a component, I can't avoid the thought of <lime-dialog/>
being a Material Design dialog, which has "my view" of what a full screen dialog is:
https://material.io/components/dialogs#full-screen-dialog
In its specs it also has a good summary of my beliefs of what a modal dialog should be vs a fullscreen dialog: https://material.io/components/dialogs#specs
(emphasizing on that it shouldn't be a large complex form squeezed into the viewport with scroll panes)
The problem that we currently have with full-screen dialogs is that if the user presses the browser's back-button (or the phone's back-button) the expected action ought to be that the dialog closes or something like that. But precisely because a dialog doesn't push a new context to the history, pressing the back-button will navigate away from the whole object, or whatever happens to be underneath the dialog. That's a problem regardless of the how the dialog is styled, but when styled in a way that lets the user understand the difference between opening a dialog and navigating to a new page, at least the user has some sort of possibility to understand the difference and lessen their own pain.
The problem that we currently have with full-screen dialogs is that if the user presses the browser's back-button (or the phone's back-button) the expected action ought to be that the dialog closes or something like that. But precisely because a dialog doesn't push a new context to the history, pressing the back-button will navigate away from the whole object, or whatever happens to be underneath the dialog. That's a problem regardless of the how the dialog is styled, but when styled in a way that lets the user understand the difference between opening a dialog and navigating to a new page, at least the user has some sort of possibility to understand the difference and lessen their own pain.
Yup, hence why I think the dialog service should do similar to this: https://mdbootstrap.com/support/angular/close-modal-on-back-button-click/
showModal() {
history.pushState(null, 'modalOpened');
this.modal.show();
}
hideModal() {
}
ngOnInit() {
this.location.onPopState(() => this.modal.hide());
}
(but if we call the dialog service multiple times it should NOT push several "modalOpened" states onto the history.. to make it possible to, for example, open a confirm dialog and then a fullscreen dialog and still only need to use the back button once to close the dialog and restore the history)
The future with <dialog/>
also doesn't interact with nav history, but comes with other nice things, although it currently isn't supported on Safari so you're still stuck with the <lime-dialog/>
host element there (as recommended by polyfill for Safari https://github.com/GoogleChrome/dialog-polyfill). So even with that we would need to add the interaction with the History API IMHO.
As I see it, this is the problem:
You (and many others in Lime) have a need/urgency of being able to utilize fullscreen views, for small apps and special solutions that you develop for the CRM.
But the current architecture of our system does not give you such a luxury. There is no place for you to add such solutions. Then the only way left for you is using (or in your words abusing 😊) the modals. Then all the other limitations and shortages around it emerge. Modals by nature are supposed to be temporary layers of information with some very simple interactions, thus shortages are fine. But we bypass this fact, and treat them as if they were fullscreen apps.
The problem now is perceived as: "modals have problems, let's fix them".
In other words, manifestation of the problem, becomes the problem which we try to solve.
For example, we will end up trying to have a special modal or dialogue that can update the URL as users progress through the steps or tabs that are embedded inside of it.
If you ask me, we should push for getting a logical place for fullscreen apps in our design and architecture; instead of putting this burden on modals. There are already sketches for it. All we need to do is to bring this into attention of decision makers.
Solving how a modal interacts with the URL and history may be nice, but it still doesn't solve our problem of having no place for fullscreen apps. We will still have to put an ugly button somewhere irrelevant, to open a modal in fullscreen.
p.s. With that said, if there are bugs in modals we should of course solve. But over engineering a modal to hack a solution together… 😬 I'm not up for it.
@Kiarokh For an upcoming cycle we have another view-ish feature that we will work on. My intentions here are just to describe what we aim for. In my wireframe here I'm not (ab)using a limel-dialog
but instead use a fixed positioned element.
In this wireframe hack, the main part is using the following to mimic the looks of the dashboard view itself (padding + background + position):
$dashboard-background-color: rgb(var(--contrast-300, eb eb eb));
$main-navigation-width: 3.5rem;
$z-index-main-navigation: 7;
$z-index-resource-planner: ($z-index-main-navigation)-1;
$black: rgb(var(--contrast-600, 33 33 33));
$resource-planner-padding: 1.25rem;
limel-button.launcher {
background-color: white;
}
#resourceplanner {
position: fixed;
left: $main-navigation-width;
top: 0;
bottom: 0;
right: 0;
z-index: $z-index-resource-planner;
overflow-y: auto;
padding: $resource-planner-padding;
background-color: $dashboard-background-color;
limel-button:not(primary):not(disabled) {
background-color: white;
}
.topbar {
background-color: $dashboard-background-color;
border-bottom: 1px solid $black;
position: fixed;
top: 0;
left: $main-navigation-width;
right: 0;
padding-left: $resource-planner-padding;
padding-right: $resource-planner-padding;
z-index: ($z-index-resource-planner)+1;
limel-icon-button[icon="delete_sign"] {
margin-left: 1rem;
}
}
...
}
public render() {
return [
<limel-button
class="launcher"
label={`Resource planner`}
icon={'calendar'}
onClick={() => {
this.isOpen = true;
}}
/>,
this.renderContent()
];
}
If the vars from the main nav could be imported we could of course use those but it's probably better if this was placed in a component with slots for header + content and a service that can dispatch the "navigation" to the view, and have that call in a command handler (to make it customisable from a solution), instead of just render a div with a flip of a state property.
I would love to get some feedback on this so we know how we can move on.
@anderssonjohan thanks for the question. It feel we're going slightly off track from here. 😄 even though the discussion is relevant, but we may wanna make a new issue for this. 😅 Something like:
"Need a universal app layout component, to keep custom solutions more identical with original CRM layout architecture" "Need a universal app header component, to keep custom solutions more identical with original CRM layout architecture" What do you think?
For me, this is a super important thing. We really need both good components and clear guidelines for consultants and custom solutions. When I joined Lime, I started putting together a document for that. I was trying to create a design system that can address these needs in Lime CRM. This design system would guide everyone about how to build fullscreen apps, or widgets, etc.. and my hope was that we offer components for these. Components that start with "elements" grow to "molecules", then to "cells", "organisms" and so forth. You get the picture… So we would have a "Lime Components" library along with "Lime Elements".
For example, fullscreen apps would need headers. Headers would be components that include smaller components such as Search, Breadcrumbs, Action slots, Filter slots, View switchers button groups, Title slot, etc... And in a dream scenario, you could choose which one of these functionalities you wanna have in your implementation. (I'm not a developer and have no clue how hard or feasible this would be.)
Anyhow, we didn't go that direction due to pragmatic reasons… long story and I don't wanna go there now. But I/we are still trying to make this dream come true.
We don't have a good solution today. The closest component for headers we have today is a component called action-bar
in the crm-components
repo. It is specifically used in tabs, below the tab-bar. And I have no clue whether it is possible to reuse. You probably can't use it.
We may think that it's possible to at least make css variables for styles and expose them to everyone to use in their own custom headers. But I don't think that's the right way to go. We (who want to control the design) should have the freedom to change these things as our design evolves. If we offer publicly available variables, firstly they only address small issues like "z-index of the header" or "background-color of the header", etc… Secondly, we will always be scared of changing them, as we may hurt a solution. But if we had these custom components, the ecosystem it would build could be much easier.
I think for our current state, the best way to go forward is if you get feedback on your design and then implement your own solution. So we at least keep the design as close to our goal as possible.
Now I don't know if I could answer your question? 😄 If not, let's book a meeting instead and look more closely at your case.
By the way 👇😁
We will still have to put an ugly button somewhere irrelevant, to open a modal in fullscreen.
(you have no other choice, so I'm not criticising your solution!)
You may say, well, can't we just change the URL when a modal is opened? Quick and dirty answer is: No. That creates other usability problems because it interferes with browser's back button. Imagine you have clicked a few objects to preview them. Now you wanna go back from the global table view to wherever you were before.
But isn't this exactly what Google image search does? Why is it different from what we do? @Kiarokh
You may say, well, can't we just change the URL when a modal is opened? Quick and dirty answer is: No. That creates other usability problems because it interferes with browser's back button. Imagine you have clicked a few objects to preview them. Now you wanna go back from the global table view to wherever you were before.
But isn't this exactly what Google image search does? Why is it different from what we do? @Kiarokh
I think we should absolutely strive to represent the current state of stuff like tabs and modals in the url. Whether what Kia is talking about is a problem or a feature, is (or was back when I last heard about it) somewhat hotly debated, but as far as I know, the general recommendation is that the browser navigation buttons should actually step through the state, exactly like Kia doesn't want them to do. I certainly can see the argument for either behaviour, and I'll try to stay out of that discussion 😄 However, I think history.replaceState
(docs) can be used to get around that if we want to. It would probably be quite a lot of work, but I'm fairly sure it could be done.
Another quick and dirty answer: 😄
It all depends on the use case.
In case of Google Pictures, it totally makes sense to go back to a picture that you clicked a just couple of seconds ago, which you can't find it now easily because of having a ton of similar pictures in a never ending scrollable list. Further, user has only one task at hand in a google pictures search results. They just want to find a photo, and that's it. It's an app (if you will), designed for finding photos. They way of out this app is clicking on "All" in the tab bar on top. (Also please note that they don't open a modal to show you a picture every time you click a picture, which you have to close to click the next picture). This is an entirely different interaction pattern.
However, for the modals in our CRM I'm suspicious whether the same interaction pattern works. I'm not saying a BIG NO to the idea. I just think the paths through which users go around in our system to dig for data is very complex. Users intention is very complex and sometimes not so easily identifiable and definable like browsing on Google Photos.
I can't give a bulletproof answer. I can just say if we want to address this need, we should talk about our navigation paradigm as a whole.
I totally agree that indicating which tab is active in the URL of an object card is wonderful. But if we add that, does it mean we should also add it to the modal (the preview [aka related view]) as well? Maybe… Are you sure, not yet. Should all the modals be the same then? Hmmm… 😫🔫 it's not that simple.
Immediate thoughts after reading the above comment: Yeah, whether or not to reflect the state of modals in the url is the part I'm most torn on. I think I'm leaning towards "no", and saying that interactions that should be tracked by url should probably not be placed in a model, but put in a custom tab or something, instead.
But tabs should definitely be tracked by the url. Again, we can build it so that going from search to a company, then clicking through a few tabs, and then clicking the browser back button, would take you back to search in one click.
I think we should also track the state of the related-view in the url… but the tabs are probably more important.
I think this discussion is getting slightly off topic.
I know full-screen apps are in the making and that might actually solve the problem that was first addressed. Maybe after that we can go back to using modals for what they are good at: consent to cookies, sign up to newsletters and prompting the user to install the latest version of iOS. Do it NOW!
I'm closing this and opening a new discussion related to navigation. https://github.com/Lundalogik/crm-feature/issues/1771
Current behavior
The current max-width given by limel-dialog is wasting valuable pixels on mobiles, making it really hard to create a good UI. On tablets etc it looks silly with the current max-width. The fullscreen mode does not mean fullscreen as it is right now. It means 100% - 2rem of the viewport.
The default size of a dialog should be much wider on a phone layout and narrower on tablets and up. By fixing this it would remove the need of custom styles with different dialog sizes everywhere, since the defaults would often be good enough.
Examples showing max-width for "fullscreen" mode:
Expected behavior
fullscreen={true}
should mean 100% of the viewport width and heightEnvironment