Add hoist prop; fixes #179

pull/186/head
Cory LaViska 2020-08-25 17:07:28 -04:00
rodzic 7d5aac4bc8
commit b8f52e48ec
7 zmienionych plików z 94 dodań i 4 usunięć

Wyświetl plik

@ -2,6 +2,7 @@
## 2.0.0-beta.16
- Add `hoist` prop to `sl-color-picker`, `sl-dropdown`, and `sl-select` to work around panel clipping
- Add `sl-format-bytes` utility component
- Add `clearable` and `required` props to `sl-select`
- Add `slClear` event to `sl-input`

Wyświetl plik

@ -87,4 +87,38 @@ The offset of the panel along the trigger can be customized using the `skidding`
</sl-dropdown>
```
### Hoisting
Dropdown panels will be clipped if they're inside a container that has `overflow: auto|hidden`. The `hoist` attribute forces the panel to use a fixed positioning strategy, allowing it to break out of the container. In this case, the panel will be positioned relative to its containing block, which is usually the viewport unless an ancestor uses a `transform`, `perspective`, or `filter`. [Refer to this page](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed) for more details.
```html preview
<div class="dropdown-hoist">
<sl-dropdown>
<sl-button slot="trigger" caret>No Hoist</sl-button>
<sl-menu>
<sl-menu-item>Item 1</sl-menu-item>
<sl-menu-item>Item 2</sl-menu-item>
<sl-menu-item>Item 3</sl-menu-item>
</sl-menu>
</sl-dropdown>
<sl-dropdown hoist>
<sl-button slot="trigger" caret>Hoist</sl-button>
<sl-menu>
<sl-menu-item>Item 1</sl-menu-item>
<sl-menu-item>Item 2</sl-menu-item>
<sl-menu-item>Item 3</sl-menu-item>
</sl-menu>
</sl-dropdown>
</div>
<style>
.dropdown-hoist {
border: solid 2px var(--sl-color-gray-80);
padding: var(--sl-spacing-medium);
overflow: hidden;
}
</style>
```
[component-metadata:sl-dropdown]

24
src/components.d.ts vendored
Wyświetl plik

@ -243,6 +243,10 @@ export namespace Components {
* The format to use for the display value. If opacity is enabled, these will translate to HEXA, RGBA, and HSLA respectively. The color picker will always accept user input in any format (including CSS color names) and convert it to the desired format.
*/
"format": 'hex' | 'rgb' | 'hsl';
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with `overflow: auto|scroll`.
*/
"hoist": boolean;
/**
* Set to true to render the color picker inline rather than inside a dropdown.
*/
@ -359,6 +363,10 @@ export namespace Components {
* Hides the dropdown panel
*/
"hide": () => Promise<void>;
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with `overflow: auto|scroll`.
*/
"hoist": boolean;
/**
* Indicates whether or not the dropdown is open. You can use this in lieu of the show/hide methods.
*/
@ -742,6 +750,10 @@ export namespace Components {
* Set to true to disable the select control.
*/
"disabled": boolean;
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with `overflow: auto|scroll`.
*/
"hoist": boolean;
/**
* Set to true to indicate that the user input is invalid.
*/
@ -1533,6 +1545,10 @@ declare namespace LocalJSX {
* The format to use for the display value. If opacity is enabled, these will translate to HEXA, RGBA, and HSLA respectively. The color picker will always accept user input in any format (including CSS color names) and convert it to the desired format.
*/
"format"?: 'hex' | 'rgb' | 'hsl';
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with `overflow: auto|scroll`.
*/
"hoist"?: boolean;
/**
* Set to true to render the color picker inline rather than inside a dropdown.
*/
@ -1697,6 +1713,10 @@ declare namespace LocalJSX {
* The distance in pixels from which to offset the panel away from its trigger.
*/
"distance"?: number;
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with `overflow: auto|scroll`.
*/
"hoist"?: boolean;
/**
* Emitted after the dropdown closes and all transitions are complete.
*/
@ -2108,6 +2128,10 @@ declare namespace LocalJSX {
* Set to true to disable the select control.
*/
"disabled"?: boolean;
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with `overflow: auto|scroll`.
*/
"hoist"?: boolean;
/**
* Set to true to indicate that the user input is invalid.
*/

Wyświetl plik

@ -64,6 +64,12 @@ export class ColorPicker {
/** Set to true to disable the color picker. */
@Prop() disabled = false;
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with
* `overflow: auto|scroll`.
*/
@Prop() hoist = false;
/** Whether to show the opacity slider. */
@Prop() opacity = false;
@ -736,6 +742,7 @@ export class ColorPicker {
class="color-dropdown"
aria-disabled={this.disabled}
containingElement={this.host}
hoist={this.hoist}
onSlShow={this.handleDropdownShow}
onSlAfterShow={this.handleDropdownAfterShow}
onSlHide={this.handleDropdownHide}

Wyświetl plik

@ -63,6 +63,12 @@ export class Dropdown {
/** The distance in pixels from which to offset the panel along its trigger. */
@Prop() skidding = 0;
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with
* `overflow: auto|scroll`.
*/
@Prop() hoist = false;
/** Emitted when the dropdown opens. Calling `event.preventDefault()` will prevent it from being opened. */
@Event() slShow: EventEmitter;
@ -80,11 +86,17 @@ export class Dropdown {
this.open ? this.show() : this.hide();
}
@Watch('placement')
@Watch('distance')
@Watch('hoist')
@Watch('placement')
@Watch('skidding')
handlePopoverOptionsChange() {
this.popover.setOptions({ placement: this.placement });
this.popover.setOptions({
strategy: this.hoist ? 'fixed' : 'absolute',
placement: this.placement,
distance: this.distance,
skidding: this.skidding
});
}
connectedCallback() {
@ -102,9 +114,10 @@ export class Dropdown {
componentDidLoad() {
this.popover = new Popover(this.trigger, this.panel, {
strategy: this.hoist ? 'fixed' : 'absolute',
placement: this.placement,
skidding: this.skidding,
distance: this.distance,
skidding: this.skidding,
onAfterHide: () => this.slAfterHide.emit(),
onAfterShow: () => this.slAfterShow.emit(),
onTransitionEnd: () => {

Wyświetl plik

@ -65,6 +65,12 @@ export class Select {
/** The select's size. */
@Prop() size: 'small' | 'medium' | 'large' = 'medium';
/**
* Enable this option to prevent the panel from being clipped when the component is placed inside a container with
* `overflow: auto|scroll`.
*/
@Prop() hoist = false;
/** The value of the control. This will be a string or an array depending on `multiple`. */
@Prop({ mutable: true }) value: string | Array<string> = '';
@ -333,6 +339,7 @@ export class Select {
<sl-dropdown
part="base"
ref={el => (this.dropdown = el)}
hoist={this.hoist}
closeOnSelect={!this.multiple}
containingElement={this.host}
class={{

Wyświetl plik

@ -33,6 +33,7 @@ export default class Popover {
skidding: 0,
distance: 0,
placement: 'bottom-start',
strategy: 'absolute',
visibleClass: 'popover-visible',
onAfterShow: () => {},
onAfterHide: () => {},
@ -85,6 +86,7 @@ export default class Popover {
this.popper = createPopper(this.anchor, this.popover, {
placement: this.options.placement,
strategy: this.options.strategy,
modifiers: [
{
name: 'flip',
@ -123,7 +125,8 @@ export default class Popover {
// Update popper options
if (this.popper) {
this.popper.setOptions({
placement: this.options.placement
placement: this.options.placement,
strategy: this.options.strategy
});
requestAnimationFrame(() => this.popper.update());
@ -150,6 +153,7 @@ export interface PopoverOptions {
| 'left-start'
| 'left-end';
skidding?: number;
strategy?: 'absolute' | 'fixed';
visibleClass?: string;
onAfterShow?: () => any;
onAfterHide?: () => any;