Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Add smart/fixed positioning option for components with dropdowns/popups and for tooltips/popovers #4762

Open
3 of 5 tasks
icfantv opened this issue Oct 28, 2015 · 32 comments · Fixed by #4899
Open
3 of 5 tasks

Comments

@icfantv
Copy link
Contributor

icfantv commented Oct 28, 2015

In an effort to give users more flexibility to dictate where popups and tooltips/popovers we need to add the ability let them specify where and how they want the item to be displayed.

Supported Locations - Top, Right, Bottom, Left, Top Left, Top Right, Bottom Left, and Bottom Right.

Smart Positioning - when used, implies that the library will determine the best location for the item.

Fixed Positioning - will display the item at the specified location.

Hybrid Positioning - exact behavior TBD, but maybe something like letting the user specify a fixed position and if it doesn't fit, use smart positioning. Or perhaps, letting the user specify an array of positions to try before using smart positioning.

Supported Components:

  • Datepicker
  • Dropdown (smart, top and bottom positioning only)
  • Popover
  • Tooltip
  • Typeahead (smart, top and bottom positioning only)
@RobJacobs
Copy link
Contributor

#3900 is a good start and should be used for reference.

@icfantv
Copy link
Contributor Author

icfantv commented Oct 28, 2015

Looks like #4293 may also be a good point of reference.

@RobJacobs
Copy link
Contributor

This comment relates specifically to how TWBS positions the dropdown component, I plan to follow up in another comment on pixel positioning (tooltip).

TWBS uses 2 approaches to positioning an element relative to another element with the major differences being the markup used and the top/left style values used. This approach relies more on css to keep the linked element positioned and is used with the dropdown component. The following is the basic markup used to create a button with a dropdown:

<div class="dropdown">
  <button> Dropdown </button> 
  <ul class="dropdown-menu"> 
    <li><a href="#">Action</a></li>
  </ul>
</div> 

The relevant positioning css applied by the dropdown and dropdown-menu classes is:

<div style="position: relative;">
  <button> Dropdown </button> 
  <ul style="position: absolute; top: 100%; left: 0"> 
    <li><a href="#">Action</a></li>
  </ul>
</div> 

What this does is let the outer element’s size control where the position of the dropdown menu will appear by setting up a relative position boundary and using absolute positioning on the dropdown-menu element. The outer element’s height will grow if the button size changes thus automatically altering where the dropdown gets positioned. If the outer element has display: inline-block the width will work in the same manner. The top: 100% puts the dropdown-menu elements top edge at 100% the height of its nearest positioned ancestor (the outer dropdown div). The dropup class simply sets bottom: 100% instead and the dropdown-menu element will appear on top of the outer element instead of underneath. Extending this approach to position the dropdown-menu element in any quadrant is as simple as applying 100% to the correct css attribute.

Pros:

  • Puts the burden of positioning the linked element on css, no need to worry about scrolling,
    element resize, etc...

Cons:

  • Requires strict markup.
  • Requires css not included in TWBS.
  • Will not work with append-to-body.

The following lists those values as well as suggested reset values:

top-left        { top: auto; bottom: 100%; left: 0; right: auto; }
top-right       { top: auto; bottom: 100%; left: auto; right 0; }
bottom-left     { top: 100%; bottom: auto; left: 0; right: auto; }
bottom-right    { top: 100%; bottom: auto; left: auto; right: 0; }
left-top        { top: 0; bottom: auto; left: auto; right: 100%; }
left-bottom     { top: auto; bottom: 0; left: auto; right: 100%; }
right-top       { top: 0; bottom: auto; left: 100%; right: auto; }
right-bottom    { top: auto; bottom: 0; left: 100%; right: auto; }

To center, a transform can be used:

vertical-center   { top: 50%; bottom: auto; transform: translate(0, -50%); }
horizontal-center { left: 50%; right: auto; transform: translate(-50%, 0); }

And with the appropriate primary position:

top-center    { top: auto; bottom: 100%; left: 50%; right: auto; transform: translate(-50%, 0); }
bottom-center { top: 100%; bottom: auto; left: 50%; right: auto; transform: translate(-50%, 0); }
left-center   { top: 50%; bottom: auto; transform: translate(0, -50%); left: auto; right: 100%; }
right-center  { top: 50%; bottom: auto; transform: translate(0, -50%); left: 1005; right: auto; }

This Plunk demos this approach and has the styles refactored into mixins in the placements.less file.

TWBS only offers 2 different positions on the dropdown - top or bottom accomplished by using the dropdown or dropup class on the parent element.

The Dropdown directive is the only directive that uses the dropdown class with a nested dropdown-menu class in it's template. Datepicker and typeahead use the dropdown-menu class in their templates but are not nested in an element with the dropdown class. We need to be careful when using the dropdown-menu class as it adds the following styles that will affect positioning:

position: absolute;
top: 100%;
left: 0;
display: none; // none by default, but block on "open" of the menu
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0; // override default ul

@icfantv
Copy link
Contributor Author

icfantv commented Jan 15, 2016

@deeg, you've been pretty active and have some quality commits. we are more than happy to have you work on stuff. ping me on the angular slack or gitter and i can walk you through setting up your own fork and having it linked with our main repo.

@deeg
Copy link
Contributor

deeg commented Jan 15, 2016

@icfantv, that is already done, just wanted to make sure the other directives hadn't been started by someone else yet. I will look into datepicker in the next few days, possibly next week.

@icfantv
Copy link
Contributor Author

icfantv commented Jan 15, 2016

Oh, ok. you'll need to check with @RobJacobs as he did the initial work for tooltips and popovers. I strongly suspect that the rest of this has not yet been started.

Oh, and by the way, you rock.

For typeahead and dropdown - I would only support smart, top, and bottom positioning. For the datepicker, probably the same, but I'd like to hear an argument for supporting E, W, or corners before ruling it out. Personally, I don't think it makes sense, but I'm just one man.

You can use what @RobJacobs did for tooltips/popovers to get you started - most of the work may already be done.

@deeg
Copy link
Contributor

deeg commented Jan 15, 2016

Thanks for the info @icfantv.

I agree with you that E, W, and corners does not make sense for typeahead or datepicker.

@anasqadrei
Copy link

Hey just wanted to make sure that I could align typeahead right because I'm using it for an Arabic list

@icfantv
Copy link
Contributor Author

icfantv commented Jan 16, 2016

@anasqadrei, please do not hijack threads by changing the subject. Questions like yours are best served by the community by asking on StackOverflow. That said, I believe it's the browser's responsibility to take the font you're using and render it correctly.

@anasqadrei
Copy link

@icfantv, I've created issue #2753 which was closed in favour of this issue and is referenced here.

@icfantv
Copy link
Contributor Author

icfantv commented Jan 17, 2016

@anasqadrei, and have you tied an RTL font yet with the latest code base?

@anasqadrei
Copy link

@icfantv, yes. Here is a plunker with the latest codebase(ui-bootstrap 1.0.3, angular 1.4.8, bootstrap 3.3.6) http://plnkr.co/fs79igc1fJWTqY4xrWTt

Copy the RTL text وا and paste it in the textbox. You will see the text in the textbox is aligned to the right but the dropdown is aligned to the left. They both should be aligned right.

@icfantv
Copy link
Contributor Author

icfantv commented Jan 18, 2016

@anasqadrei, cool, thanks for the plunker. Please create a new issue for this so we can track it. Thanks.

@icfantv
Copy link
Contributor Author

icfantv commented Jan 18, 2016

@anasqadrei. so, shocker...i don't have an arabic keyboard so if you could maybe just paste a translation of the characters so we can try to reproduce that would be helpful. I suppose I could also try with Hebrew as that should suffer from the same problem. Thanks.

@anasqadrei
Copy link

@icfantv, I've updated the plunker so you could type in English characters. Type "o" or "on" for example. Hebrew would also work. I've aligned everything in the html body to RTL anyway.

Issue #2753 was already created with similar plunkers. It was closed in favour of this issue (#4762)

@icfantv
Copy link
Contributor Author

icfantv commented Jan 18, 2016

@anasqadrei, ok, I see it now. you're just wanting the dropdown typeahead box to be right justified? Please do open a new issue for this. I think we may be able to fix this without waiting for a new position service. Thanks.

@gercheq
Copy link

gercheq commented Apr 2, 2016

Just add .dropdown-menu-right http://getbootstrap.com/components/#dropdowns-alignment

ie.

      <ul uib-dropdown-menu class="dropdown-menu-right" aria-labelledby="Select Your Language">
          <li ng-repeat="lang in languages">
              <a ng-click="changeLanguage(lang.key)" href="#">{{ lang.text }}</a></li>
          </li>
      </ul>

@evilaliv3
Copy link

i would suggest that for all related rtl stuff you should take a look at this commit MohammadYounes/RTL-bootstrap@3be91ac in particular to the code used by @MohammadYounes in order to easily handle the positioning of tooltips.

The solution there implemented makes use of the standard https://www.w3.org/International/questions/qa-html-dir

https://mohammadyounes.github.io/RTL-bootstrap/inline/

@evilaliv3
Copy link

is someone aware of any workaround for this?

@wesleycho ?

@byronigoe
Copy link

Why is this issue still open? It appears that "auto" handles the smart positioning, by swapping left/right and top/bottom when there's not enough room. What is left to implement for position?

@Js41637
Copy link

Js41637 commented Mar 1, 2017

The auto positioning is great however similar to the initial Hybrid mode, being able to specify a preferred position (as it seems to default to top?) would be great.

@byronigoe
Copy link

@Js41637 You can specify a preferred position, e.g. "auto bottom-right". Again, I believe everything in this request has been implemented.

@Js41637
Copy link

Js41637 commented Mar 1, 2017

I tried putting auto bottom and it only added it to the bottom?

@byronigoe
Copy link

@Js41637 I created a Plunker to test "auto bottom", and when there isn't space on the bottom, it moves the popup to the top. Add more BR tags to line 27 if your monitor is a higher resolution:
https://plnkr.co/edit/oJykYhAHaTBJF6GQaMo3?p=preview

@xReeQz
Copy link

xReeQz commented May 22, 2017

As I can see typeahead now supports smart positioning. Can anyone tell me how I can use it? I'd like it to open up automatically when there's no space at the bottom.

@Ansrala
Copy link

Ansrala commented Oct 4, 2017

@icfantv Is this issue dead? Because I would much love an auto positioning for dropdowns.

@adamcbuckley
Copy link

If anyone else ended up here because they want to a uib-typeahead list to appear above the input field, then this is the workaround I use.

It seems that Bootstrap 3 already defines this:

.dropup .dropdown-menu {
    top: auto;
    bottom: 100%;
    margin-bottom: 2px;
}

However uib-typeahead creates a ul.dropdown-menu with a style (on the element) which overrides the top property defined by Bootstrap. Therefore in your own CSS file add the following rule:

.dropup .dropdown-menu {
    top: auto !important;
}

The parent of your HTML input field should have the dropup class:

<div class="dropup">
    <input type="text" data-uib-typeahead="..."/>
</div>

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.